Overview
RWA delegate contracts provide optional, asset-specific risk management and compliance controls for Real World Asset tokens. They are only deployed when custom risk controls beyond the token’s native functionality are required.
Base Contract : src/RWADelegate.sol
RWA delegates are optional . If an RWA token already implements sufficient controls (e.g., built-in KYC, transfer restrictions), no delegate is needed.
When to Use RWA Delegates
Deploy an RWA delegate when you need:
Volume limits or time-based restrictions
Additional compliance metadata validation
Pause capabilities specific to the RWA
Risk management beyond token-native controls
Core Interface
interface IRWADelegate {
// Risk validation before RWA leaves the system
function checkRWAOut (
address user ,
uint256 amount ,
bytes calldata metadata
) external returns ( bool );
// Risk validation before RWA enters the system
function checkRWAIn (
address user ,
uint256 amount ,
bytes calldata metadata
) external returns ( bool );
// Pause controls
function pause () external ;
function unpause () external ;
}
Key Functions
checkRWAOut
Validates RWA token transfers out of the protocol (when user receives RWA).
function checkRWAOut (
address user ,
uint256 amount ,
bytes calldata metadata
) external onlyRole ( MULTILIQUID_SWAP_CONTRACT ) returns ( bool );
Called During :
Stablecoin → RWA swaps
Stablecoin → RWA (in RWA-to-RWA swaps)
Typical Validations :
Check daily volume limits
Verify compliance metadata
Validate user eligibility
Enforce time-based restrictions
Returns : true if validation passes, reverts otherwise
checkRWAIn
Validates RWA token transfers into the protocol (when user provides RWA).
function checkRWAIn (
address user ,
uint256 amount ,
bytes calldata metadata
) external onlyRole ( MULTILIQUID_SWAP_CONTRACT ) returns ( bool );
Called During :
RWA → Stablecoin swaps
RWA → RWA swaps (from source RWA)
Typical Validations :
Check incoming volume limits
Validate token source
Verify compliance requirements
Returns : true if validation passes, reverts otherwise
Pause Controls
function pause () external onlyRole ( ISSUER_ADMIN_ROLE );
function unpause () external onlyRole ( ISSUER_ADMIN_ROLE );
Effect : When paused, all swaps involving this RWA are blocked
Access : RWA issuer admin only
Example: ULTRA Delegate
The ULTRA RWA delegate implements daily volume limits with timezone-specific resets.
Features
Daily Volume Limits :
Configurable per-wallet limits
Cumulative tracking over rolling 24-hour window
Automatic reset at 2pm Singapore Time (UTC+8)
Implementation :
mapping ( address => uint256 ) public dailyVolume;
mapping ( address => uint256 ) public lastResetTime;
mapping ( address => uint256 ) public volumeLimit;
uint256 public constant RESET_HOUR = 6 ; // 2pm SGT = 6am UTC
function checkRWAOut ( address user , uint256 amount , bytes calldata )
external
override
returns ( bool )
{
// Reset if new day
if ( shouldReset (user)) {
dailyVolume[user] = 0 ;
lastResetTime[user] = block .timestamp;
}
// Check limit
require (
dailyVolume[user] + amount <= volumeLimit[user],
"Daily volume limit exceeded"
);
// Update volume
dailyVolume[user] += amount;
return true ;
}
function shouldReset ( address user ) internal view returns ( bool ) {
uint256 lastReset = lastResetTime[user];
uint256 currentHour = ( block .timestamp / 3600 ) % 24 ;
uint256 lastResetHour = (lastReset / 3600 ) % 24 ;
// Reset if crossed the reset hour
return currentHour >= RESET_HOUR && lastResetHour < RESET_HOUR;
}
Administrative Functions
// Set volume limit for a user
function setVolumeLimit ( address user , uint256 limit )
external
onlyRole ( ISSUER_ADMIN_ROLE );
// Get current volume status
function getVolumeStatus ( address user )
external
view
returns ( uint256 used , uint256 limit , uint256 available );
Access Control
DEFAULT_ADMIN_ROLE : Can upgrade delegate, manage roles
ISSUER_ADMIN_ROLE : RWA issuer’s administrative role
Configure volume limits
Set risk parameters
Pause/unpause delegate
Update compliance requirements
MULTILIQUID_SWAP_CONTRACT : Granted to MultiliquidSwap contract
Call checkRWAIn() and checkRWAOut()
Trigger risk validations
OPERATOR_ROLE : Operational management
Events
event VolumeRecorded (
address indexed user ,
uint256 amount ,
uint256 newTotal ,
bool isOutbound
);
event VolumeLimitUpdated (
address indexed user ,
uint256 newLimit
);
event DelegatePaused ( address indexed pauser );
event DelegateUnpaused ( address indexed unpauser );
Integration
Without RWA Delegate
If no RWA delegate is needed:
// Register RWA without delegate
multiliquidSwap. setRWAAcceptance (
rwaID,
address ( 0 ), // No delegate
rwaTokenAddress,
true // Accepted
);
// Set price adapter
multiliquidSwap. setRwaPriceAdapter (rwaID, priceAdapter);
With RWA Delegate
If custom risk controls are needed:
// Deploy delegate
RWADelegate delegate = new ULTRADelegate ();
delegate. initialize (multiliquidAdmin, issuerAdmin, multiliquidSwapAddress, rwaID, rwaTokenAddress);
// Register RWA with delegate
multiliquidSwap. setRWAAcceptance (
rwaID,
address (delegate), // Delegate address
rwaTokenAddress,
true // Accepted
);
// Set price adapter
multiliquidSwap. setRwaPriceAdapter (rwaID, priceAdapter);
Next: Price Adapters Learn about the modular oracle system providing USD-denominated pricing