# 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 [#deposit-flow]

Step 1: Request a deposit [#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.

<Callout type="warn">
  `msg.sender` must approve the MetaVaultWrapper to spend the underlying asset before calling `requestDeposit`.
</Callout>

**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 [#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 [#step-3-mint-shares]

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

<Callout type="info">
  The `assets` parameter is not used in the MetaVaultWrapper implementation. Calling `deposit` always mints **all** claimable shares for the controller.
</Callout>

**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 [#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 [#redeem-flow]

Step 1: Request a redeem [#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 [#step-2-wait-for-settlement-1]

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 [#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)
```

<Callout type="info">
  Like `deposit`, the `shares` parameter is not used. Calling `redeem` always returns **all** claimable assets for the controller.
</Callout>

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

Complete redeem example [#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 [#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 [#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 [#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                  |

<Callout type="warn">
  `previewDeposit`, `previewRedeem`, `previewWithdraw`, and `previewMint` are **not implemented** on the MetaVaultWrapper, as specified by ERC-7540 for asynchronous vaults. Calling them will revert.
</Callout>
