# From External Mint Instruction to On-Chain Transaction

Source: https://docs.settlemint.com/docs/architecture/security/replay-idempotency-mint-controls
How DALP protects EVM mint instructions from duplicate client retries, replayed requests, nonce conflicts, and unauthorized supply changes.



DALP minting becomes a signed EVM instruction to an asset contract. Replay protection has to answer three separate questions:

1. Is this API request a retry of the same client instruction?
2. Is this blockchain transaction already queued, pending, completed, failed, or cancelled?
3. Is the caller authorized to change supply on this specific asset?

## What this is [#what-this-is]

Use this control map before automating DALP minting. It shows how client retries, transaction status checks, custody approvals, and supply controls fit together. It is not an API reference or a legal approval model.

## Who this is for [#who-this-is-for]

| Reader                      | Decision this page supports                                                               |
| --------------------------- | ----------------------------------------------------------------------------------------- |
| Operations lead             | Decide how retries, approvals, and transaction status should be handled in a mint runbook |
| Compliance or risk reviewer | Confirm which controls prevent duplicate or unauthorized supply changes                   |
| API integrator              | Choose idempotency keys, retry behavior, and reconciliation checks for mint automation    |
| Asset issuer                | Understand which responsibilities stay with DALP and which stay with the institution      |

## Control model [#control-model]

Replay protection is layered. No single layer is the whole control.

<Mermaid
  chart="`flowchart TB
  Client[Client or operator<br/>mint instruction] --> Idem[API idempotency key<br/>same request body + path]
  Idem --> Auth[Permission and wallet verification<br/>Supply Management role]
  Auth --> Queue[Transaction queue<br/>sender + chain + scoped key]
  Queue --> Nonce[Nonce coordination<br/>ordered per signing address + chain]
  Nonce --> Sign[Signer and custody policy<br/>approval or HSM quorum]
  Sign --> Chain[EVM asset contract<br/>mint or batchMint]
  Chain --> Index[Indexer and webhooks<br/>outcome reconciliation]

  Idem -. rejects .-> Reuse[Same key, different request]
  Queue -. rejects .-> Wallet[Same key, different wallet route]
  Auth -. rejects .-> Role[Caller lacks mint authority]
  Chain -. reverts .-> Rules[Paused asset, cap, collateral, or recipient compliance failure]

`"
/>

| Layer              | What it protects                     | Primary control                                                    | What it does not prove                                                           |
| ------------------ | ------------------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| API idempotency    | Duplicate HTTP retries               | `Idempotency-Key` tied to method, path, and request body           | Final on-chain state                                                             |
| Transaction queue  | Duplicate blockchain submission      | Sender wallet + chain ID + operation-scoped idempotency key        | Legal approval outside the platform                                              |
| Nonce coordination | Concurrent transaction conflicts     | Ordered nonce assignment per signing address and chain             | That the business instruction is approved                                        |
| Authorization      | Unauthorized supply changes          | Per-asset Supply Management role and wallet verification           | That the recipient can receive tokens                                            |
| Custody policy     | Signing without operational approval | Configured signer, custody provider, or HSM policy                 | On-chain compliance success                                                      |
| Asset contract     | Invalid mint execution               | EVM role checks and compliance modules                             | Off-chain reserve or legal sufficiency unless represented by configured controls |
| Reconciliation     | Outcome visibility                   | Transaction status, indexer updates, and subscribed webhook events | That a cached API response is the authoritative final on-chain outcome           |

## Mint instruction flow [#mint-instruction-flow]

A mint instruction follows this sequence for single-recipient and batch minting.

<Mermaid
  chart="`sequenceDiagram
  autonumber
  participant Client as Client / Asset Console
  participant API as DALP Unified API
  participant Queue as Transaction Queue
  participant Signer as Signer / Custody
  participant Chain as EVM Asset Contract
  participant Indexer as Indexer + Webhooks

  Client->>API: POST /api/token/{token}/mint<br/>Idempotency-Key: mint-2026-05-15-001
  API->>API: Compare method, path, body, and key
  API->>API: Check asset role and wallet verification
  API->>Queue: Enqueue token.mint with scoped key
  Queue->>Queue: Reuse existing transaction request if this is a retry
  Queue->>Signer: Assign or reuse the signing wallet nonce
  Signer->>Signer: Request signature or approval
  Signer->>Chain: Broadcast signed EVM transaction
  Chain->>Chain: Enforce Supply Management role and mint rules
  Chain-->>Indexer: Emit on-chain events
  Indexer-->>Client: Status, indexed asset data, or webhook event

`"
/>

If the caller sends the same `Idempotency-Key` with the same request body, DALP treats it as the same client instruction during the idempotency window. If the caller sends the same key with a different body, path, or method, DALP rejects it as key reuse.

For blockchain execution, DALP scopes the queued transaction by sender wallet, chain ID, and operation kind. A retry with the same key reattaches to the existing transaction request instead of submitting a second mint. A retry that tries to change wallet routing under the same key is rejected.

Nonce management sits below the client idempotency key. After the mint instruction is accepted into the queue, DALP coordinates nonce assignment per signing address and chain so concurrent mints from the same wallet are ordered instead of racing the network. Retries reuse the tracked transaction request and its nonce path; stuck or conflicting transactions are handled through transaction status, retry, replacement, or operator recovery flows rather than by issuing a second business mint instruction.

## What the client must do [#what-the-client-must-do]

| Client responsibility                          | Required practice                                                                                                                 |
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Generate a stable key                          | Use one `Idempotency-Key` per business mint instruction. Keep it stable across network retries.                                   |
| Do not reuse keys across instructions          | A second mint, even to the same recipient and amount, needs a new key.                                                            |
| Keep the request body stable                   | Changing recipients, amounts, token address, executor route, or wallet route means it is a different instruction. Use a new key.  |
| Store the key with the business record         | Persist the key with the ticket, trade, subscription, or operations record that authorized the mint.                              |
| Reconcile by transaction status                | Treat the HTTP response as acceptance or completion of the API operation, then reconcile the transaction and indexed asset state. |
| Use subscribed webhooks for downstream systems | Do not let a cached retry response become the only proof that downstream ledgers use.                                             |

When a mutation request is sent without an explicit `Idempotency-Key`, DALP can still process it, but the client has no stable key to use for a safe retry. Production integrations should send the header themselves.

## Mint authorization and supply controls [#mint-authorization-and-supply-controls]

Minting is controlled at the API layer and again on-chain.

| Control                                    | Enforced before signing                        | Enforced on-chain                     | Owner                           |
| ------------------------------------------ | ---------------------------------------------- | ------------------------------------- | ------------------------------- |
| User authentication and organization scope | Yes                                            | No                                    | Institution / 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 / custody provider  |
| Paused asset state                         | Yes                                            | Yes                                   | Emergency role                  |
| Recipient identity and compliance          | Validated before execution where available     | Yes, by configured compliance modules | Compliance manager              |
| Supply cap and collateral modules          | Surfaced through simulation or revert handling | Yes                                   | Governance / compliance manager |

Single-recipient minting calls the asset contract's `mint` function. Batch minting calls `batchMint`. DALP asset contracts restrict both paths to the per-asset `SUPPLY_MANAGEMENT_ROLE`.

Supply controls depend on the asset configuration:

| Control                | Effect on minting                                                                               |
| ---------------------- | ----------------------------------------------------------------------------------------------- |
| Supply cap             | Prevents mints that would exceed the configured circulating supply cap                          |
| Collateral requirement | Prevents mints when the configured collateral claim is missing, expired, or insufficient        |
| Recipient compliance   | Prevents issuance to a recipient that does not satisfy configured identity or eligibility rules |
| Paused state           | Blocks minting until the asset is unpaused                                                      |

## Retry and outcome rules [#retry-and-outcome-rules]

| Situation                                      | Expected behavior                                                                      |
| ---------------------------------------------- | -------------------------------------------------------------------------------------- |
| Same key, same request, original still running | DALP reports the existing in-flight operation or waits for the same queued transaction |
| Same key, same request, original completed     | DALP returns the existing transaction result or reads current state after indexing     |
| Same key, different request body               | DALP rejects the request as idempotency-key reuse                                      |
| Same key, different wallet route               | DALP rejects the retry because it no longer targets the same execution route           |
| Previous transaction failed or was cancelled   | Retry with a new idempotency key after the cause is resolved                           |
| Client did not receive the HTTP response       | Retry with the same key, then check transaction status and indexed asset state         |
| HTTP response was served from cache            | Treat it as the same API response, not as fresh chain finality                         |

The idempotency window is 24 hours. After that window, use a new key and reconcile the earlier transaction before issuing another mint instruction.

## What DALP does not decide [#what-dalp-does-not-decide]

DALP's replay and idempotency controls do not replace institutional approval policy.

| Not covered by idempotency                                                                                                  | Required owner                              |
| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| Whether a mint is legally approved                                                                                          | Institution and its counsel                 |
| Whether off-chain cash, collateral, or subscription documents are sufficient unless represented by configured DALP controls | Institution                                 |
| Whether an external ledger has posted the mint correctly                                                                    | Integration owner                           |
| Whether a custody provider's approval matrix is appropriate                                                                 | Institution / custody provider              |
| Whether an EVM transaction remains canonical before the configured finality process completes                               | Chain operations and reconciliation process |

DALP is EVM-only. These controls describe DALP's EVM transaction path and do not imply support for non-EVM chains, bridge settlement, or cross-chain replay protection.

## Operational checklist [#operational-checklist]

| Before minting                                                      | During retry                                                                        | After completion                                                      |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| Confirm token address, chain, recipient list, amounts, and decimals | Reuse the same idempotency key only for the same instruction                        | Record transaction hash, transaction status, and indexed total supply |
| Confirm Supply Management role and wallet verification method       | Do not change executor or wallet route 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 cached responses separately from final chain outcome      |

## Where to go next [#where-to-go-next]

* [Mint assets](/docs/developer-guides/asset-servicing/mint-assets) for the API request shape
* [Signing flow](/docs/architecture/flows/signing-flow) for custody and approval sequencing
* [Per-asset RBAC](/docs/architecture/components/asset-contracts/rbac) for the Supply Management role
* [Supply Cap & Collateral](/docs/architecture/security/compliance/supply-cap-collateral) for mint-specific compliance modules
* [Transaction tracking](/docs/developer-guides/operations/transaction-tracking) for retry-safe outcome checks
* [Webhook endpoints](/docs/developer-guides/api-integration/webhook-endpoints) for delivery retries, replays, and chain-of-custody proofs
