> ## Documentation Index
> Fetch the complete documentation index at: https://docs.multiliquid.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# MultiliquidSwap Contract

> Central orchestrator contract managing all swap operations between RWAs and stablecoins

## Overview

The `MultiliquidSwap` contract is the core orchestrator of the Multiliquid Protocol, managing all atomic swap operations between Real World Asset (RWA) tokens and stablecoins. It coordinates with delegate contracts, price adapters, and implements comprehensive fee management and risk controls.

**Contract Location**: `src/MultiliquidSwap.sol`

### Key Responsibilities

* Orchestrate bidirectional swaps between RWAs and stablecoins
* Calculate swap amounts using USD-denominated pricing
* Enforce volume-based fee tiers
* Manage RWA whitelists per stablecoin
* Coordinate with asset-specific delegate contracts
* Track and collect protocol fees

## Contract Architecture

### Inheritance

```solidity theme={null}
contract MultiliquidSwap is
    Initializable,
    UUPSUpgradeable,
    ReentrancyGuardUpgradeable,
    AccessControlEnumerableUpgradeable,
    PausableUpgradeable,
    IMultiliquidSwap
```

### Base Contracts

* **Initializable**: Supports proxy initialization
* **UUPSUpgradeable**: Enables secure contract upgrades
* **ReentrancyGuardUpgradeable**: Reentrancy attack protection
* **AccessControlEnumerableUpgradeable**: Role-based permission system with enumeration
* **PausableUpgradeable**: Emergency pause capability
* **IMultiliquidSwap**: Interface implementation

## Core Functions

### Swap Functions

<Note>
  **NAV-Based Deterministic Pricing**: All swap functions use deterministic NAV-based pricing. While parameters accept "minimum" or "maximum" amounts for safety bounds, integrators should use the exact amounts returned by the corresponding calculation functions (`calculateSwapIntoStablecoin`, `calculateSwapIntoRWA`, etc.) rather than applying arbitrary slippage tolerances. The protocol pricing is not subject to market slippage like AMM DEXs.

  See the [Integration Guide](/evm/guides/integration#execute-swap) for code examples showing proper usage of calculation functions.
</Note>

#### swapIntoStablecoin

Swap RWA tokens for stablecoins (ExactIn variant).

```solidity theme={null}
function swapIntoStablecoin(SwapIntoStablecoinInputs calldata inputs) external;
```

**Parameters**:

* `inputs.stablecoinID`: ID of target stablecoin
* `inputs.stablecoinAmount`: **Minimum** stablecoin amount to receive
* `inputs.rwaID`: ID of source RWA token
* `inputs.rwaAmount`: **Exact** RWA amount to spend
* `inputs.stablecoinMetadata`: Metadata for stablecoin delegate
* `inputs.rwaMetadata`: Metadata for RWA delegate

**Access**: Public, requires whitelisting (if enforced by delegates)

**Emits**: `SwapIntoStablecoin(stablecoinID, rwaID, user, stablecoinAmt, rwaAmt, feeAmt, stablecoinMetadata, rwaMetadata)`

**Requirements**:

* Contract not paused
* RWA and stablecoin must be accepted
* RWA must be whitelisted by stablecoin
* User must have sufficient RWA balance
* Calculated stablecoin output must meet minimum
* RWA delegate validation must pass

**Example**:

```javascript theme={null}
// First, calculate exact output for 1000 ULTRA input
const [stableAmt, feeAmt] = await multiliquidSwap.calculateSwapIntoStablecoin(
    usdcID,
    ultraID,
    parseUnits("1000", 6)
);

// Use exact calculated amount (NAV-based pricing is deterministic)
await multiliquidSwap.swapIntoStablecoin({
    stablecoinID: usdcID,
    stablecoinAmount: stableAmt,             // Exact calculated output
    rwaID: ultraID,
    rwaAmount: parseUnits("1000", 6),        // Exact input
    stablecoinMetadata: "0x",
    rwaMetadata: "0x"
});
```

***

#### swapIntoStablecoinExactOut

Swap RWA tokens for stablecoins (ExactOut variant).

```solidity theme={null}
function swapIntoStablecoinExactOut(SwapIntoStablecoinInputs calldata inputs) external;
```

**Parameters**:

* `inputs.stablecoinID`: ID of target stablecoin
* `inputs.stablecoinAmount`: **Exact** stablecoin amount to receive
* `inputs.rwaID`: ID of source RWA token
* `inputs.rwaAmount`: **Maximum** RWA amount willing to spend
* `inputs.stablecoinMetadata`: Metadata for stablecoin delegate
* `inputs.rwaMetadata`: Metadata for RWA delegate

**Example**:

```javascript theme={null}
// First, calculate exact RWA required for 1000 USDC output
const [rwaRequired, feeAmt] = await multiliquidSwap.calculateSwapIntoStablecoinExactOut(
    usdcID,
    ultraID,
    parseUnits("1000", 6),
    userAddress
);

// Use exact calculated amount (NAV-based pricing is deterministic)
await multiliquidSwap.swapIntoStablecoinExactOut({
    stablecoinID: usdcID,
    stablecoinAmount: parseUnits("1000", 6),  // Exact output
    rwaID: ultraID,
    rwaAmount: rwaRequired,                   // Exact calculated input
    stablecoinMetadata: "0x",
    rwaMetadata: "0x"
});
```

***

#### swapIntoRWA

Swap stablecoins for RWA tokens (ExactIn variant).

```solidity theme={null}
function swapIntoRWA(SwapIntoRWAInputs calldata inputs) external;
```

**Parameters**:

* `inputs.rwaID`: ID of target RWA token
* `inputs.rwaAmount`: **Minimum** RWA amount to receive
* `inputs.stablecoinID`: ID of source stablecoin
* `inputs.stablecoinAmount`: **Exact** stablecoin amount to spend
* `inputs.stablecoinMetadata`: Metadata for stablecoin delegate
* `inputs.rwaMetadata`: Metadata for RWA delegate

**Emits**: `SwapIntoRWA(rwaID, stablecoinID, user, rwaAmt, stablecoinAmt, feeAmt, redemptionFeeAmt, stablecoinMetadata, rwaMetadata)`

**Example**:

```javascript theme={null}
// First, calculate exact RWA output for 1000 USDC input
const [rwaAmt, feeAmt, redemptionFeeAmt] = await multiliquidSwap.calculateSwapIntoRWA(
    ultraID,
    usdcID,
    parseUnits("1000", 6),
    userAddress
);

// Use exact calculated amount (NAV-based pricing is deterministic)
await multiliquidSwap.swapIntoRWA({
    rwaID: ultraID,
    rwaAmount: rwaAmt,                        // Exact calculated output
    stablecoinID: usdcID,
    stablecoinAmount: parseUnits("1000", 6),  // Exact input
    stablecoinMetadata: "0x",
    rwaMetadata: "0x"
});
```

***

#### swapIntoRWAExactOut

Swap stablecoins for RWA tokens (ExactOut variant).

```solidity theme={null}
function swapIntoRWAExactOut(SwapIntoRWAInputs calldata inputs) external;
```

**Parameters**:

* `inputs.rwaID`: ID of target RWA token
* `inputs.rwaAmount`: **Exact** RWA amount to receive
* `inputs.stablecoinID`: ID of source stablecoin
* `inputs.stablecoinAmount`: **Maximum** stablecoin amount willing to spend
* `inputs.stablecoinMetadata`: Metadata for stablecoin delegate
* `inputs.rwaMetadata`: Metadata for RWA delegate

***

#### swapRWAToRWA

Swap between two RWA tokens using a specific stablecoin delegate as the rebalanced portfolio. This will accrue double redemption fees.

```solidity theme={null}
function swapRWAToRWA(SwapRWAToRWAInputs calldata inputs) external;
```

**Parameters**:

* `inputs.exactOut`: Boolean indicating exactOut (true) or exactIn (false)
* `inputs.stablecoinID`: ID of stablecoin used for pricing
* `inputs.rwaInID`: ID of source RWA
* `inputs.rwaInAmount`: RWA input amount (exact if exactOut=false, max if exactOut=true)
* `inputs.rwaOutID`: ID of target RWA
* `inputs.rwaOutAmount`: RWA output amount (min if exactOut=false, exact if exactOut=true)
* `inputs.rwaInMetadata`: Metadata for source RWA delegate
* `inputs.rwaOutMetadata`: Metadata for target RWA delegate

**Process**:

1. User provides `rwaIn` tokens
2. Protocol calculates equivalent value
3. Protocol calculates equivalent value in `rwaOut` tokens
4. User receives `rwaOut` tokens
5. Fees deducted from output

**Use Case**: Swap ULTRA → USTB

***

#### swapStablecoinToStablecoin

Swap between two stablecoins using a specific stablecoinDelegate based on `useDelegateForStablecoinOut`. The delegate chosen determines fees.

```solidity theme={null}
function swapStablecoinToStablecoin(SwapStablecoinToStablecoinInputs calldata inputs) external;
```

**Parameters**:

* `inputs.exactOut`: Boolean indicating exactOut (true) or exactIn (false)
* `inputs.useDelegateForStablecoinOut`: Route through stablecoinOut delegate (true) or stablecoinIn delegate (false)
* `inputs.stablecoinInID`: ID of source stablecoin
* `inputs.stablecoinInAmount`: Input amount
* `inputs.stablecoinOutID`: ID of target stablecoin
* `inputs.stablecoinOutAmount`: Output amount
* `inputs.stablecoinInMetadata`: Metadata for source stablecoin delegate
* `inputs.stablecoinOutMetadata`: Metadata for target stablecoin delegate

**Use Case**: Swap USDC → USDT

***

### Calculation/View Functions

The contract provides view functions for off-chain quote generation, with one calculation function corresponding to each swap function.

#### calculateSwapIntoRWA

Calculate RWA output for a given stablecoin input (for `swapIntoRWA`).

```solidity theme={null}
function calculateSwapIntoRWA(
    bytes32 rwaID,
    bytes32 stablecoinID,
    uint256 stableAmt,
    address user
) external view returns (
    uint256 rwaAmt,
    uint256 feeAmt,
    uint256 redemptionFeeAmt
);
```

**Returns**:

* `rwaAmt`: RWA amount user will receive (after fees)
* `feeAmt`: Protocol fee charged
* `redemptionFeeAmt`: Redemption fee charged by stablecoin issuer

***

#### calculateSwapIntoRWAExactOut

Calculate stablecoin input required for exact RWA output (for `swapIntoRWAExactOut`).

```solidity theme={null}
function calculateSwapIntoRWAExactOut(
    bytes32 rwaID,
    bytes32 stablecoinID,
    uint256 exactRWAOut,
    address user
) external view returns (
    uint256 stablecoinRequired,
    uint256 feeAmt,
    uint256 redemptionFeeAmt
);
```

**Returns**:

* `stablecoinRequired`: Stablecoin amount needed to receive exact RWA output
* `feeAmt`: Protocol fee charged
* `redemptionFeeAmt`: Redemption fee charged by stablecoin issuer

***

#### calculateSwapIntoStablecoin

Calculate stablecoin output for a given RWA input (for `swapIntoStablecoin`).

```solidity theme={null}
function calculateSwapIntoStablecoin(
    bytes32 stablecoinID,
    bytes32 rwaID,
    uint256 rwaAmt
) external view returns (
    uint256 stableAmt,
    uint256 feeAmt
);
```

**Returns**:

* `stableAmt`: Stablecoin amount user will receive (after fees)
* `feeAmt`: Protocol fee charged

***

#### calculateSwapIntoStablecoinExactOut

Calculate RWA input required for exact stablecoin output (for `swapIntoStablecoinExactOut`).

```solidity theme={null}
function calculateSwapIntoStablecoinExactOut(
    bytes32 stablecoinID,
    bytes32 rwaID,
    uint256 exactStablecoinOut,
    address user
) external view returns (
    uint256 rwaRequired,
    uint256 feeAmt
);
```

**Returns**:

* `rwaRequired`: RWA amount needed to receive exact stablecoin output
* `feeAmt`: Protocol fee charged

***

#### calculateSwapRWAToRWA

Calculate amounts for RWA-to-RWA swap (for `swapRWAToRWA`).

```solidity theme={null}
function calculateSwapRWAToRWA(
    bytes32 stablecoinID,
    bytes32 rwaInID,
    bytes32 rwaOutID,
    uint256 rwaInAmount,
    uint256 rwaOutAmount,
    bool exactOut
) external view returns (
    RWAToRWAReturnParams memory outputs
);
```

**Parameters**:

* `stablecoinID`: ID of stablecoin used for pricing
* `rwaInID`: ID of input RWA token
* `rwaOutID`: ID of output RWA token
* `rwaInAmount`: Input RWA amount (exact if exactOut=false, max if exactOut=true)
* `rwaOutAmount`: Output RWA amount (min if exactOut=false, exact if exactOut=true)
* `exactOut`: Boolean indicating exactOut (true) or exactIn (false)

**Returns** (`RWAToRWAReturnParams`):

* `rwaInAmount`: RWA input amount required
* `rwaOutAmount`: RWA output amount received
* `protocolFeeAmt`: Protocol fee charged
* `redemptionFeeAmt`: Total redemption fees (both RWAs)

***

#### calculateSwapStablecoinToStablecoin

Calculate amounts for stablecoin-to-stablecoin swap (for `swapStablecoinToStablecoin`).

```solidity theme={null}
function calculateSwapStablecoinToStablecoin(
    bool exactOut,
    bool useDelegateForStablecoinOut,
    bytes32 stablecoinInID,
    uint256 stablecoinInAmount,
    bytes32 stablecoinOutID,
    uint256 stablecoinOutAmount,
    address user
) external view returns (
    StablecoinToStablecoinReturnParams memory outputs
);
```

**Parameters**:

* `exactOut`: Boolean indicating exactOut (true) or exactIn (false)
* `useDelegateForStablecoinOut`: Route through stablecoinOut delegate (true) or stablecoinIn delegate (false)
* `stablecoinInID`: ID of input stablecoin
* `stablecoinInAmount`: Input amount (exact if exactOut=false, max if exactOut=true)
* `stablecoinOutID`: ID of output stablecoin
* `stablecoinOutAmount`: Output amount (min if exactOut=false, exact if exactOut=true)

**Returns** (`StablecoinToStablecoinReturnParams`):

* `stablecoinInAmount`: Stablecoin input amount required
* `stablecoinOutAmount`: Stablecoin output amount received
* `protocolFeeAmt`: Protocol fee charged
* `acceptanceFeeAmt`: Acceptance fee charged by issuer
* `redemptionFeeAmt`: Redemption fee charged by issuer

***

### Administrative Functions

#### setRWAAcceptance

Register or update an RWA token in the protocol.

```solidity theme={null}
function setRWAAcceptance(
    bytes32 rwaID,
    address _delegate,
    address _assetAddress,
    bool _accepted
) external onlyRole(OPERATOR_ROLE);
```

**Parameters**:

* `rwaID`: Unique identifier for the RWA (keccak256 of a protocol-defined string)
* `_delegate`: Address of RWA delegate contract (address(0) if no delegate)
* `_assetAddress`: Address of the RWA token contract
* `_accepted`: `true` to accept, `false` to remove

**Access**: `OPERATOR_ROLE`

**Events**:

```solidity theme={null}
event RWAAcceptanceSet(
    bytes32 indexed rwaID,
    address indexed delegate,
    address indexed assetAddress,
    uint8 decimals,
    bool accepted
);
```

***

#### setStablecoinAcceptance

Register or update a stablecoin in the protocol.

```solidity theme={null}
function setStablecoinAcceptance(
    bytes32 stablecoinID,
    address _delegate,
    address _assetAddress,
    bool _accepted,
    bool _yieldBearing
) external onlyRole(OPERATOR_ROLE);
```

**Parameters**:

* `stablecoinID`: Unique identifier for the stablecoin
* `_delegate`: Address of stablecoin delegate contract
* `_assetAddress`: Address of the stablecoin token contract
* `_accepted`: `true` to accept, `false` to remove
* `_yieldBearing`: indicates whether the stablecoin is yield-bearing

**Access**: `OPERATOR_ROLE`

**Events**:

```solidity theme={null}
event StablecoinAcceptanceSet(
    bytes32 indexed stablecoinID,
    address indexed delegate,
    address indexed assetAddress,
    uint8 decimals,
    bool accepted,
    bool yieldBearing
);
```

***

#### setStablecoinAcceptanceForSwap

Register a stablecoin for swap-only mode (without delegate).

```solidity theme={null}
function setStablecoinAcceptanceForSwap(
    bytes32 stablecoinID,
    address _assetAddress,
    bool _accepted
) external onlyRole(OPERATOR_ROLE);
```

**Purpose**: For stablecoins used only in stablecoin-to-stablecoin swaps

**Access**: `OPERATOR_ROLE`

***

#### setRwaPriceAdapter

Set or update the price adapter for an RWA.

```solidity theme={null}
function setRwaPriceAdapter(bytes32 rwaID, address priceAdapter)
    external
    onlyRole(OPERATOR_ROLE);
```

**Access**: `OPERATOR_ROLE`

**Events**:

```solidity theme={null}
event UpdateRWAUSDValue(bytes32 indexed rwaID, address priceAdapter);
```

***

#### setStablecoinUSDValue

Set the USD value for a stablecoin (usually 1e18 for \$1.00 pegged stablecoins).

```solidity theme={null}
function setStablecoinUSDValue(bytes32 stablecoinID, uint256 value)
    external
    onlyRole(OPERATOR_ROLE);
```

**Access**: `OPERATOR_ROLE`

**Events**:

```solidity theme={null}
event UpdateStablecoinUSDValue(bytes32 indexed stablecoinID, uint256 value);
```

***

#### setRWADiscountRate

Set discount rate for RWA when swapping from a specific stablecoin.

```solidity theme={null}
function setRWADiscountRate(
    bytes32 stablecoinID,
    bytes32 rwaID,
    uint256 rate
) external;
```

**Access**: Stablecoin delegate contract only

**Parameters**:

* `stablecoinID`: ID of the stablecoin
* `rwaID`: ID of the RWA token
* `rate`: Discount rate in WAD format (1e18 = 100%, must be less than 1e18)

***

#### setRWARedemptionFee

Set redemption fee for RWA when swapping into RWA from a stablecoin.

```solidity theme={null}
function setRWARedemptionFee(
    bytes32 stablecoinID,
    bytes32 rwaID,
    uint256 rate
) external;
```

**Access**: Stablecoin delegate contract only

**Parameters**:

* `stablecoinID`: ID of the stablecoin
* `rwaID`: ID of the RWA token
* `rate`: Redemption fee in WAD format (1e18 = 100%, must be less than 1e18)

***

#### setMultiliquidFees

Set the protocol fee tier structure. Fee tiers are volume-based, where larger swaps receive lower fee rates.

```solidity theme={null}
function setMultiliquidFees(FeeTier[] calldata _feeTiers) external onlyRole(OPERATOR_ROLE);
```

**Parameters**:

* `_feeTiers`: Array of fee tiers, each containing `maxVolume` (WAD) and `fee` (WAD)

**Access**: `OPERATOR_ROLE`

**Events**:

```solidity theme={null}
event MultiliquidFeeTiersSet(FeeTier[] feeTiers);
```

<Note>
  This function replaces the entire fee tier structure. There is no modification—only deletion and addition of the complete tier list.
</Note>

***

#### setStablecoinAcceptanceFee

Set acceptance fee charged when a stablecoin delegate accepts another stablecoin as backing (used in stablecoin-to-stablecoin swaps).

```solidity theme={null}
function setStablecoinAcceptanceFee(
    bytes32 stablecoinOutID,
    address stablecoin,
    uint256 rate
) external;
```

**Access**: Stablecoin delegate contract only

**Parameters**:

* `stablecoinOutID`: ID of the stablecoin being issued/minted
* `stablecoin`: Address of the stablecoin being accepted as backing
* `rate`: Acceptance fee in WAD format (1e18 = 100%, must be less than 1e18)

***

#### setStablecoinRedemptionFee

Set redemption fee charged when a stablecoin delegate redeems/burns its stablecoin and gives another stablecoin from custody (used in stablecoin-to-stablecoin swaps).

```solidity theme={null}
function setStablecoinRedemptionFee(
    bytes32 stablecoinOutID,
    address stablecoin,
    uint256 rate
) external;
```

**Access**: Stablecoin delegate contract only

**Parameters**:

* `stablecoinOutID`: ID of the stablecoin being redeemed/burned
* `stablecoin`: Address of the stablecoin being given out from custody
* `rate`: Redemption fee in WAD format (1e18 = 100%, must be less than 1e18)

***

#### pause

Pauses the contract, disabling all swap functionality.

```solidity theme={null}
function pause() external onlyRole(OPERATOR_ROLE);
```

**Access**: `OPERATOR_ROLE`

**Emits**: `Paused(address account)` from OpenZeppelin's PausableUpgradeable

***

#### unpause

Unpauses the contract, re-enabling swap functionality.

```solidity theme={null}
function unpause() external onlyRole(OPERATOR_ROLE);
```

**Access**: `OPERATOR_ROLE`

**Emits**: `Unpaused(address account)` from OpenZeppelin's PausableUpgradeable

***

## Events

### Swap Events

```solidity theme={null}
event SwapIntoRWA(
    bytes32 indexed rwaID,
    bytes32 indexed stablecoinID,
    address indexed user,
    uint256 rwaAmt,
    uint256 stablecoinAmt,
    uint256 feeAmt,
    uint256 redemptionFeeAmt,
    bytes stablecoinMetadata,
    bytes rwaMetadata
);

event SwapIntoRWAExactOut(
    bytes32 indexed rwaID,
    bytes32 indexed stablecoinID,
    address indexed user,
    uint256 rwaAmt,
    uint256 stablecoinAmt,
    uint256 feeAmt,
    uint256 redemptionFeeAmt,
    bytes stablecoinMetadata,
    bytes rwaMetadata
);

event SwapIntoStablecoin(
    bytes32 indexed stablecoinID,
    bytes32 indexed rwaID,
    address indexed user,
    uint256 stablecoinAmt,
    uint256 rwaAmt,
    uint256 feeAmt,
    bytes stablecoinMetadata,
    bytes rwaMetadata
);

event SwapIntoStablecoinExactOut(
    bytes32 indexed stablecoinID,
    bytes32 indexed rwaID,
    address indexed user,
    uint256 stablecoinAmt,
    uint256 rwaAmt,
    uint256 feeAmt,
    bytes stablecoinMetadata,
    bytes rwaMetadata
);

event RWAToRWASwap(
    bytes32 indexed rwaInID,
    bytes32 indexed rwaOutID,
    bytes32 indexed stablecoinID,
    address user,
    uint256 rwaInAmount,
    uint256 rwaOutAmount,
    uint256 protocolFeeAmt,
    uint256 redemptionFeeAmt,
    bytes rwaInMetadata,
    bytes rwaOutMetadata
);

event StablecoinToStablecoinSwap(
    bytes32 indexed stablecoinInID,
    bytes32 indexed stablecoinOutID,
    address indexed user,
    uint256 stablecoinInAmount,
    uint256 stablecoinOutAmount,
    uint256 protocolFeeAmt,
    uint256 acceptanceFeeAmt,
    uint256 redemptionFeeAmt,
    bytes stablecoinInMetadata,
    bytes stablecoinOutMetadata
);
```

### Admin Events

```solidity theme={null}
event RWAAcceptanceSet(
    bytes32 indexed rwaID,
    address indexed delegate,
    address indexed assetAddress,
    uint8 decimals,
    bool accepted
);

event StablecoinAcceptanceSet(
    bytes32 indexed stablecoinID,
    address indexed delegate,
    address indexed assetAddress,
    uint8 decimals,
    bool accepted,
    bool yieldBearing
);

event UpdateRWAUSDValue(bytes32 indexed rwaID, address priceAdapter);
event UpdateStablecoinUSDValue(bytes32 indexed stablecoinID, uint256 value);

event MultiliquidFeeTiersSet(FeeTier[] feeTiers);
event DiscountRateSet(bytes32 indexed stablecoinID, bytes32 indexed rwaID, uint256 rate);
event RedemptionFeeSet(bytes32 indexed stablecoinID, bytes32 indexed rwaID, uint256 rate);

event StablecoinAcceptanceFeeSet(
    bytes32 indexed stablecoinOutID, address indexed stablecoinIn, uint256 rate
);
event StablecoinRedemptionFeeSet(
    bytes32 indexed stablecoinOutID, address indexed stablecoinIn, uint256 rate
);
```

***

## Access Control Roles

**DEFAULT\_ADMIN\_ROLE**: Can upgrade contract and manage all roles

**OPERATOR\_ROLE**:

* Accept new RWAs and stablecoins
* Set price adapters and USD values
* Configure fee tiers
* Pause/unpause the contract

**BLACKLISTER\_ROLE**:

* Manages address blacklisting for compliance purposes

***

<Card title="Next: Stablecoin Delegate Contracts" icon="file-code" href="/evm/contracts/stablecoin-delegate">
  Learn about asset-specific contracts handling stablecoin integration
</Card>
