# Depositing and Redeeming

MetaVaults follow the [ERC-7540](https://eips.ethereum.org/EIPS/eip-7540) asynchronous vault standard. Unlike standard ERC-4626 vaults where deposits and redeems are instant, MetaVaults use a **request → settle → share mint / share burn** flow.

## Deposit flow

### Step 1: Request a deposit

```solidity
function requestDeposit(
    uint256 assets,
    address controller,
    address owner
) external returns (uint256 requestId)
```

The depositor transfers `assets` (underlying token, e.g. USDC) to the wrapper. The assets are forwarded to the infrastructure vault.

{% hint style="warning" %}
`msg.sender` must approve the MetaVaultWrapper to spend the underlying asset before calling `requestDeposit`.
{% endhint %}

**Requirements:**

* `assets > 0`
* `owner == msg.sender` or `msg.sender` is an approved operator of `owner`
* The vault must not be paused

**What happens internally:**

1. If the controller has a claimable deposit from a previous epoch, it is automatically claimed first.
2. Assets are transferred from `owner` to the wrapper, then forwarded to the infrastructure vault.
3. The request is recorded in the current epoch's deposit request balance.

### Step 2: Wait for settlement

The accountant calls `settle()` on the infrastructure vault to end the current epoch. During settlement:

* Pending deposit assets are converted to shares using the epoch's total supply and total assets snapshot.
* Shares are minted and made available for claiming.

### Step 3: Mint shares

```solidity
function deposit(
    uint256 assets,     // not used — all claimable shares are minted
    address receiver,
    address controller
) external returns (uint256 shares)
```

{% hint style="info" %}
The `assets` parameter is not used in the MetaVaultWrapper implementation. Calling `deposit` always mints **all** claimable shares for the controller.
{% endhint %}

**Requirements:**

* `controller == msg.sender` or `msg.sender` is an approved operator of `controller`
* The controller must have a claimable deposit from a settled epoch

**Returns:** The number of wrapper shares minted to `receiver`.

### Complete deposit example

```solidity
// 1. Approve the wrapper to spend USDC
IERC20(usdc).approve(address(wrapper), 1000e6);

// 2. Request deposit
wrapper.requestDeposit(1000e6, msg.sender, msg.sender);

// ... wait for settle() ...

// 3. Claim shares
uint256 shares = wrapper.deposit(0, msg.sender, msg.sender);
```

## Redeem flow

### Step 1: Request a redeem

```solidity
function requestRedeem(
    uint256 shares,
    address controller,
    address owner
) external returns (uint256 requestId)
```

The depositor's wrapper shares are burned and the equivalent infrastructure vault shares are queued for redemption.

**Requirements:**

* `shares > 0`
* `owner == msg.sender` or `msg.sender` is an approved operator of `owner`
* The vault must not be paused

**What happens internally:**

1. If the controller has a claimable redeem from a previous epoch, it is automatically claimed first.
2. Wrapper shares are burned from `owner`.
3. The corresponding infrastructure vault shares are queued for redemption.
4. The request is recorded in the current epoch's redeem request balance.

### Step 2: Wait for settlement

During `settle()`, pending redeem shares are converted to assets using the epoch's snapshot values. Assets are made available for claiming.

### Step 3: Burn shares for assets

```solidity
function redeem(
    uint256 shares,     // not used — all claimable assets are returned
    address receiver,
    address controller
) public returns (uint256 assets)
```

{% hint style="info" %}
Like `deposit`, the `shares` parameter is not used. Calling `redeem` always returns **all** claimable assets for the controller.
{% endhint %}

**Returns:** The amount of underlying assets transferred to `receiver`.

### Complete redeem example

```solidity
// 1. Request redeem of 500 shares
wrapper.requestRedeem(500e6, msg.sender, msg.sender);

// ... wait for settle() ...

// 2. Claim assets
uint256 assets = wrapper.redeem(0, msg.sender, msg.sender);
```

## Decreasing a request

If a depositor changes their mind before settlement, they can decrease their pending request:

```solidity
// Decrease a deposit request (get assets back)
wrapper.decreaseDepositRequest(500e6);

// Decrease a redeem request (get shares back)
wrapper.decreaseRedeemRequest(250e6);
```

These functions can only be called by the original requester (`msg.sender`). The refunded assets or shares are returned directly to `msg.sender`.

## Operator model

MetaVaults support the ERC-7540 operator pattern. A controller can approve an operator to act on their behalf:

```solidity
wrapper.setOperator(operatorAddress, true);
```

Once approved, the operator can call `requestDeposit`, `deposit`, `requestRedeem`, and `redeem` on behalf of the controller.

## View functions for integrators

| Function                                         | Returns                                                         |
| ------------------------------------------------ | --------------------------------------------------------------- |
| `pendingDepositRequest(requestId, controller)`   | Assets queued in the current epoch                              |
| `claimableDepositRequest(requestId, controller)` | Assets claimable from a settled epoch                           |
| `pendingRedeemRequest(requestId, controller)`    | Shares queued in the current epoch                              |
| `claimableRedeemRequest(requestId, controller)`  | Shares claimable from a settled epoch                           |
| `maxDeposit(receiver)`                           | Maximum claimable deposit amount (0 if paused or current epoch) |
| `maxRedeem(owner)`                               | Maximum claimable redeem amount (0 if paused or current epoch)  |
| `convertToShares(assets)`                        | Convert assets to shares using the last settled epoch rate      |
| `convertToAssets(shares)`                        | Convert shares to assets using the last settled epoch rate      |
| `convertToShares(assets, epochId)`               | Convert using a specific epoch's rate                           |
| `convertToAssets(shares, epochId)`               | Convert using a specific epoch's rate                           |
| `totalAssets()`                                  | Estimated total assets of the wrapper                           |
| `epochId()`                                      | Current epoch ID from the infrastructure vault                  |

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


---

# Agent Instructions: 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/depositing-and-redeeming.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.
