# Vault

The Vault is the core module responsible for the storage, issuance, and redemption of cUSD, and for managing the underlying collateral assets. It plays a pivotal role as the protocol's liquidity backbone by enabling minting and burning of cUSD, facilitating liquidity for borrowers, and ensuring capital efficiency through the Fractional Reserves.

## Overview of operations

* **Mint/Burn:** cUSD can be minted/burned *\~1:1* for any of the supported backing assets. Fees are dynamically calculated according to the allocation ratio of the asset.
* **Redeem:** cUSD can be redeemed for a proportional amount of the basket of assets for a fixed fee.
* [**Fractional Reserves**](https://docs.cap.app/concepts/vault/fractional-reserves): Idle capital in the Vault is deployed into yield-generating strategies (US T-bill yield, crypto lending markets) until borrowed or withdrawn.
* **Borrow/Repay**: When operators borrow/repays assets, the Vault tracks utilization of the pool

## Mechanics

### Mint/Burn

The Vault is the main interface for liquidity providers to mint and burn cUSD. cUSD can be minted/burned at Oracle value for any of the assets. Fees are calculated in the [Minter](https://docs.cap.app/concepts/vault/minter) contract according to the allocation of the assets.

When a user mints/burns, the flow is as follows:

1. **User Call**: User calls `Vault.mint()` (or burn) with asset and amount
2. **Fee Calculation**: Vault calls `Minter.getMintAmount()` (or getBurnAmount) to calculate fees
3. **Logic Processing**: MinterLogic calculates amount out and fees at current Oracle value
4. **State Update**: VaultLogic handles asset transfer and state updates
5. **Token Minting**: cUSD is minted/burned in exchange for underlying assets

{% hint style="info" %}
Mint and burn functions are disabled if Oracle prices are stale, until Oracles are back in sync
{% endhint %}

### Redeem

A depeg event of any of the underlying assets can result in a last man standing problem where the last to withdraw will be left with the depegged asset. When such events occur, the protocol incentivizes users to withdraw proportionally to the ratio of the assets, effectively socializing the losses. Redeem fees are charged at a fixed percentage, whereas burn fees are dynamic, making it economically infeasible to burn for USDT beyond the burn kink ratio. For instance, if the basket contains 50% of USDC valued at $0.9 and 50% of USDT valued at $1, then the redeem request for $100 cUSD should withdraw $45 worth of USDC and $50 worth of USDT minus fees.

When a user redeems, the flow is as follows:

1. **User Call**: User calls `Vault.redeem()` with cUSD
2. **Fee Calculation**: Vault calls `Minter.getRedeemAmount()` to calculate proportional amounts
3. **State Update**: cUSD is burned from user, assets are divested from strategies
4. **Asset Transfer**: All underlying assets are transferred to user

### Borrow Operations

Registered Operators can borrow assets from the Vault via the Lender, provided they are sufficiently collateralized by delegated assets from shared security networks. While assets are lent out from the Vault, the core borrow logic is implemented in the Lender contract. When the Operator requests to borrow via the Lender, the Lender calls `Vault.borrow()` to transfer assets to the Lender, updating the utilization and reserve state of the Vault.

Similarly, Operators can repay via the Lender, which transfers borrowed assets back to the Vault.

### Vault Management

Assets must first be whitelisted in order to be used in Cap. Only regulated dollar-denominated crypto assets are accepted as a backing assets.

Interest rates for borrowing each asset of the reserve is a function of the utilization rate of the asset. The [current utilization rate](https://github.com/cap-labs-dev/cap-contracts/blob/main/contracts/vault/Vault.sol#L198) of each asset can be queried in the Vault contract.

### Configurations

* **Whitelist minters**: Supports fee bypass for privileged users
* **Pause mechanisms**:
  * Asset-Level Pause: Individual assets can be paused while others remain active
  * Protocol-Level Pause: Complete protocol shutdown capability

### Key Vault Parameters

* **Total Supplies**: Total amount of each asset deposited in the vault
* **Total Borrows**: Total amount of each asset borrowed from the vault
* **Utilization Rate**: Ratio of borrowed assets to total supplies, calculated as (Total Borrows / Total Supplies) \* 100%
* **Available Balance**: Amount of asset available for borrowing, calculated as Total Supplies - Total Borrows
* **Utilization Index**: Cumulative utilization tracking for interest rate calculations
* **Insurance Fund**: Address that receives fees from mint/burn operations
* **Pause States**: Individual asset pause states and protocol-wide pause capability

## Architecture

The Vault module inherits from the Fractional Reserve and Minter contracts

1. **Vault** - Manages asset storage, accounting, and cUSD minting/burning
2. [**Fractional Reserve**](https://docs.cap.app/concepts/vault/fractional-reserves) - Manages idle capital deployment
3. [**Minter**](https://docs.cap.app/concepts/vault/minter) - Handles dynamic fee calculation for minting operations

### Vault Contract

The Vault Contract is the main user-facing contract that enables minting and borrowing, as well as reserve asset management.

#### Core Functions

**`mint`**: Allows users to deposit approved assets and receive cUSD in return

```solidity
function mint(address _asset, uint256 _amountIn, uint256 _minAmountOut, address _receiver, uint256 _deadline)
    external
    returns (uint256 amountOut)
```

* `_asset`: Whitelisted asset to deposit
* `_amountIn`: Amount of asset to use in the minting
* `_minAmountOut`: Minimum amount to mint (slippage protection)
* `_receiver`: Receiver of the minting
* `_deadline`: Deadline of the transaction

Key features:

* **Slippage Protection**: `_minAmountOut` parameter
* **Deadline Protection**: Transaction deadline validation
* **Dynamic Fees**: Fees based on asset allocation ratios

**`burn`**: Burns cUSD in exchange for one of the underlying assets.

```solidity
function burn(address _asset, uint256 _amountIn, uint256 _minAmountOut, address _receiver, uint256 _deadline)
    external
    returns (uint256 amountOut)
```

* `_asset`: Asset to withdraw
* `_amountIn`: Amount of cap token to burn
* `_minAmountOut`: Minimum amount out to receive
* `_receiver`: Receiver of the withdrawal
* `_deadline`: Deadline of the transaction

**`redeem`**: Allows users to burn cUSD in exchange for multi-collateral withdrawal, proportional to the ratio of the underlying assets.

```solidity
function redeem(uint256 _amountIn, uint256[] calldata _minAmountsOut, address _receiver, uint256 _deadline)
    external
    returns (uint256[] memory amountsOut)
```

* `_amountIn`: Amount of Cap token to burn
* `_minAmountsOut`: Minimum amounts of assets to withdraw
* `_receiver`: Receiver of the withdrawal
* `_deadline`: Deadline of the transaction

Key features:

* **Proportional Withdrawal**: Withdraws assets proportional to current ratios
* **Fee Avoidance**: Avoids dynamic fees by withdrawing proportionally

**`borrow`**: Allows whitelisted agents to borrow assets from the vault

```solidity
function borrow(address _asset, uint256 _amount, address _receiver) external
```

* `_asset`: Asset to borrow
* `_amount`: Amount of asset to borrow
* `_receiver`: Receiver of the borrow

**`repay`**: Allows repayment of borrowed assets

```solidity
function repay(address _asset, uint256 _amount) external
```

* `_asset`: Asset to repay
* `_amount`: Amount of asset to repay

#### Admin Functions

* **`addAsset`**: Adds new assets to the vault
* **`removeAsset`**: Removes assets from the vault (only if no supplies)
* **`pauseAsset`**: Pauses operations for specific assets
* **`unpauseAsset`**: Resumes operations for specific assets
* **`pauseProtocol`**: Pauses all protocol operations
* **`unpauseProtocol`**: Resumes all protocol operations
* **`setInsuranceFund`**: Sets the insurance fund address
* **`rescueERC20`**: Rescues unsupported tokens from the vault

#### **View Functions**

* **`assets`**: Get the list of assets supported by the vault
* **`totalSupplies`**: Get the total supplies of an asset
* **`totalBorrows`**: Get the total borrows of an asset
* **`utilization`**: Get the utilization rate of an asset
* **`availableBalance`**: Get available balance to borrow an asset
* **`paused`**: Get the pause state of an asset
* **`currentUtilizationIndex`**: Get up-to-date cumulative utilization index
* **`insuranceFund`**: Get the insurance fund address

### Data Structures

#### VaultStorage

The VaultStorage stores all vault configuration and state information.

```solidity
struct VaultStorage {
    EnumerableSet.AddressSet assets;           // List of supported assets
    mapping(address => uint256) totalSupplies; // Total supplies per asset
    mapping(address => uint256) totalBorrows;  // Total borrows per asset
    mapping(address => uint256) utilizationIndex; // Utilization index per asset
    mapping(address => uint256) lastUpdate;    // Last update time per asset
    mapping(address => bool) paused;           // Pause state per asset
    address insuranceFund;                     // Insurance fund address
}
```

#### MintBurnParams

Parameters for minting or burning operations.

```solidity
struct MintBurnParams {
    address asset;        // Asset to mint or burn
    uint256 amountIn;     // Amount of asset to use
    uint256 amountOut;    // Amount of cap token to mint or burn
    uint256 minAmountOut; // Minimum amount to mint or burn
    address receiver;     // Receiver of the operation
    uint256 deadline;     // Deadline of the transaction
    uint256 fee;          // Fee paid to insurance fund
}
```

#### RedeemParams

Parameters for redemption operations.

```solidity
struct RedeemParams {
    uint256 amountIn;        // Amount of cap token to burn
    uint256[] amountsOut;    // Amounts of assets to withdraw
    uint256[] minAmountsOut; // Minimum amounts of assets to withdraw
    address receiver;        // Receiver of the withdrawal
    uint256 deadline;        // Deadline of the transaction
    uint256[] fees;          // Fees paid to insurance fund
}
```

#### BorrowParams

Parameters for borrowing operations.

```solidity
struct BorrowParams {
    address asset;    // Asset to borrow
    uint256 amount;   // Amount of asset to borrow
    address receiver; // Receiver of the borrow
}
```

#### RepayParams

Parameters for repayment operations.

```solidity
struct RepayParams {
    address asset;  // Asset to repay
    uint256 amount; // Amount of asset to repay
}
```
