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 toreceiver
(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
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
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
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).
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).
convertToAssets
¶
convertToAssets(uint256 shares) → uint256
Summary
Convert shares into value amount using current NAV and total supply.
previewDeposit
¶
previewDeposit(uint256 assetAmount) → uint256
Summary
Estimate shares minted for a given value amount (rounded down).
previewWithdraw
¶
previewWithdraw(uint256 assetAmount) → uint256
Summary
Estimate shares burned for withdrawing a given value amount (rounded up).
pricePerShare
¶
pricePerShare() → uint256
Summary
Current price per 1e18 share, computed via convertToAssets(1e18)
.
totalAssets
¶
totalAssets() → uint256
Summary
Aggregate NAV across all registered adapters by summing each adapter’s totalValue()
.