# 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 %}
