Skip to content

RWA Vault – Functions

Core Public Vault Ops

depositAsset

depositAsset(address adapter, bytes data, address receiver, uint256 minSharesOut) → uint256

Summary
Deposit an asset through a whitelisted depositable adapter and mint iRAAC shares to receiver.

Usage
- Adapter must be registered and added to the Depositable list.
- Shares minted are proportional to the contributed value vs NAV and total supply.
- A minting fee (bps) may apply; net shares are transferred to receiver.

Parameters

Name Type Description
adapter address Whitelisted depositable adapter
data bytes Adapter-specific calldata (e.g., tokenId)
receiver address Address receiving iRAAC shares
minSharesOut uint256 Minimum net shares expected (slippage bound)

Returns

  • sharesMinted – Net shares minted to receiver (after fees)
TS / ethers
const adapter = "0xAdapter...";
const data = ethers.AbiCoder.defaultAbiCoder().encode(["uint256"],[tokenId]);
const minSharesOut = parseUnits("10", 18);

// Approve adapter to spend the asset
await assetContract.approve(adapter, tokenId);

const tx = await rwaVault.depositAsset(adapter, data, receiver, minSharesOut);
await tx.wait();
Source code
function depositAsset(address adapter, bytes calldata data, address receiver, uint256 minSharesOut)
    external
    override
    onlySupportedDepositableAdapter(adapter)
    notBlacklisted(msg.sender)
    whenNotPaused
    nonReentrant
    returns (uint256 sharesMinted)
{
    return _deposit(adapter, data, receiver, indexTokenMintingFee, minSharesOut);
}

poolDepositAsset

poolDepositAsset(address adapter, bytes data, address receiver, uint256 minSharesOut) → uint256

Summary
Deposit via any supported adapter with zero mint fee. Used by Stability Pool during liquidations and protocol operations.

Stability Pool only

This entrypoint is strictly intended for the Stability Pool.

Parameters

Name Type Description
adapter address Supported adapter (registered)
data bytes Adapter-specific calldata
receiver address Address receiving iRAAC shares
minSharesOut uint256 Minimum net shares expected (slippage bound)

Returns
- sharesMinted

TS / ethers
const tx = await rwaVault.poolDepositAsset(adapter, data, receiver, minSharesOut);
await tx.wait();
Source code
function poolDepositAsset(address adapter, bytes calldata data, address receiver, uint256 minSharesOut)
    external
    onlySupportedAdapter(adapter)
    nonReentrant
    returns (uint256 sharesMinted)
{
    require(msg.sender == stabilityPool, "RWAVault: only stability pool caller");
    return _deposit(adapter, data, receiver, 0, minSharesOut);
}

adminDepositAsset

adminDepositAsset(address adapter, bytes data, bool mint, uint256 minSharesOut)

Summary
Manager operation to deposit assets via an adapter. If mint is true, mint vault shares (zero fee) to the caller; otherwise only deposit the asset without minting.

Atomic operations recommended

When coordinating multi‑step reallocations (e.g., deposit one asset then withdraw another), consider setting mint=false for the first step and pairing with a burn=false withdraw in the same transaction to avoid transient NAV swings.

Parameters

Name Type Description
adapter address Supported adapter
data bytes Adapter-specific calldata
mint bool If true, mints shares to the caller
minSharesOut uint256 Slippage bound when mint=true
TS / ethers
// Peg maintenance example: deposit asset without mint, then withdraw another without burn, atomically
await (await rwaVault.adminDepositAsset(adapterIn, dataIn, false, 0)).wait();
await (await rwaVault.adminWithdrawAsset(adapterOut, dataOut, manager, false, 0)).wait();
Source code
function adminDepositAsset(address adapter, bytes calldata data, bool mint, uint256 minSharesOut)
    external
    onlyManager
    onlySupportedAdapter(adapter)
    nonReentrant
{
    if (mint) {
        _deposit(adapter, data, msg.sender, 0, minSharesOut);
    } else {
        IVaultAssetAdapter(adapter).deposit(data, msg.sender);
    }
    emit AdminDeposit(adapter, data, mint);
}

adminWithdrawAsset

adminWithdrawAsset(address adapter, bytes data, address receiver, bool burn, uint256 maxSharesBurn)

Summary
Manager operation to withdraw an underlying asset from the vault to receiver. If burn=true, burns corresponding shares from the caller prior to withdrawal.

Atomic operations recommended

For paired reallocations (with mint=false on deposit), use burn=false here and bundle in a single transaction so that temporary mint/burn deferrals do not skew NAV mid‑flow.

Parameters

Name Type Description
adapter address Supported adapter
data bytes Adapter-specific calldata
receiver address Recipient of the withdrawn asset
burn bool If true, burns shares from caller
maxSharesBurn uint256 Slippage bound when burn=true
TS / ethers
// Withdraw asset without burning (paired with a previous adminDepositAsset without mint)
await (await rwaVault.adminWithdrawAsset(adapter, data, manager, false, 0)).wait();
Source code
function adminWithdrawAsset(address adapter, bytes calldata data, address receiver, bool burn, uint256 maxSharesBurn)
    external
    onlyManager
    onlySupportedAdapter(adapter)
    nonReentrant
{
    if (receiver == address(0)) revert InvalidAddress();

    uint256 assetValue = IVaultAssetAdapter(adapter).getAssetValue(data);
    if (burn) {
        uint256 sharesToBurn = convertToShares(assetValue);
        if (sharesToBurn > maxSharesBurn) revert SlippageExceeded();
        if (IVaultToken(vaultToken).balanceOf(msg.sender) < sharesToBurn) revert InsufficientBalance();
        IVaultToken(vaultToken).burn(msg.sender, sharesToBurn);
    }

    IVaultAssetAdapter(adapter).withdraw(data, receiver);
    emit AdminWithdraw(adapter, data, receiver, burn);
}

burnVaultToken

burnVaultToken(address from, uint256 amount)

Summary
Burn iRAAC shares from from. Primarily used by the Stability Pool during liquidation settlement to compensate iRAAC holders (reducing supply increases price per share, all else equal).

TS / ethers
await (await rwaVault.burnVaultToken(user, parseUnits("100", 18))).wait();
Source code
function burnVaultToken(address from, uint256 amount) external {
    if (!isManager(msg.sender) && msg.sender != stabilityPool) revert("only manager or stability pool");
    IVaultToken(vaultToken).burn(from, amount);
    emit VaultTokenBurned(from, amount);
}

NFT Redemption

redeemNFT

redeemNFT(address adapter, uint256 tokenId, uint256 maxSharesBurn)

Summary
Burn shares equal to the selected NFT’s current vault value and withdraw the NFT to the caller. The redeemable NFT must match the next random selection computed via VRF.

Flow
1) Verify VRF seed is set and selection is fulfilled.
2) Compute the next (adapter, tokenId) via getNextRandomNFT().
3) Burn required shares and withdraw the NFT.
4) Request a new random seed for the next redemption.

TS / ethers
const [nextAdapter, nextTokenId] = await rwaVault.getNextRandomNFT();
const value = await adapter.getAssetValue(ethers.AbiCoder.defaultAbiCoder().encode(["uint256"],[nextTokenId]));
const maxSharesBurn = await rwaVault.convertToShares(value).then(v => v.mul(101).div(100)); // +1% slippage
await (await rwaVault.redeemNFT(nextAdapter, nextTokenId, maxSharesBurn)).wait();
Source code
function redeemNFT(address _adapter, uint256 _tokenId, uint256 maxSharesBurn) external override nonReentrant whenNotPaused notBlacklisted(msg.sender) {
    if (address(vrfConsumer) == address(0)) revert InvalidVRFAddress();

    (address adapter, uint256 tokenId) = getNextRandomNFT();
    if (adapter != _adapter || tokenId != _tokenId) revert NFTNotRedeemable();

    bytes memory data = abi.encode(tokenId);
    uint256 nftPrice = IVaultAssetAdapter(adapter).getAssetValue(data);
    if (nftPrice == 0) revert InvalidNFT();
    uint256 sharesBurned = convertToShares(nftPrice);
    if (sharesBurned > maxSharesBurn) revert SlippageExceeded();
    if (IVaultToken(vaultToken).balanceOf(msg.sender) < sharesBurned) revert InsufficientBalance();

    IVaultToken(vaultToken).burn(msg.sender, sharesBurned);
    IVaultAssetAdapter(adapter).withdraw(data, msg.sender);
    vrfConsumer.requestRandomWords();

    emit RedeemNFT(msg.sender, IVaultAssetAdapter(adapter).getAssetToken(), tokenId, sharesBurned);
}

getNextRandomNFT

getNextRandomNFT() → (address adapter, uint256 tokenId)

Summary
Return the next redeemable NFT chosen using Chainlink VRF and a simple reservoir sampling across redeemable ERC‑721 adapters.

Selection Logic
- Require VRF fulfillment and derive a seed.
- Iterate redeemable adapters and count only those with non‑zero NFT inventory.
- Use seeded reservoir sampling to pick an adapter, then compute tokenId by modulo into the adapter’s deposited inventory.

Source code
function getNextRandomNFT() public view returns (address adapter, uint256 tokenId) {
    if (address(vrfConsumer) == address(0)) revert InvalidVRFAddress();
    IBaseVRFv2Consumer.RequestStatus memory requestStatus = vrfConsumer.getRequestStatus();
    if (!requestStatus.fulfilled) revert IBaseVRFv2Consumer.RequestNotFulfilled();

    uint256 rand = requestStatus.randomWords[0];
    adapter = _findRandomAdapter(rand);
    tokenId = IERC721VaultAdapter(adapter).getDepositedTokenAtIndex(rand % IERC721VaultAdapter(adapter).getDepositedTokensCount());
    return (adapter, tokenId);
}

requestRandomSeed

requestRandomSeed()

Summary
Public reseed request (when enabled) to fetch a new VRF random seed after the required delay.

Source code
function requestRandomSeed() external notBlacklisted(msg.sender) whenNotPaused {
    if (!allowVRFRequest) revert("public requests disabled");
    require(block.timestamp - vrfConsumer.getLastFulfillTimestamp() >= vrfRequestDelay, "you cannot send request");
    vrfConsumer.requestRandomWords();
    emit RandomSeedRequested(block.timestamp);
}

Share Accounting & NAV

convertToShares

convertToShares(uint256 assetAmount) → uint256

Summary
Convert a value amount into shares using current NAV and total supply (rounding up).

Source code
function convertToShares(uint256 assetAmount) public view override returns (uint256) {
    uint256 supply = IVaultToken(vaultToken).totalSupply();
    uint256 assets = totalAssets();
    if (supply == 0 || assets == 0) return assetAmount;
    return (assetAmount * supply + assets - 1) / assets;
}

convertToAssets

convertToAssets(uint256 shares) → uint256

Summary
Convert shares into value amount using current NAV and total supply.

Source code
function convertToAssets(uint256 shares) public view override returns (uint256) {
    uint256 supply = IVaultToken(vaultToken).totalSupply();
    uint256 assets = totalAssets();
    if (assets == 0 || supply == 0) return shares;
    else return (shares * assets) / supply;
}

previewDeposit

previewDeposit(uint256 assetAmount) → uint256

Summary
Estimate shares minted for a given value amount (rounded down).

Source code
function previewDeposit(uint256 assetAmount) external view override returns (uint256 shares) {
    uint256 supply = IVaultToken(vaultToken).totalSupply();
    uint256 total  = totalAssets();
    if (supply == 0 || total == 0) return assetAmount;
    return (assetAmount * supply) / total;
}

previewWithdraw

previewWithdraw(uint256 assetAmount) → uint256

Summary
Estimate shares burned for withdrawing a given value amount (rounded up).

Source code
function previewWithdraw(uint256 assetAmount) external view override returns (uint256 shares){
    uint256 supply = IVaultToken(vaultToken).totalSupply();
    uint256 total  = totalAssets();
    if (supply == 0 || total == 0) return assetAmount;
    return (assetAmount * supply + total - 1) / total;
}

pricePerShare

pricePerShare() → uint256

Summary
Current price per 1e18 share, computed via convertToAssets(1e18).

Source code
function pricePerShare() external view override returns (uint256) {
    return convertToAssets(1e18);
}

totalAssets

totalAssets() → uint256

Summary
Aggregate NAV across all registered adapters by summing each adapter’s totalValue().

Source code
function totalAssets() public view override returns (uint256 totalValue) {
    for (uint256 i = 0; i < adapters.length; i++) {
        totalValue += IVaultAssetAdapter(adapters[i]).totalValue();
    }
    return totalValue;
}

underlyingVaultToken

underlyingVaultToken() → address

Summary
Return the vault’s ERC‑20 share token (iRAAC) address.

Source code
function underlyingVaultToken() external view override returns (address) {
    return vaultToken;
}