Overview
TheMultiliquidSwapV2 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/v2/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
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
- IMultiliquidSwapV2: Interface implementation
Core Functions
Swap Functions
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 (
calculateStableAmt, calculateRWAAmt, etc.) rather than applying arbitrary slippage tolerances. The protocol pricing is not subject to market slippage like AMM DEXs.See the Integration Guide for code examples showing proper usage of calculation functions.swapIntoStablecoin
Swap RWA tokens for stablecoins (ExactIn variant).inputs.stablecoinID: ID of target stablecoininputs.stablecoinAmount: Minimum stablecoin amount to receiveinputs.rwaID: ID of source RWA tokeninputs.rwaAmount: Exact RWA amount to spendinputs.stablecoinMetadata: Metadata for stablecoin delegateinputs.rwaMetadata: Metadata for RWA delegate
SwapExecuted(user, rwaID, stablecoinID, rwaAmount, stablecoinAmount, fee)
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
swapIntoStablecoinExactOut
Swap RWA tokens for stablecoins (ExactOut variant).inputs.stablecoinID: ID of target stablecoininputs.stablecoinAmount: Exact stablecoin amount to receiveinputs.rwaID: ID of source RWA tokeninputs.rwaAmount: Maximum RWA amount willing to spendinputs.stablecoinMetadata: Metadata for stablecoin delegateinputs.rwaMetadata: Metadata for RWA delegate
swapIntoRWA
Swap stablecoins for RWA tokens (ExactIn variant).inputs.rwaID: ID of target RWA tokeninputs.rwaAmount: Minimum RWA amount to receiveinputs.stablecoinID: ID of source stablecoininputs.stablecoinAmount: Exact stablecoin amount to spendinputs.stablecoinMetadata: Metadata for stablecoin delegateinputs.rwaMetadata: Metadata for RWA delegate
SwapExecuted(user, stablecoinID, rwaID, stablecoinAmount, rwaAmount, fee)
Example:
swapIntoRWAExactOut
Swap stablecoins for RWA tokens (ExactOut variant).inputs.rwaID: ID of target RWA tokeninputs.rwaAmount: Exact RWA amount to receiveinputs.stablecoinID: ID of source stablecoininputs.stablecoinAmount: Maximum stablecoin amount willing to spendinputs.stablecoinMetadata: Metadata for stablecoin delegateinputs.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.inputs.exactOut: Boolean indicating exactOut (true) or exactIn (false)inputs.stablecoinID: ID of stablecoin used for pricinginputs.rwaInID: ID of source RWAinputs.rwaInAmount: RWA input amount (exact if exactOut=false, max if exactOut=true)inputs.rwaOutID: ID of target RWAinputs.rwaOutAmount: RWA output amount (min if exactOut=false, exact if exactOut=true)inputs.rwaInMetadata: Metadata for source RWA delegateinputs.rwaOutMetadata: Metadata for target RWA delegate
- User provides
rwaIntokens - Protocol calculates equivalent value
- Protocol calculates equivalent value in
rwaOuttokens - User receives
rwaOuttokens - Fees deducted from output
swapStablecoinToStablecoin
Swap between two stablecoins using a specific stablecoinDelegate based onuseDelegateForStablecoinOut. The delegate chosen determines fees.
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 stablecoininputs.stablecoinInAmount: Input amountinputs.stablecoinOutID: ID of target stablecoininputs.stablecoinOutAmount: Output amountinputs.stablecoinInMetadata: Metadata for source stablecoin delegateinputs.stablecoinOutMetadata: Metadata for target stablecoin delegate
Calculation/View Functions
The contract provides view functions for off-chain quote generation, with one calculation function corresponding to each swap function.calculateRWAAmt
Calculate RWA output for a given stablecoin input (forswapIntoRWA).
rwaAmt: RWA amount user will receive (after fees)feeAmt: Protocol fee chargedredemptionFeeAmt: Redemption fee charged by stablecoin issuer
calculateStablecoinRequired
Calculate stablecoin input required for exact RWA output (forswapIntoRWAExactOut).
stablecoinRequired: Stablecoin amount needed to receive exact RWA outputfeeAmt: Protocol fee chargedredemptionFeeAmt: Redemption fee charged by stablecoin issuer
calculateStableAmt
Calculate stablecoin output for a given RWA input (forswapIntoStablecoin).
stableAmt: Stablecoin amount user will receive (after fees)feeAmt: Protocol fee charged
calculateRWARequired
Calculate RWA input required for exact stablecoin output (forswapIntoStablecoinExactOut).
rwaRequired: RWA amount needed to receive exact stablecoin outputfeeAmt: Protocol fee charged
calculateRWAToRWA
Calculate amounts for RWA-to-RWA swap (forswapRWAToRWA).
stablecoinID: ID of stablecoin used for pricingrwaInID: ID of input RWA tokenrwaOutID: ID of output RWA tokenrwaInAmount: 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)
RWAToRWAReturnParams):
rwaInAmount: RWA input amount requiredrwaOutAmount: RWA output amount receivedprotocolFeeAmt: Protocol fee chargedredemptionFeeAmt: Total redemption fees (both RWAs)
calculateStablecoinToStablecoin
Calculate amounts for stablecoin-to-stablecoin swap (forswapStablecoinToStablecoin).
exactOut: Boolean indicating exactOut (true) or exactIn (false)useDelegateForStablecoinOut: Route through stablecoinOut delegate (true) or stablecoinIn delegate (false)stablecoinInID: ID of input stablecoinstablecoinInAmount: Input amount (exact if exactOut=false, max if exactOut=true)stablecoinOutID: ID of output stablecoinstablecoinOutAmount: Output amount (min if exactOut=false, exact if exactOut=true)
StablecoinToStablecoinReturnParams):
stablecoinInAmount: Stablecoin input amount requiredstablecoinOutAmount: Stablecoin output amount receivedprotocolFeeAmt: Protocol fee chargedacceptanceFeeAmt: Acceptance fee charged by issuerredemptionFeeAmt: Redemption fee charged by issuer
Administrative Functions
setRWAAcceptance
Register or update an RWA token in the protocol.rwaID: Unique identifier for the RWA (keccak256 of lowercase address)_delegate: Address of RWA delegate contract (address(0) if no delegate)_assetAddress: Address of the RWA token contract_accepted:trueto accept,falseto remove
OPERATOR_ROLE
Events:
setStablecoinAcceptance
Register or update a stablecoin in the protocol.stablecoinID: Unique identifier for the stablecoin_delegate: Address of stablecoin delegate contract_assetAddress: Address of the stablecoin token contract_accepted:trueto accept,falseto remove
OPERATOR_ROLE
Events:
setStablecoinAcceptanceForSwap
Register a stablecoin for swap-only mode (without delegate).OPERATOR_ROLE
setRwaPriceAdapter
Set or update the price adapter for an RWA.OPERATOR_ROLE
Events:
setStablecoinUSDValue
Set the USD value for a stablecoin (usually 1e18 for $1.00 pegged stablecoins).OPERATOR_ROLE
Events:
setRWADiscountRate
Set discount rate for RWA when swapping from a specific stablecoin.stablecoinID: ID of the stablecoinrwaID: ID of the RWA tokenrate: 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.stablecoinID: ID of the stablecoinrwaID: ID of the RWA tokenrate: 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._feeTiers: Array of fee tiers, each containingmaxVolume(WAD) andfee(WAD)
OPERATOR_ROLE
Events:
This function replaces the entire fee tier structure. There is no modification—only deletion and addition of the complete tier list.
setStablecoinAcceptanceFee
Set acceptance fee charged when a stablecoin delegate accepts another stablecoin as backing (used in stablecoin-to-stablecoin swaps).stablecoinOutID: ID of the stablecoin being issued/mintedstablecoin: Address of the stablecoin being accepted as backingrate: 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).stablecoinOutID: ID of the stablecoin being redeemed/burnedstablecoin: Address of the stablecoin being given out from custodyrate: Redemption fee in WAD format (1e18 = 100%, must be less than 1e18)
pause
Pauses the contract, disabling all swap functionality.OPERATOR_ROLE
Emits: Paused(address account) from OpenZeppelin’s PausableUpgradeable
unpause
Unpauses the contract, re-enabling swap functionality.OPERATOR_ROLE
Emits: Unpaused(address account) from OpenZeppelin’s PausableUpgradeable
Events
Swap Events
Admin Events
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
Next: Stablecoin Delegate Contracts
Learn about asset-specific contracts handling stablecoin integration