Mint replay, idempotency, and supply controls
How DALP keeps EVM mint retries tied to one queued transaction while preserving nonce ordering, signer approval, and per-asset supply controls.
DALP treats a mint as one approved business instruction that becomes a signed EVM transaction. The workflow starts with an authenticated mint request, checks the caller, wallet route, and per-asset Supply Management role, queues the transaction with a scoped idempotency key, applies signer or custody approval, executes mint or batchMint on the EVM asset contract, and exposes the outcome through transaction status, indexed state, and webhooks.
For assets that use the SMART capped extension, the maximum supply cap is a storage value, not a hard-coded bytecode constant. The capped extension stores the cap in the private _cap variable, exposes it through cap(), and updates it through setCap(uint256 newCap) when an account with the Governance role is allowed to change the cap. setCap rejects zero values and values below current totalSupply; the mint hook rejects mints where totalSupply + amount would exceed cap().
Retry safety uses the HTTP Idempotency-Key, DALP's transaction queue, wallet-route fingerprinting, ordered EVM nonce handling, and transaction outcome reconciliation. DALP does not add a separate unique on-chain operation ID for each approved mint instruction. The on-chain execution identity remains the signed EVM transaction: signer, nonce, calldata, target contract, value, and chain ID.
For the request shape, see Mint assets.
Reader decisions
| Reader | Use this page to decide |
|---|---|
| Operations lead | How to handle retries, signer approvals, status checks, and reconciliation in a mint runbook |
| Risk or compliance reviewer | Which controls prevent duplicate mints or unauthorized supply changes |
| API integrator | How to choose idempotency keys and when a retry needs a new key |
| Asset issuer | Which duties DALP enforces and which stay with the institution |
One-view control map
The key point is simple: the idempotency key, transaction queue, nonce lane, signer approval, and asset contract each answer a different question. None of them replaces the others.
Control layers
| Layer | What it protects | Primary control | What it does not prove |
|---|---|---|---|
| API request | Duplicate client retries | Idempotency-Key tied to tenant, route, method, and request body | Final chain state |
| Mint route | Operation-specific replay | Mint operation kind, signing wallet, chain ID, and scoped retry key | Legal approval for the mint |
| Transaction queue | Duplicate transaction submission | Existing transaction request for the same scoped key and route | That a changed payload is safe to treat as the same instruction |
| Nonce lane | Concurrent sends from one signing address | Ordered nonce use per signing address and EVM chain | That the business instruction is approved |
| Authorization | Unauthorized supply changes | User authentication, organization scope, wallet verification, and per-asset Supply Management role | That the recipient passes every on-chain rule |
| Signer or custody policy | Signature release | Configured signer, HSM, or custody approval route | That the chain will accept the mint |
| Asset contract | Invalid mint execution | EVM role checks and configured compliance modules | Off-chain reserve, cash, or subscription sufficiency unless represented by configured controls |
| Reconciliation | Outcome visibility | Transaction status, indexed asset state, and webhook events | That the first HTTP response is the final chain outcome |
Supply integrity controls
DALP prevents over-issuance through the controls that are active on the asset, not through a separate hidden mint governor. A mint can proceed only when the caller has the per-asset Supply Management role, the asset is not paused, the recipients and amounts pass request validation, the signing route is authorised, and the EVM asset contract accepts the mint.
Configured contract controls enforce the supply limit at execution time:
- Assets with a supply cap reject mints that would push
totalSupplyabove the configured maximum. - Assets with collateral enforcement reject mints when the recorded collateral claim does not cover the post-mint supply under the configured ratio.
- Assets with an issuance-volume limit reject mints that would exceed the configured token-unit quota for the active fixed or rolling period.
DALP-level stop controls depend on the layer that owns the risk. The asset pause check blocks further mints for the paused asset. The issuance-volume limit acts as the automatic abnormal-volume circuit breaker when abnormal minting is defined as a fixed or rolling token-unit quota.
Custody policy can add transaction amount limits, rolling spend limits, approval workflows, and destination allowlists before a signature is released. API and queue controls prevent duplicate submission and unsafe retry behaviour before the transaction reaches the chain.
If an institution needs controls beyond the configured asset modules and custody policy, keep them outside the generic mint path. Examples include treasury release approvals, anomaly rules that are not expressed as token-unit issuance quotas, or off-chain reserve checks that are not represented by DALP controls. Model those controls as operating policy or a project-specific integration around the mint API.
For "submitted but not confirmed" mints, treat the queued transaction as pending until transaction tracking, indexed asset state, or webhooks show the outcome. Do not send a changed mint with the same idempotency key. Do not issue a fresh key for the same business instruction until you have reconciled the previous transaction. During congestion, partial infrastructure failure, or a reorg, the safe record is the transaction status plus the indexed totalSupply, not the first HTTP response.
Idempotency and replay controls
DALP separates client retry safety from signer and chain replay safety.
For ordinary idempotent HTTP mutations, the Idempotency-Key protects the request by binding the key to the tenant, method, route, and canonical request body. A repeated request with the same key and same body can reuse the cached response during the cache window. A repeated request with the same key and a different body, route, or method is rejected as key reuse.
Minting adds a transaction queue control. The mint endpoint encodes a single-recipient call as mint and a batch call as batchMint, then passes both through the queue kind token.mint. DALP scopes the incoming Idempotency-Key as {key}-token_mint before the queue persists or reattaches to a transaction request. This queue match does not compare token address, recipients, or amounts; clients must use a new key when any mint payload field changes.
Before persisting or reattaching, the queue resolves the signing wallet, EVM chain, scoped key, and wallet-selection fingerprint. A retry with the same key reuses the same queued mint only when the sender wallet, chain, operation kind, and wallet route still match. DALP rejects a retry when the resolved wallet route changes in a way that could attach the caller to a transaction submitted from a different signing path.
The wallet-selection fingerprint is based on the canonical smart wallet address and EOA routing flag. If no smart wallet address is present, DALP also uses the selected account wallet row.
An honest retry can survive internal wallet-row resolution when the route still points to the same address. A retry that changes the actual signing address, account-wallet-only route, or EOA routing must use a new key.
| Control point | Stable input | Duplicate behavior | Changed input behavior |
|---|---|---|---|
| Mint route | Idempotency-Key, token.mint, signing wallet, and chain ID | Reattaches to the existing queued transaction | Treats the key as the same queued mint while wallet routing is unchanged |
| Transaction queue | Sender wallet, chain ID, scoped key, and wallet-selection fingerprint | Reuses or tracks the existing transaction request | Rejects a retry that changes the effective signing address, account-wallet-only route, or EOA routing |
| EVM transaction | Signing address, nonce, calldata, target contract, value, and chain ID | Reconciliation uses transaction status and events | The chain treats changed calldata, nonce, or target as a different transaction |
The EVM transaction has its own identity: signing address, nonce, calldata, target contract, value, and chain ID. If calldata, nonce, target, or signer changes, the chain sees a different transaction. DALP therefore treats the idempotency key as a client and queue control, not as a substitute for transaction status checks.
Nonce and chain replay controls
DALP serialises EVM sends by signing wallet and chain. The nonce lane is scoped to the wallet address and EVM chain ID, so concurrent mint requests from the same signing address do not independently guess or reuse the next account nonce.
When DALP prepares and signs locally, the sign and broadcast steps are journaled separately. If broadcast succeeds but the workflow replays before recording the result, DALP reuses the same signed bytes and recovers the already-known transaction hash instead of signing a replacement with the same nonce. If the node reports that the nonce is already consumed, DALP reads the pending on-chain nonce, advances the tracked nonce, and retries from the later nonce.
When a custody provider signs a prepared transaction, DALP validates the signed transaction before broadcast. The parsed transaction must match the original approval request for nonce, target contract, calldata, chain ID, recovered signer, and value when value is present. DALP rejects a mismatch before broadcast. That keeps the approval flow tied to the reserved nonce and intended chain.
| Replay or recovery case | DALP control | Integrator expectation |
|---|---|---|
| Same wallet, concurrent EVM sends | Ordered nonce lane per signing address and chain ID | Submit through the DALP transaction queue instead of broadcasting from a separate system with the same signing wallet |
| Stuck or replayed local broadcast | Reuse the same signed bytes, recover already-known hashes, and sync from the pending on-chain nonce on nonce errors | Check transaction status before creating a new mint instruction |
| Signed transaction from custody | Pre-broadcast validation of nonce, target, calldata, chain ID, signer, and value | Treat a mismatch as a failed approval or signing event, not as a transaction to retry blindly |
| EIP-155 chain replay | Chain ID is part of the signed EVM transaction and DALP rejects custody-signed transactions with the wrong chain ID | Keep each mint instruction tied to the intended EVM network |
For stuck transactions, DALP distinguishes whether the transaction reached the chain. Before broadcast, a queued or pending-approval transaction can be cancelled without consuming a nonce. During signing, cancellation is rejected because the nonce may already be in flight. After broadcast, if a transaction has a hash and nonce, cancellation uses a replacement transaction from the same address to itself with zero value and empty calldata. That replacement consumes the same nonce instead of creating a second mint.
For nonce gaps, DALP compares its tracked nonce with the pending on-chain nonce for the signing wallet and chain. When the tracker is ahead of the chain, the gap is detectable as allocated-but-unconfirmed nonce values. Recovery can fill those gaps with no-op self-transfers, or an operator can reset the tracked nonce with an audited reason when manual recovery is required. When the chain is ahead, DALP only advances the tracker; it does not roll the nonce backward.
For outage recovery, DALP keeps transaction state and nonce reservations in the durable workflow path. A reservation that has not been broadcast can be released and compacted back into the nonce lane. A reservation marked as broadcasted is not released back into the lane, because reusing that nonce could replace a live transaction. Sign-only custody approvals keep an explicit reservation until the approval monitor finalises the broadcast or releases the reservation after a permanent failure.
This nonce model protects DALP-managed submissions. It does not protect transactions that bypass DALP and use the same signing wallet directly through another broadcaster. If an institution shares a minting wallet with external tooling, reconcile that external activity before relying on DALP queue state.
Use one stable key for one approved mint instruction. If the recipient, amount, asset, signing route, executor, or wallet route changes, use a new key.
Retry example
A mint request posts to /api/v2/tokens/{tokenAddress}/mints with Idempotency-Key. The route encodes either mint or batchMint, sets the queue kind to token.mint, and wraps the response with a transaction-request status URL. DALP scopes the incoming header as {key}-token_mint; the transaction queue then persists by signing wallet, chain ID, and that scoped key for 24 hours.
| Retry input | Queue result | Client action |
|---|---|---|
| Same key, same signing route, first transaction still running | DALP attaches to the existing workflow and reports the same transaction request | Poll the returned transaction status URL or wait for the subscribed webhook |
| Same key, same signing route, first transaction completed | DALP returns the stored transaction hash and reads the indexed asset state when available | Reconcile the hash and indexed total supply with the business record |
| Same key, different wallet route | DALP rejects the retry as an idempotency conflict | Fix the route mismatch or submit a new approved instruction with a new key |
| Same key after the 24-hour idempotency window | DALP rejects the expired key | Reconcile the earlier transaction before issuing a new mint instruction |
Mint instruction flow
A single-recipient mint calls the asset contract's mint function. A batch mint calls batchMint. Both paths go through the same queue and supply-control model.
When a client loses the HTTP response, the retry should use the same key. The client should then check transaction status or indexed state instead of sending a new key just because the first response was lost.
What the client must do
| Client responsibility | Required practice |
|---|---|
| Generate a stable key | Send one Idempotency-Key for each approved mint instruction. Keep it stable across network retries. |
| Keep the payload stable | Treat token address, recipients, amounts, executor route, and wallet route changes as a new business instruction with a new key. |
| Store the key | Keep the key with the ticket, trade, subscription, or operations record that approved the mint. |
| Check outcome separately | Treat the HTTP response as API acceptance or completion. Reconcile transaction status, indexed asset state, and webhook delivery. |
| Avoid proof by retry | Do not let a repeated HTTP response become the only evidence used by a downstream ledger. |
DALP can process a mutation request without an explicit Idempotency-Key, but the client then has no stable key for a safe retry. Production integrations should send the header themselves.
Mint authorization and supply controls
DALP checks mint authority before signing and the asset contract checks mint rules on-chain.
| Control | Before signing | On-chain | Typical owner |
|---|---|---|---|
| User authentication and organization scope | Yes | No | Institution and DALP deployment |
| API key access scope | Yes | No | Institution |
| Per-asset Supply Management role | Yes | Yes | Asset administrator |
| Wallet verification | Yes | No | Institution |
| Custody or HSM approval policy | During signing | No | Institution or custody provider |
| Paused asset state | Yes | Yes | Emergency role |
| Recipient identity and compliance rules | Checked before execution where configured | Yes | Compliance manager |
| Supply cap and collateral modules | Surfaced through simulation or revert handling | Yes | Governance or compliance manager |
The asset contract can block mints when the asset is paused, the supply cap would be exceeded, a required collateral claim is missing or stale, or the recipient does not satisfy configured identity and eligibility rules.
Access and cap ownership
Minting authority and cap authority are separate:
| Action | Required access | Where DALP enforces it |
|---|---|---|
| Single-recipient mint | Per-asset Supply Management role | Before signing and in the asset contract mint function |
| Batch mint | Per-asset Supply Management role | Before signing and in the asset contract batchMint function |
| Burn or batch burn | Per-asset Supply Management role | In the asset contract burn functions |
Change an asset cap with setCap(uint256 newCap) | Governance role | In capped asset contracts that expose cap updates |
| Add, remove, or configure compliance modules | Governance role | In the asset contract governance functions and compliance module configuration |
| Pause or unpause an asset | Emergency role | In the asset contract pause controls |
A capped asset's cap value is stored as _cap in the SMART capped extension. It is readable through cap(). It is not an immutable contract constant. For asset types that expose setCap, changing the cap is a governance action, not a minting action. The Supply Management role can mint or burn within the current controls, but it does not own cap changes.
For capped assets, the supply-control evidence includes _cap, cap(), setCap, and mint-time cap enforcement. Those controls belong in the SMART core token audit scope when the deployed asset type includes the capped extension. Deployment evidence should still point to the security review or attestation for the specific contract version and network.
The audit trail for a mint should connect the approved business instruction, idempotency key, transaction request, signer or custody approval, EVM transaction hash, on-chain events, indexed totalSupply, and the active cap or collateral state. DALP supplies those operational records. It does not decide whether an institution had enough off-chain cash, subscription evidence, board approval, or reserve documentation unless those requirements are represented by configured DALP controls.
Retry and outcome rules
| Situation | Expected behavior |
|---|---|
| Same key, same request, original still running | DALP reports or waits for the existing queued transaction. |
| Same key, same request, original completed | DALP returns the existing result or reads current state after indexing. |
| Same key, changed mint payload, same wallet route | DALP treats the key as the existing queued mint. Use a new key for the changed instruction. |
| Same key, different wallet or executor route | DALP rejects the retry because it targets a different execution route. |
| Previous transaction failed or was cancelled | Resolve the cause, then retry with a new idempotency key. |
| Client did not receive the HTTP response | Retry with the same key, then check transaction status and indexed asset state. |
| Retry attaches to a completed transaction | Treat the response as the same queued result, not as fresh chain finality. |
The idempotency cache window is 24 hours. After that window, DALP rejects reuse of the expired key; it does not treat a new key as proof that the earlier transaction is safe to ignore. Reconcile the earlier transaction before sending another mint instruction with a new key. If the earlier transaction is still active and should not execute, cancel it before broadcast or use the post-broadcast cancellation path instead of issuing a duplicate mint.
What DALP does not decide
DALP's replay and idempotency controls do not replace institutional approval policy.
| Outside this control model | Required owner |
|---|---|
| Legal approval for a mint | Institution and counsel |
| Off-chain cash, collateral, or subscription evidence unless represented by configured DALP controls | Institution |
| External ledger posting | Integration owner |
| Custody-provider approval matrix | Institution and custody provider |
| Chain finality before the configured finality process completes | Chain operations and reconciliation process |
DALP's mint path is EVM-only. These controls cover EVM transactions. They do not cover bridge settlement or replay protection for non-EVM networks.
Operational checklist
| Before minting | During retry | After completion |
|---|---|---|
| Confirm token address, EVM chain, recipients, amounts, and decimals. | Reuse the same key only for the same mint instruction. | Record transaction hash, status, and indexed total supply. |
| Confirm the Supply Management role and wallet verification method. | Keep the executor and wallet route unchanged under the same key. | Reconcile webhooks or transaction status with the business record. |
| Confirm cap, collateral, pause, and recipient eligibility controls. | If the request is still in flight, wait or poll status instead of issuing a new key. | Investigate retry responses separately from final chain outcome. |
Where to go next
- Mint assets for the API request shape
- Signing flow for custody and approval sequencing
- Per-asset RBAC for the Supply Management role
- Supply Cap & Collateral for mint-specific cap and reserve-backed controls
- Issuance Volume Limit for fixed or rolling token-unit issuance quotas
- Transaction tracking for retry-safe outcome checks and transaction status URLs
- Events catalogue for delivery retries, replays, and chain-of-custody proofs
- Idempotency and on-chain outcome events for webhook idempotency fields and finality signals
Compliance and custody split
Understand how DALP separates identity and compliance decisions from custody approvals and signing policies when token operations are executed.
Vendor governance responsibility model
DALP separates platform controls from the third-party services, operating procedures, and regulatory evidence that a financial institution owns when it assesses outsourcing, DORA, and vendor governance obligations.