> For the complete documentation index, see [llms.txt](https://dev.spectra.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.spectra.finance/metavaults/contract-functions/metavault-wrapper.md).

# MetaVaultWrapper

The MetaVaultWrapper is the user-facing contract for MetaVaults. It implements [ERC-7540](https://eips.ethereum.org/EIPS/eip-7540) (asynchronous deposit/redeem), [ERC-7575](https://eips.ethereum.org/EIPS/eip-7575), and [ERC-165](https://eips.ethereum.org/EIPS/eip-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.

Code for MetaVaultWrapper.sol can be found on [GitHub](https://github.com/spectra-finance/metavaults-V1/blob/main/src/MetaVaultWrapper.sol).

## Methods

### requestDeposit

```solidity
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.

{% hint style="warning" %}
`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.
{% endhint %}

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>Amount of underlying assets to deposit. Must be > 0.</td></tr><tr><td><code>controller</code></td><td>address</td><td>Address that the deposit request is recorded for</td></tr><tr><td><code>owner</code></td><td>address</td><td>Address that the assets are transferred from</td></tr></tbody></table>

<table><thead><tr><th width="190">Return Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>requestId</code></td><td>uint256</td><td>Always returns 0 (request ID is not used in this implementation)</td></tr></tbody></table>

### decreaseDepositRequest

```solidity
function decreaseDepositRequest(uint256 assets) external nonReentrant whenNotPaused
```

Decreases the caller's pending deposit request by `assets`. The assets are refunded to `msg.sender`.

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>Amount of assets to remove from the pending request. Must be > 0 and ≤ pending balance.</td></tr></tbody></table>

### deposit

```solidity
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`.

{% hint style="info" %}
The `assets` parameter is not used — all claimable shares are always claimed in full.
{% endhint %}

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>Not used (included for ERC-7540 interface compliance)</td></tr><tr><td><code>receiver</code></td><td>address</td><td>Address that will receive the minted wrapper shares</td></tr><tr><td><code>controller</code></td><td>address</td><td>Address whose claimable deposit is being claimed</td></tr></tbody></table>

<table><thead><tr><th width="190">Return Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>Amount of wrapper shares minted to <code>receiver</code></td></tr></tbody></table>

### requestRedeem

```solidity
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.

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>Amount of wrapper shares to redeem. Must be > 0.</td></tr><tr><td><code>controller</code></td><td>address</td><td>Address that the redeem request is recorded for</td></tr><tr><td><code>owner</code></td><td>address</td><td>Address that the shares are burned from</td></tr></tbody></table>

<table><thead><tr><th width="190">Return Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>requestId</code></td><td>uint256</td><td>Always returns 0</td></tr></tbody></table>

### decreaseRedeemRequest

```solidity
function decreaseRedeemRequest(uint256 shares) external nonReentrant whenNotPaused
```

Decreases the caller's pending redeem request by `shares`. The shares are minted back to `msg.sender`.

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>Amount of shares to remove from the pending request. Must be > 0 and ≤ pending balance.</td></tr></tbody></table>

### redeem

```solidity
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`.

{% hint style="info" %}
The `shares` parameter is not used — all claimable assets are always claimed in full.
{% endhint %}

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>Not used (included for ERC-7540 interface compliance)</td></tr><tr><td><code>receiver</code></td><td>address</td><td>Address that will receive the underlying assets</td></tr><tr><td><code>controller</code></td><td>address</td><td>Address whose claimable redeem is being claimed</td></tr></tbody></table>

<table><thead><tr><th width="190">Return Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>Amount of underlying assets transferred to <code>receiver</code></td></tr></tbody></table>

### setOperator

```solidity
function setOperator(address operator, bool approved) external returns (bool)
```

Approves or revokes `operator` to act on behalf of `msg.sender` for deposit/redeem operations.

<table><thead><tr><th width="190">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>operator</code></td><td>address</td><td>Address to approve/revoke as operator</td></tr><tr><td><code>approved</code></td><td>bool</td><td><code>true</code> to approve, <code>false</code> to revoke</td></tr></tbody></table>

### updateEpochID

```solidity
function updateEpochID() external
```

Synchronizes 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

```solidity
function getInfraVault() public view returns (address)
```

Returns the address of the underlying infrastructure vault.

### isOperator

```solidity
function isOperator(address controller, address operator) external view returns (bool status)
```

Returns whether `operator` is approved to act on behalf of `controller`.

### totalVaultShares

```solidity
function totalVaultShares() public view returns (uint256)
```

Returns the total infrastructure vault shares held by the wrapper.

### epochId

```solidity
function epochId() external view returns (uint256)
```

Returns the current epoch ID from the infrastructure vault.

### lastUserDepositRequestEpoch

```solidity
function lastUserDepositRequestEpoch(address user) external view returns (uint256)
```

Returns the epoch ID of the user's last deposit request.

### lastUserRedeemRequestEpoch

```solidity
function lastUserRedeemRequestEpoch(address user) external view returns (uint256)
```

Returns the epoch ID of the user's last redeem request.

### convertToShares

```solidity
function convertToShares(uint256 assets) public view returns (uint256 shares)
```

Converts `assets` to wrapper shares using the **last settled epoch** rate.

### convertToShares

```solidity
function convertToShares(uint256 assets, uint256 requestID) external view returns (uint256 shares)
```

Converts `assets` to wrapper shares using a **specific epoch** rate.

### convertToAssets

```solidity
function convertToAssets(uint256 shares) public view returns (uint256 assets)
```

Converts wrapper `shares` to assets using the **last settled epoch** rate.

### convertToAssets

```solidity
function convertToAssets(uint256 shares, uint256 requestID) external view returns (uint256 assets)
```

Converts wrapper `shares` to assets using a **specific epoch** rate.

### maxDeposit

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

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

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

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

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

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

```solidity
function totalAssets() public view returns (uint256)
```

Returns an estimate of the wrapper's total assets using the last settled epoch rate: `convertToAssets(totalSupply())`.

### decimals

```solidity
function decimals() public view returns (uint8)
```

Returns the decimals of the underlying asset.

### share

```solidity
function share() external view returns (address)
```

Returns the address of the share token (the wrapper itself). ERC-7575 compliance.

### supportsInterface

```solidity
function supportsInterface(bytes4 interfaceId) public view returns (bool)
```

Returns `true` for IERC165, IERC7540, IERC7575, IERC7540Deposit, IERC7540Redeem, and IERC7540Operator.

{% hint style="warning" %}
`previewDeposit`, `previewRedeem`, `previewWithdraw`, and `previewMint` are not implemented and will revert, as specified by ERC-7540 for asynchronous vaults.
{% endhint %}

## Events

### DepositRequest

```solidity
event DepositRequest(
    address indexed controller,
    address indexed owner,
    uint256 indexed requestId,
    address sender,
    uint256 assets
)
```

Emitted when a deposit request is created.

### RedeemRequest

```solidity
event RedeemRequest(
    address indexed controller,
    address indexed owner,
    uint256 indexed requestId,
    address sender,
    uint256 shares
)
```

Emitted when a redeem request is created.

### OperatorSet

```solidity
event OperatorSet(address indexed controller, address indexed operator, bool approved)
```

Emitted when an operator approval is set or revoked.

### DecreaseDepositRequest

```solidity
event DecreaseDepositRequest(
    uint256 indexed epochId,
    address indexed owner,
    uint256 indexed previousRequestedAssets,
    uint256 newRequestedAssets
)
```

Emitted when a deposit request is decreased.

### DecreaseRedeemRequest

```solidity
event DecreaseRedeemRequest(
    uint256 indexed epochId,
    address indexed owner,
    uint256 indexed previousRequestedShares,
    uint256 newRequestedShares
)
```

Emitted when a redeem request is decreased.

### ClaimPendingDeposit

```solidity
event ClaimPendingDeposit(
    uint256 indexed epochId,
    uint256 indexed assetsClaimed,
    uint256 indexed wrapperSharesReceived
)
```

Emitted when the wrapper claims pending deposits from the infrastructure vault.

### ClaimPendingRedeem

```solidity
event ClaimPendingRedeem(
    uint256 indexed epochId,
    uint256 indexed wrapperSharesClaimed,
    uint256 indexed assetsReceived
)
```

Emitted when the wrapper claims pending redeems from the infrastructure vault.

### MetaVaultWrapperInitialized

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.spectra.finance/metavaults/contract-functions/metavault-wrapper.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
