> ## 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.

# RWA Delegate Contracts

> Optional risk management contracts for Real World Asset tokens

## 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`

<Info>
  RWA delegates are **optional**. If an RWA token already implements sufficient controls (e.g., built-in KYC, transfer restrictions), no delegate is needed.
</Info>

## 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

```solidity theme={null}
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);
}
```

## Key Functions

### checkRWAOut

Validates RWA token transfers out of the protocol (when user receives RWA).

```solidity theme={null}
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).

```solidity theme={null}
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

<Note>
  `pause()` and `unpause()` are defined on the concrete `RWADelegate` implementation contract, not on the `IRWADelegate` interface.
</Note>

```solidity theme={null}
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**:

* Single global daily volume limit applied to all users
* Per-user volume tracking compared against the global limit
* Automatic reset at 2pm Singapore Time (UTC+8)

**Implementation**:

```solidity theme={null}
struct UserVolumeData {
    uint256 volume;       // Cumulative volume for the current day
    uint32 lastResetDay;  // Day number of last reset
    uint96 reserved;
}

uint256 public dailyVolumeLimit;  // Global limit applied to every user
mapping(address => UserVolumeData) public userVolumes;

uint256 public constant RESET_HOUR = 6;  // 2pm SGT = 6am UTC

function checkRWAOut(address user, uint256 amount, bytes calldata)
    external
    override
    returns (bool)
{
    UserVolumeData storage data = userVolumes[user];
    uint32 currentDay = _currentDay();

    // Reset if new day
    if (data.lastResetDay < currentDay) {
        data.volume = 0;
        data.lastResetDay = currentDay;
    }

    // Check against the global daily volume limit
    require(
        data.volume + amount <= dailyVolumeLimit,
        "Daily volume limit exceeded"
    );

    // Update user volume
    data.volume += amount;

    return true;
}
```

### Administrative Functions

```solidity theme={null}
// Set the global daily volume limit (applies to all users)
function setDailyVolumeLimit(uint256 limit)
    external
    onlyRole(ISSUER_ADMIN_ROLE);

// Get current volume status for a specific user
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 the global daily volume limit
* 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

```solidity theme={null}
event VolumeRecorded(
    address indexed user,
    uint256 amount,
    uint256 newTotal,
    bool isOutbound
);

event DailyVolumeLimitUpdated(
    uint256 newLimit
);

event DelegatePaused(address indexed pauser);
event DelegateUnpaused(address indexed unpauser);
```

***

## Integration

### Without RWA Delegate

If no RWA delegate is needed:

```solidity theme={null}
// 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:

```solidity theme={null}
// 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);
```

***

<Card title="Next: Price Adapters" icon="file-code" href="/evm/contracts/price-adapters">
  Learn about the modular oracle system providing USD-denominated pricing
</Card>
