Direct Minting Troubleshooting
Use this page as a Developer Hub reference for FXRP direct minting. The tables below are a one-screen summary; later sections add prevention steps, tag and executor edge cases, and smart-account routing.
Before You Send XRP
Validate these before submitting an XRPL payment. Mistakes here are often irreversible.
| Check | How to verify | If wrong |
|---|---|---|
| Core Vault address | directMintingPaymentAddress() | Payment not recognized; mint reverts with InvalidReceivingAddress |
| Amount ≥ minimum fee | getDirectMintingMinimumFeeUBA() | Entire payment goes to fee receiver; minter receives 0 FXRP (DirectMintingPaymentTooSmallForFee) |
| Recipient encoding | Tag via MintingTagManager, or 32-byte / 48-byte memo (see memo field) | FXRP may mint to the wrong address or route via smart accounts |
| Memo format | 32-byte: DIRECT_MINTING prefix + recipient. 48-byte: DIRECT_MINTING_EX + recipient + executor (see Direct Mint FXRP guide) | Unrecognized memo → smart account path |
| Not a donation | Do not use the Core Vault donation destination tag | Reverts with PaymentIsCoreVaultDonation |
| Not a redemption reference | Do not reuse agent redemption memos | Reverts with ForbiddenPaymentReference |
Irreversible Failures
These do not revert. Funds are consumed or sent to the wrong place.
The failures below succeed on-chain from the protocol's perspective. Prevention is the only remedy.
1. Payment below the minimum minting fee
- Cause:
receivedAmount < getDirectMintingMinimumFeeUBA() - Result: Full XRP amount minted as fee to
getDirectMintingFeeReceiver(). Minter and executor receive nothing. - Event:
DirectMintingPaymentTooSmallForFee - Prevention: Always send
amount ≥ getDirectMintingMinimumFeeUBA()plus your intended mint amount.
2. Wrong recipient in memo or tag
- Cause: Incorrect EVM address in 32-byte memo, 48-byte
DIRECT_MINTING_EXmemo, orsetMintingRecipient() - Result: FXRP mints to the encoded address. No recovery on-chain.
- Prevention: Double-check recipient address. Prefer destination tags with a registered recipient over raw memo encoding.
3. Payment sent to the wrong XRPL address
- Cause: User sends XRP to an address other than
directMintingPaymentAddress() - Result:
InvalidReceivingAddresson execution; XRP is outside the FAssets system. - Prevention: Always fetch the address from the contract at runtime. Do not hardcode.
4. Unrecognized memo routes to smart accounts
- Cause: Missing memo, invalid tag, or memo that does not match
DIRECT_MINTING/DIRECT_MINTING_EX/ registered tag - Result: FXRP is minted to
SmartAccountManager, not directly to your wallet. - Event:
DirectMintingExecutedToSmartAccount - Prevention: Use a supported encoding path, or confirm smart account routing is intended. See Smart Account Path below.
Execution Reverts
Call executeDirectMinting or executeDirectMintingWithData only after the XRPL payment is finalized and attested.
| Error | Cause | Resolution |
|---|---|---|
InvalidReceivingAddress | Proof shows payment not to Core Vault | Verify XRPL destination address |
AmountNotPositive | Zero-amount payment | Send a positive amount |
PaymentFailed | Underlying transaction failed on XRPL | Retry payment on XRPL |
MissingMintingTagManager | Tag manager not configured | Wait for governance setup; direct minting unavailable |
MissingSmartAccountManager | Smart account manager not configured | Same as above |
InvalidExecutor | Caller is not the allowed executor, and exclusive window not expired | Use allowed executor, or wait getDirectMintingOthersCanExecuteAfterSeconds() |
OnlyProofOwner | FDC proof proofOwner ≠ msg.sender | Executor who paid for attestation must submit the proof, or request proof with proofOwner = address(0) |
DirectMintingStillDelayed | Rate limit or large-mint delay not elapsed | Wait until executionAllowedAt from directMintingDelayState(txId) |
PaymentAlreadyConfirmed | Same payment executed twice | Normal — mint already completed |
MintingCapExceeded | Global FAsset supply cap reached | Retry later or wait for cap increase |
PaymentIsCoreVaultDonation | Core Vault donation tag used | Use confirmCoreVaultDonation instead |
ForbiddenPaymentReference | Redemption-style memo detected | Use a valid direct-minting memo or tag |
NoDataExpectedForDirectMinting | executeDirectMintingWithData used for tag/memo/direct path | Use executeDirectMinting instead |
NoValueExpected | Non-zero msg.value on direct-recipient path | Send native tokens only on smart-account path |
EmergencyPauseActive | System emergency pause | Wait for unpause |
LegalPaymentNotProven / TransactionNotProven | Invalid or unverifiable FDC proof | Regenerate proof after finalization |
Delays
Rate limits delay minting; they do not permanently reject it.
| Trigger | Setting | Event |
|---|---|---|
| Hourly cap exceeded | getDirectMintingHourlyLimitUBA() | DirectMintingDelayed |
| Daily cap exceeded | getDirectMintingDailyLimitUBA() | DirectMintingDelayed |
| Large mint | getDirectMintingLargeMintingThresholdUBA() + getDirectMintingLargeMintingDelaySeconds() | LargeDirectMintingDelayed |
Retry steps:
- Listen for
DirectMintingDelayedorLargeDirectMintingDelayed. - Read
directMintingDelayState(transactionId)→allowedAt. - Re-submit the same FDC proof with
executeDirectMintingafterallowedAt. - If governance unblocks mints, watch for
DirectMintingsUnblockedand checkgetDirectMintingsUnblockUntilTimestamp(). Optionally callmarkUnblockedDirectMintingAllowed(transactionId)to reset the executor exclusive window.
Notes
- Recipient and executor are frozen at delay creation. Tag transfers during a delay cannot redirect funds.
- Attached native value (
msg.value) is returned to the executor if minting is delayed. - Minting capacity is reserved during a delay and counts toward
MintingCapExceeded.
For off-chain pre-flight logic, see Check Direct Minting Limits and rate limits.
Executor and Proof of Ownership
Preferred executor
Set via:
- Tag:
MintingTagManager.setAllowedExecutor(tagId, executor) - Memo: 48-byte
DIRECT_MINTING_EXformat (recipient + executor)
If allowedExecutor ≠ address(0):
- Only that address can execute initially.
- After
getDirectMintingOthersCanExecuteAfterSeconds()from the payment timestamp (or fromallowedAtfor delayed mints), anyone may execute and receive the executor fee.
FDC Proof Ownership
If the attestation request sets proofOwner to a specific address, only that address can call executeDirectMinting.
Use proofOwner = address(0) for open execution.
Minting Tag Manager Pitfalls
| Mistake | Error / behavior |
|---|---|
Wrong fee on reserve() | WrongReservationPaymentAmount |
| Non-owner sets recipient | OnlyTagOwner |
Recipient set to address(0) | ZeroAddress |
| Tag transferred | Recipient resets to new owner; executor cleared immediately |
| Executor changed | Cooldown before new executor is active — query pendingAllowedExecutorChange(tagId) |
See Minting Tag Manager and Transfer a Minting Tag.
Smart Account Path
Use this path only when intentional.
| Rule | Detail |
|---|---|
| When used | No memo, unrecognized memo, or unregistered destination tag |
| Execution | executeDirectMintingWithData(proof, data) — data verified by smart account manager |
| Native value | msg.value forwarded to smart account manager (e.g., for composed redeem flows) |
| Executor fee | Set by smart account manager, not AssetManager |
| Direct path | Do not use WithData or attach msg.value for tag/memo/direct mints |
If smart-account execution reverts, FXRP is not minted and XRP remains at the Core Vault. See Failure Handling and Recover Stuck Mint Transaction.
Fee Reference
| Fee | Getter |
|---|---|
| Minimum minting fee | getDirectMintingMinimumFeeUBA() |
| Percentage minting fee | getDirectMintingFeeBIPS() |
| Executor fee (direct path) | getDirectMintingExecutorFeeUBA() |
Minted amount (direct path):
receivedAmount - mintingFee - executorFee
Minting fee = max(percentage, minimum), capped at receivedAmount.
The executor fee is taken from the remainder.
Pre-flight Checklist
- Core Vault address from
directMintingPaymentAddress() - Amount >
getDirectMintingMinimumFeeUBA() - Recipient encoded correctly (tag or memo)
- Executor set if exclusivity is required
- Hourly/daily/large-mint limits checked
- FDC proof obtained after XRPL finalization
- Correct execute method (
WithDataonly for smart account path) - Emergency pause not active
Monitoring Events
| Event | Meaning |
|---|---|
DirectMintingExecuted | Success — mint to recipient |
DirectMintingExecutedToSmartAccount | Success — mint via smart accounts |
DirectMintingDelayed | Hourly/daily rate limit; retry after executionAllowedAt |
LargeDirectMintingDelayed | Large mint above threshold; retry after executionAllowedAt |
DirectMintingPaymentTooSmallForFee | Payment consumed as fee; no user mint |
DirectMintingsUnblocked | Governance bypassed hourly/daily limiter until startedUntilTimestamp |
- Direct Mint FXRP · Direct Mint with Tag · Check Direct Minting Limits
- Protocol overview: Direct Minting · Minting · Redemption