> For the complete documentation index, see [llms.txt](https://docs.axis.to/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.axis.to/usdx-the-synthetic-dollar/mint-and-redeem.md).

# USDx Primary Market

Mint USDx from collateral and redeem USDx back to collateral through the Axis primary market.

{% hint style="info" %}
This is a **How-to Guide**. For background on why the minting system works this way, see [Architecture](/technical-and-architecture/architecture.md). For complete function signatures, see [Core Contracts Reference](/reference/core-contracts.md).
{% endhint %}

***

## Minting and redeeming are one market

Minting creates new synthetic dollars and redeeming is the reverse. Both are the same action seen from opposite sides: you are **buying or selling USDx in the primary market** against the whitelisted collateral assets. Each collateral asset defines a market that can come online or be deprecated over time.

The market is the general case, which is why the core V2 contract is `USDxMarket`. Participants trade against it through signed orders rather than calling a mint function directly, so one contract settles both directions. Its signed-order, **settle-onchain / match-offchain** design is inspired by the [**0x**](https://0x.org) **and** [**CoW Swap**](https://swap.cow.fi) **style** of onchain settlement: settlement happens atomically onchain while order matching happens offchain (RFQ), and participants keep control of their assets until settlement.

The flow is the same on both sides:

1. An approved counterparty requests a price from the **Axis Market API**.
2. The counterparty generates a **signed EIP-712 order** on those terms.
3. The protocol server checks the required balances and approvals. It may **reject** an order but **cannot alter** it, the terms are pre-approved by the signer and settle exactly as signed, or not at all.
4. On approval, the order is sent to the chain and settles as an **atomic onchain mint** (or redeem). Settlement is atomic on chain; matching is off chain (RFQ); users retain control throughout.

Putting reserves to work involves the cost of winding and unwinding positions, so the price a counterparty is quoted reflects that cost; the protocol works to **minimize slippage** in servicing primary market orders.

***

## How to Mint USDx

Minting converts supported collateral into USDx by settling a signed EIP-712 order on `USDxMarket`. An **approved counterparty**, a whitelisted, eligible primary market account, submits an order on the USDx market; when that order is filled, USDx is **minted at roughly 1:1** against the incoming collateral, at the asset and amounts specified in the order. An eligible participant signs the order; an authorized operator submits it for settlement. New supply flows only through the market: `USDxMarket` holds `MARKET_ROLE` on `USDx` and is the only supply authority at launch, Axis ships no separate `MINTER_ROLE`/`BURNER_ROLE`.

On settlement, the incoming collateral is **routed through the market's channels and lanes to a custodian account**, from which **custody is then transferred out to the exchanges and trading venues** that hold the backing portfolio, see [Backing, Custody & Transparency](/backing-reserves-and-transparency/backing-custody-transparency.md). By design, Axis takes **no profit from minting or redeeming USDx**: mint and redeem settle against the collateral in the order rather than at a spread meant to earn Axis a margin. Yield comes from how the backing is deployed, not from the mint or redeem itself.

### Prerequisites

* The order's `accountId` must be an approved primary market account, eligible under current access and terms.
* The `signer` must be authorized for that account, a direct EOA match, an accepted delegated signer, or an ERC-1271 smart account.
* The collateral asset and USDx must form an enabled route (`routeId`), and the settlement path (`channelId`) must be enabled.
* The account must have approved `USDxMarket` to spend the collateral (the order's input asset).
* An operator holding `MINT_OPERATOR_ROLE` must submit the order for settlement. Issuance itself is gated by `MARKET_ROLE` on `USDx`, held by `USDxMarket`, there is no standalone minter role.

### Step 1: Construct the Order

The V2 order (`Order`, documented as `PrimaryMarketOrder`) binds the account, the approved route and channel, the signer, the side, the input/output assets, the receiver, a deadline, a one-time nonce, and the accepted-terms hash.

```solidity
IUSDxMarket.Order memory order = IUSDxMarket.Order({
    accountId: userAccountId,             // approved primary market account
    routeId: mintRouteId,                 // enabled USDT -> USDx route
    channelId: custodyChannelId,          // approved settlement path
    signer: userAddress,                  // authorized for accountId
    side: IUSDxMarket.OrderSide.MINT,
    inputAsset: USDT_ADDRESS,
    outputAsset: USDX_ADDRESS,
    inputAmount: 1000e6,                  // 1000 USDT (6 decimals)
    minOutputAmount: 1000e18,             // min 1000 USDx out (18 decimals)
    receiver: userAddress,                // receives USDx
    deadline: block.timestamp + 1 hours,
    nonce: 1,                             // non-zero, unique per accountId
    termsHash: acceptedTermsHash          // accepted Minting-ToS version
});
```

{% hint style="warning" %}
The nonce must be **non-zero** and unused. Check availability with `verifyNonce(accountId, nonce)` before signing, nonces are namespaced per `accountId`, not per signer address, and are consumed only on successful settlement.
{% endhint %}

### Step 2: Sign the Order (EIP-712)

The EIP-712 domain name is `USDxMarket`, version `1`.

```javascript
// ethers.js v6
const domain = {
    name: "USDxMarket",
    version: "1",
    chainId: chainId,
    verifyingContract: usdxMarketAddress
};

const types = {
    Order: [
        { name: "accountId", type: "bytes32" },
        { name: "routeId", type: "bytes32" },
        { name: "channelId", type: "bytes32" },
        { name: "signer", type: "address" },
        { name: "side", type: "uint8" },
        { name: "inputAsset", type: "address" },
        { name: "outputAsset", type: "address" },
        { name: "inputAmount", type: "uint256" },
        { name: "minOutputAmount", type: "uint256" },
        { name: "receiver", type: "address" },
        { name: "deadline", type: "uint256" },
        { name: "nonce", type: "uint256" },
        { name: "termsHash", type: "bytes32" }
    ]
};

const signature = await signer.signTypedData(domain, types, order);
```

### Step 3: Preview the Settlement

Before an operator settles, preview the order against current policy, routing, nonce, signature, and capacity:

```solidity
// Read-only: does this order settle under current state?
IUSDxMarket.SettlementCheck memory check =
    usdxMarket.checkSettlement(order, sig, settlementData);
```

`checkMint(order, sig)` returns an `OrderCheck` (`valid`, `code`, `orderHash`, `signer`, `nonceUsed`, `availableBlockCapacity`) for the mint side. The `settlementData` argument is ignored by the preview; it only feeds the emitted settlement hash at real settlement.

### Step 4: Operator Settles the Order

An operator holding `MINT_OPERATOR_ROLE` submits the signed order. Settlement re-runs every check, routes collateral to the channel's custody, mints USDx to the receiver, marks the nonce used, and records a settlement proof.

```solidity
IUSDxMarket.Signature memory sig = IUSDxMarket.Signature({
    signatureType: IUSDxMarket.SignatureType.EIP712,
    signatureBytes: signatureBytes
});

// side alias: settle(...) with OrderSide.MINT, or mint(...)
bytes32 proofId = usdxMarket.settle(order, sig, settlementData);
```

### Using cast

```bash
$ cast send $USDX_MARKET \
    "settle((bytes32,bytes32,bytes32,address,uint8,address,address,uint256,uint256,address,uint256,uint256,bytes32),(uint8,bytes),bytes)" \
    "($ACCOUNT_ID,$ROUTE_ID,$CHANNEL_ID,$SIGNER,0,$INPUT_ASSET,$OUTPUT_ASSET,$INPUT_AMOUNT,$MIN_OUTPUT_AMOUNT,$RECEIVER,$DEADLINE,$NONCE,$TERMS_HASH)" \
    "(0,$SIGNATURE)" \
    "$SETTLEMENT_DATA" \
    --private-key $MINT_OPERATOR_KEY
```

### Why a Settlement Is Rejected

`checkMint` / `checkSettlement` surface a `bytes32` reason code without reverting, so a rejected order can be diagnosed before submission. Settlement re-runs the same checks. Common codes:

| Reason code         | Cause                                                                    |
| ------------------- | ------------------------------------------------------------------------ |
| `NOT_ELIGIBLE`      | Account not approved, or access/terms conditions not met                 |
| `RESTRICTED`        | Account or receiver blocked by a restriction                             |
| `ROUTE_DISABLED`    | The `routeId` is not an enabled market route                             |
| `CHANNEL_DISABLED`  | The `channelId` settlement path is not enabled                           |
| `UNAUTHORIZED`      | Signer is not the account's EOA, accepted delegate, or ERC-1271 approver |
| `CAPACITY_EXCEEDED` | Configured `CapConfig` capacity for the scope is exhausted               |
| `PAUSED`            | Market, token, or the relevant flow is paused                            |

A failed settlement consumes neither the nonce nor the capacity, so a rejected order can be safely retried. Signature expiry (`block.timestamp > deadline`) and a consumed nonce also block settlement.

***

## How to Redeem USDx

Redemption burns USDx and returns collateral to the receiver, settled by an operator on the primary market, the mirror of mint.

{% hint style="info" %}
This is the **primary market** redemption of USDx for collateral. Redeeming *staked* USDx (sUSDx → USDx) is a separate, asynchronous ERC-7540 flow with a cooldown, see the [Stake & Unstake guide](/susdx-the-rewards-vault/stake-and-unstake.md) and [What is sUSDx?](/susdx-the-rewards-vault/susdx.md).
{% endhint %}

### Prerequisites

* The `accountId` must be an approved, eligible primary market account, and the `signer` authorized for it.
* USDx and the collateral asset must form an enabled redeem route (`routeId`), with an enabled settlement `channelId`.
* The account must have approved `USDxMarket` to spend its USDx (the order's input asset).
* An operator holding `REDEEM_OPERATOR_ROLE` must submit the order.
* The market must have sufficient collateral available through the channel.

### Step 1: Construct a Redeem Order

Same `Order` schema as mint, with `side = REDEEM` and the assets reversed, USDx in, collateral out:

```solidity
IUSDxMarket.Order memory order = IUSDxMarket.Order({
    accountId: userAccountId,
    routeId: redeemRouteId,               // enabled USDx -> USDT route
    channelId: custodyChannelId,
    signer: userAddress,
    side: IUSDxMarket.OrderSide.REDEEM,
    inputAsset: USDX_ADDRESS,
    outputAsset: USDT_ADDRESS,
    inputAmount: 1000e18,                 // 1000 USDx (18 decimals)
    minOutputAmount: 1000e6,              // min 1000 USDT out (6 decimals)
    receiver: userAddress,                // receives collateral
    deadline: block.timestamp + 1 hours,
    nonce: 2,
    termsHash: acceptedTermsHash
});
```

### Step 2: Sign and Settle

Sign with the same EIP-712 domain (`USDxMarket`, version `1`). An operator holding `REDEEM_OPERATOR_ROLE` then settles:

```solidity
// side alias: settle(...) with OrderSide.REDEEM, or redeem(...)
bytes32 proofId = usdxMarket.settle(order, sig, settlementData);
```

Settlement verifies the order, meters redeem capacity (`CapConfig` metering USDx input), burns the USDx, and releases collateral to the receiver through the approved channel.

***

## How to Set Up Delegated Signing

Smart contracts cannot produce ECDSA signatures directly. The delegation registry on `USDxMarket` lets a source account authorize an EOA to sign orders on its behalf (a two-step initiate-then-confirm handshake). ERC-1271 smart-account validation is also supported as a separate path.

### Step 1: Source Account Initiates Delegation

```solidity
// Called by the delegating account
usdxMarket.setDelegatedSigner(eoaAddress);
// SignerStatus: PENDING
```

### Step 2: Signer Confirms

```solidity
// Called by the EOA being delegated
usdxMarket.confirmDelegatedSigner(sourceAccount);
// SignerStatus: ACCEPTED
```

The EOA can now sign orders whose `signer` is authorized for the source account. Read current status with `delegatedSigner(signer, source)`.

### Revoking Delegation

```solidity
// Called by the delegating account
usdxMarket.removeDelegatedSigner(eoaAddress);
// SignerStatus: REJECTED
```

***

## Nonce & Replay Protection

Nonces prevent order replay. Each `accountId` has an independent nonce space tracked as a bitmap (256 nonces per storage slot). A nonce must be non-zero and is consumed **only on successful settlement**.

### Check Nonce Availability

```solidity
bool used = usdxMarket.isNonceUsed(accountId, nonce);
// or the bitmap form:
(uint256 slot, uint256 bitmap, uint256 bit) =
    usdxMarket.verifyNonce(accountId, nonce);
bool available = (bitmap & bit) == 0;
```

```bash
$ cast call $USDX_MARKET "isNonceUsed(bytes32,uint256)(bool)" $ACCOUNT_ID $NONCE
```

Nonces do not need to be sequential, any unused non-zero nonce in the `uint256` space is valid.

### Cancelling an Order

A holder of `SETTLEMENT_MANAGER_ROLE` can pre-emptively tombstone an order hash with `cancelOrder(order)`, emitting `OrderCancelled`, so it can never settle. Cancellation does **not** consume the nonce, the order is invalidated by its tombstone, not by the nonce slot, and does not verify the signature.

***

Staked USDx (sUSDx) is where yield accrues: the collateral backing USDx is deployed into strategies whose structural edge is cross-venue and cross-asset fragmentation, a durable, market-neutral yield source that does not rely on any single mechanism (funding is one component and can be the larger share in a given period; see the Transparency Dashboard for current attribution), and that yield is passed to stakers through sUSDx. See [How Axis Earns Yield](/susdx-the-rewards-vault/how-axis-earns-yield.md). Holding USDx alone earns nothing.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.axis.to/usdx-the-synthetic-dollar/mint-and-redeem.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
