SettleMint
Security

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

ReaderUse this page to decide
Operations leadHow to handle retries, signer approvals, status checks, and reconciliation in a mint runbook
Risk or compliance reviewerWhich controls prevent duplicate mints or unauthorized supply changes
API integratorHow to choose idempotency keys and when a retry needs a new key
Asset issuerWhich duties DALP enforces and which stay with the institution

One-view control map

Rendering diagram...

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

LayerWhat it protectsPrimary controlWhat it does not prove
API requestDuplicate client retriesIdempotency-Key tied to tenant, route, method, and request bodyFinal chain state
Mint routeOperation-specific replayMint operation kind, signing wallet, chain ID, and scoped retry keyLegal approval for the mint
Transaction queueDuplicate transaction submissionExisting transaction request for the same scoped key and routeThat a changed payload is safe to treat as the same instruction
Nonce laneConcurrent sends from one signing addressOrdered nonce use per signing address and EVM chainThat the business instruction is approved
AuthorizationUnauthorized supply changesUser authentication, organization scope, wallet verification, and per-asset Supply Management roleThat the recipient passes every on-chain rule
Signer or custody policySignature releaseConfigured signer, HSM, or custody approval routeThat the chain will accept the mint
Asset contractInvalid mint executionEVM role checks and configured compliance modulesOff-chain reserve, cash, or subscription sufficiency unless represented by configured controls
ReconciliationOutcome visibilityTransaction status, indexed asset state, and webhook eventsThat 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 totalSupply above 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 pointStable inputDuplicate behaviorChanged input behavior
Mint routeIdempotency-Key, token.mint, signing wallet, and chain IDReattaches to the existing queued transactionTreats the key as the same queued mint while wallet routing is unchanged
Transaction queueSender wallet, chain ID, scoped key, and wallet-selection fingerprintReuses or tracks the existing transaction requestRejects a retry that changes the effective signing address, account-wallet-only route, or EOA routing
EVM transactionSigning address, nonce, calldata, target contract, value, and chain IDReconciliation uses transaction status and eventsThe 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 caseDALP controlIntegrator expectation
Same wallet, concurrent EVM sendsOrdered nonce lane per signing address and chain IDSubmit through the DALP transaction queue instead of broadcasting from a separate system with the same signing wallet
Stuck or replayed local broadcastReuse the same signed bytes, recover already-known hashes, and sync from the pending on-chain nonce on nonce errorsCheck transaction status before creating a new mint instruction
Signed transaction from custodyPre-broadcast validation of nonce, target, calldata, chain ID, signer, and valueTreat a mismatch as a failed approval or signing event, not as a transaction to retry blindly
EIP-155 chain replayChain ID is part of the signed EVM transaction and DALP rejects custody-signed transactions with the wrong chain IDKeep 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 inputQueue resultClient action
Same key, same signing route, first transaction still runningDALP attaches to the existing workflow and reports the same transaction requestPoll the returned transaction status URL or wait for the subscribed webhook
Same key, same signing route, first transaction completedDALP returns the stored transaction hash and reads the indexed asset state when availableReconcile the hash and indexed total supply with the business record
Same key, different wallet routeDALP rejects the retry as an idempotency conflictFix the route mismatch or submit a new approved instruction with a new key
Same key after the 24-hour idempotency windowDALP rejects the expired keyReconcile 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.

Rendering diagram...

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 responsibilityRequired practice
Generate a stable keySend one Idempotency-Key for each approved mint instruction. Keep it stable across network retries.
Keep the payload stableTreat token address, recipients, amounts, executor route, and wallet route changes as a new business instruction with a new key.
Store the keyKeep the key with the ticket, trade, subscription, or operations record that approved the mint.
Check outcome separatelyTreat the HTTP response as API acceptance or completion. Reconcile transaction status, indexed asset state, and webhook delivery.
Avoid proof by retryDo 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.

ControlBefore signingOn-chainTypical owner
User authentication and organization scopeYesNoInstitution and DALP deployment
API key access scopeYesNoInstitution
Per-asset Supply Management roleYesYesAsset administrator
Wallet verificationYesNoInstitution
Custody or HSM approval policyDuring signingNoInstitution or custody provider
Paused asset stateYesYesEmergency role
Recipient identity and compliance rulesChecked before execution where configuredYesCompliance manager
Supply cap and collateral modulesSurfaced through simulation or revert handlingYesGovernance 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:

ActionRequired accessWhere DALP enforces it
Single-recipient mintPer-asset Supply Management roleBefore signing and in the asset contract mint function
Batch mintPer-asset Supply Management roleBefore signing and in the asset contract batchMint function
Burn or batch burnPer-asset Supply Management roleIn the asset contract burn functions
Change an asset cap with setCap(uint256 newCap)Governance roleIn capped asset contracts that expose cap updates
Add, remove, or configure compliance modulesGovernance roleIn the asset contract governance functions and compliance module configuration
Pause or unpause an assetEmergency roleIn 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

SituationExpected behavior
Same key, same request, original still runningDALP reports or waits for the existing queued transaction.
Same key, same request, original completedDALP returns the existing result or reads current state after indexing.
Same key, changed mint payload, same wallet routeDALP treats the key as the existing queued mint. Use a new key for the changed instruction.
Same key, different wallet or executor routeDALP rejects the retry because it targets a different execution route.
Previous transaction failed or was cancelledResolve the cause, then retry with a new idempotency key.
Client did not receive the HTTP responseRetry with the same key, then check transaction status and indexed asset state.
Retry attaches to a completed transactionTreat 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 modelRequired owner
Legal approval for a mintInstitution and counsel
Off-chain cash, collateral, or subscription evidence unless represented by configured DALP controlsInstitution
External ledger postingIntegration owner
Custody-provider approval matrixInstitution and custody provider
Chain finality before the configured finality process completesChain 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 mintingDuring retryAfter 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

On this page