MetaVaultWrapper
The MetaVaultWrapper is the user-facing contract for MetaVaults. It implements ERC-7540 (asynchronous deposit/redeem), ERC-7575, and ERC-165. Wrapper shares are ERC-20 tokens representing the depositor's pro-rata claim on the underlying infrastructure vault.
The wrapper delegates asset custody to an infrastructure vault (AsyncVault) and maintains its own epoch tracking to correctly account for per-user request balances.
The implementation is maintained in Spectra's private MetaVault contracts repository.
Methods
requestDeposit
function requestDeposit(
uint256 assets,
address controller,
address owner
) external nonReentrant whenNotPaused returns (uint256 requestId)Requests a deposit of assets (underlying token) into the MetaVault. Assets are transferred from owner to the wrapper and forwarded to the infrastructure vault. The request is recorded for the current epoch.
If the controller has a claimable deposit from a previous epoch, it is automatically claimed first.
msg.sender must be owner or an approved operator of owner. The owner must approve the wrapper for the underlying asset before calling this function.
| Input Parameter | Type | Description |
|---|---|---|
assets | uint256 | Amount of underlying assets to deposit. Must be > 0. |
controller | address | Address that the deposit request is recorded for |
owner | address | Address that the assets are transferred from |
| Return Parameter | Type | Description |
|---|---|---|
requestId | uint256 | Always returns 0 (request ID is not used in this implementation) |
decreaseDepositRequest
function decreaseDepositRequest(uint256 assets) external nonReentrant whenNotPausedDecreases the caller's pending deposit request by assets. The assets are refunded to msg.sender.
| Input Parameter | Type | Description |
|---|---|---|
assets | uint256 | Amount of assets to remove from the pending request. Must be > 0 and ≤ pending balance. |
deposit
function deposit(
uint256 assets,
address receiver,
address controller
) external nonReentrant whenNotPaused returns (uint256 shares)Claims all claimable shares for the controller from a previously settled deposit request. Wrapper shares are minted to receiver.
The assets parameter is not used — all claimable shares are always claimed in full.
| Input Parameter | Type | Description |
|---|---|---|
assets | uint256 | Not used (included for ERC-7540 interface compliance) |
receiver | address | Address that will receive the minted wrapper shares |
controller | address | Address whose claimable deposit is being claimed |
| Return Parameter | Type | Description |
|---|---|---|
shares | uint256 | Amount of wrapper shares minted to receiver |
requestRedeem
function requestRedeem(
uint256 shares,
address controller,
address owner
) external nonReentrant whenNotPaused returns (uint256 requestId)Requests a redemption of shares (wrapper shares). Shares are burned from owner and the equivalent infrastructure vault shares are queued for redemption.
If the controller has a claimable redeem from a previous epoch, it is automatically claimed first.
| Input Parameter | Type | Description |
|---|---|---|
shares | uint256 | Amount of wrapper shares to redeem. Must be > 0. |
controller | address | Address that the redeem request is recorded for |
owner | address | Address that the shares are burned from |
| Return Parameter | Type | Description |
|---|---|---|
requestId | uint256 | Always returns 0 |
decreaseRedeemRequest
function decreaseRedeemRequest(uint256 shares) external nonReentrant whenNotPausedDecreases the caller's pending redeem request by shares. The shares are minted back to msg.sender.
| Input Parameter | Type | Description |
|---|---|---|
shares | uint256 | Amount of shares to remove from the pending request. Must be > 0 and ≤ pending balance. |
redeem
function redeem(
uint256 shares,
address receiver,
address controller
) public nonReentrant whenNotPaused returns (uint256 assets)Claims all claimable assets for the controller from a previously settled redeem request. Assets are transferred to receiver.
The shares parameter is not used — all claimable assets are always claimed in full.
| Input Parameter | Type | Description |
|---|---|---|
shares | uint256 | Not used (included for ERC-7540 interface compliance) |
receiver | address | Address that will receive the underlying assets |
controller | address | Address whose claimable redeem is being claimed |
| Return Parameter | Type | Description |
|---|---|---|
assets | uint256 | Amount of underlying assets transferred to receiver |
setOperator
function setOperator(address operator, bool approved) external returns (bool)Approves or revokes operator to act on behalf of msg.sender for deposit/redeem operations.
| Input Parameter | Type | Description |
|---|---|---|
operator | address | Address to approve/revoke as operator |
approved | bool | true to approve, false to revoke |
updateEpochID
function updateEpochID() externalSynchronizes the wrapper's internal epoch ID with the infrastructure vault's current epoch. Called automatically by requestDeposit, deposit, requestRedeem, and redeem, but can also be called manually.
View Methods
getInfraVault
function getInfraVault() public view returns (address)Returns the address of the underlying infrastructure vault.
isOperator
function isOperator(address controller, address operator) external view returns (bool status)Returns whether operator is approved to act on behalf of controller.
totalVaultShares
function totalVaultShares() public view returns (uint256)Returns the total infrastructure vault shares held by the wrapper.
epochId
function epochId() external view returns (uint256)Returns the current epoch ID from the infrastructure vault.
lastUserDepositRequestEpoch
function lastUserDepositRequestEpoch(address user) external view returns (uint256)Returns the epoch ID of the user's last deposit request.
lastUserRedeemRequestEpoch
function lastUserRedeemRequestEpoch(address user) external view returns (uint256)Returns the epoch ID of the user's last redeem request.
convertToShares
function convertToShares(uint256 assets) public view returns (uint256 shares)Converts assets to wrapper shares using the last settled epoch rate.
convertToShares
function convertToShares(uint256 assets, uint256 requestID) external view returns (uint256 shares)Converts assets to wrapper shares using a specific epoch rate.
convertToAssets
function convertToAssets(uint256 shares) public view returns (uint256 assets)Converts wrapper shares to assets using the last settled epoch rate.
convertToAssets
function convertToAssets(uint256 shares, uint256 requestID) external view returns (uint256 assets)Converts wrapper shares to assets using a specific epoch rate.
maxDeposit
function maxDeposit(address receiver) public view returns (uint256 maxAssets)Returns the maximum amount the receiver can claim via deposit. Returns 0 if paused or if the user's last deposit request is for the current (unsettled) epoch.
maxRedeem
function maxRedeem(address owner) public view returns (uint256 maxShares)Returns the maximum amount the owner can claim via redeem. Returns 0 if paused or if the user's last redeem request is for the current (unsettled) epoch.
pendingDepositRequest
function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256 assets)Returns the amount of assets the controller has pending in the current epoch's deposit queue.
claimableDepositRequest
function claimableDepositRequest(uint256 requestId, address controller) external view returns (uint256 assets)Returns the amount of assets the controller can claim from a settled deposit request.
pendingRedeemRequest
function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256 shares)Returns the amount of shares the controller has pending in the current epoch's redeem queue.
claimableRedeemRequest
function claimableRedeemRequest(uint256 requestID, address controller) external view returns (uint256 shares)Returns the amount of shares the controller can claim from a settled redeem request.
totalAssets
function totalAssets() public view returns (uint256)Returns an estimate of the wrapper's total assets using the last settled epoch rate: convertToAssets(totalSupply()).
decimals
function decimals() public view returns (uint8)Returns the decimals of the underlying asset.
share
function share() external view returns (address)Returns the address of the share token (the wrapper itself). ERC-7575 compliance.
supportsInterface
function supportsInterface(bytes4 interfaceId) public view returns (bool)Returns true for IERC165, IERC7540, IERC7575, IERC7540Deposit, IERC7540Redeem, and IERC7540Operator.
previewDeposit, previewRedeem, previewWithdraw, and previewMint are not implemented and will revert, as specified by ERC-7540 for asynchronous vaults.
Events
DepositRequest
event DepositRequest(
address indexed controller,
address indexed owner,
uint256 indexed requestId,
address sender,
uint256 assets
)Emitted when a deposit request is created.
RedeemRequest
event RedeemRequest(
address indexed controller,
address indexed owner,
uint256 indexed requestId,
address sender,
uint256 shares
)Emitted when a redeem request is created.
OperatorSet
event OperatorSet(address indexed controller, address indexed operator, bool approved)Emitted when an operator approval is set or revoked.
DecreaseDepositRequest
event DecreaseDepositRequest(
uint256 indexed epochId,
address indexed owner,
uint256 indexed previousRequestedAssets,
uint256 newRequestedAssets
)Emitted when a deposit request is decreased.
DecreaseRedeemRequest
event DecreaseRedeemRequest(
uint256 indexed epochId,
address indexed owner,
uint256 indexed previousRequestedShares,
uint256 newRequestedShares
)Emitted when a redeem request is decreased.
ClaimPendingDeposit
event ClaimPendingDeposit(
uint256 indexed epochId,
uint256 indexed assetsClaimed,
uint256 indexed wrapperSharesReceived
)Emitted when the wrapper claims pending deposits from the infrastructure vault.
ClaimPendingRedeem
event ClaimPendingRedeem(
uint256 indexed epochId,
uint256 indexed wrapperSharesClaimed,
uint256 indexed assetsReceived
)Emitted when the wrapper claims pending redeems from the infrastructure vault.
MetaVaultWrapperInitialized
event MetaVaultWrapperInitialized(
address indexed owner,
address indexed infraVault,
address indexed wrapper
)Emitted when the wrapper is initialized.
Errors
| Error | Description |
|---|---|
ZeroAddress() | An address parameter is address(0) |
ZeroAssets() | Assets amount is 0 |
ZeroShares() | Shares amount is 0 |
ERC7540InvalidOperator() | Caller is not the owner or an approved operator |
ZeroDecreaseAmount() | Decrease amount is 0 |
DecreaseAmountExceedsPending(uint256 pendingAmount, uint256 decreaseAmount) | Decrease amount exceeds the pending balance |
InvalidUnderlying() | Underlying asset does not match the infrastructure vault's asset |
NoClaimAvailable(address owner) | No settled request available to claim |