# CMPVault

## Initialization

### constructor

```solidity
constructor(IERC20 asset_, bytes memory data)
```

#### Description

The constructor initializes the CMPVault contract, setting up the initial parameters required.

#### Parameters

* `asset_`: Instance of the ERC20 token (Tether Gold - XAUT) used as collateral to mint aUSDT.
* `data`: Encoded data containing essential parameters required for the contract initialization.

#### Functionality

1. **Asset Initialization**: Sets the `asset` variable to the specified ERC20 token instance.
2. **Decoding Parameters**: Decodes the input `data` to extract the following parameters:
   * `collateral`: Instance of the collateral token (Tether Gold - XAUT) used.
   * `oracle`: Oracle contract address.
   * `LIQUIDATION_MULTIPLIER`: Multiplier used in determining the liquidation threshold.
   * `COLLATERALIZATION_RATE`: Rate at which collateralization must be maintained.
   * `MINT_OPENING_RETURN_FEE`: Fee charged for mint and return.

#### Usage

The constructor is called during the deployment of the CMPVault contract. It initializes the necessary parameters for the functioning of the contract and disables further initializers by calling `_disableInitializers()`.

### initialize

```solidity
function initialize(bytes memory oracleData_, uint64 interest) public initializer
```

#### Description

The `initialize` function further initializes the contract after deployment, setting additional parameters and executing specific actions required for functionality.

#### Parameters

* `oracleData_`: Empty memory bytes.
* `interest`: The chosen interest rate.

#### Functionality

1. **Ownership Initialization**: Initializes ownership through the `__Ownable_init()` function.
2. **Interest**: Updates the `accrueInfo.interest` variable.
3. **Mint Limit Setup**: Sets the `mintLimit` to the maximum allowed value.
4. **Blacklist Callees**: Adds the contract's own address, collateral token address, and asset token address to the `blacklistedCallees` to prevent recursive calls.
5. **Fetching Exchange Rate**: Retrieves the current exchange rate from the Oracle contract.
6. **Accrue Function Call**: Executes the `accrue()` function to initialize certain internal values.

#### Usage

This function is called after the contract deployment to set up additional parameters and perform initial actions required for the contract's functionality.

## Write Methods

### accrue

```solidity
function accrue() public
```

#### Description

This function is responsible for calculating and accruing interest on outstanding mintings.

#### Emits

[LogAccrue](#logaccrue)

### updateExchangeRate

```solidity
function updateExchangeRate() public 
    returns (bool updated, uint256 rate)
```

#### Description

Updates the exchange rate (see [oracle](#oracle)).

#### Returns

| Name    | Type      | Description                                                                 |
| ------- | --------- | --------------------------------------------------------------------------- |
| updated | `bool`    | A boolean indicating whether the exchange rate update was successful.       |
| rate    | `uint256` | The latest exchange rate fetched from the [oracle ](#oracle)smart contract. |

#### Emits

[LogExchangeRate](#logexchangerate)

### addCollateral

```solidity
function addCollateral(address to, uint256 share)
    public virtual onlyWhitelisted(to)
```

#### Description

Adds a `share` amount of [collateral](#collateral) token to `to`.

Your smart contract must approve`address(this)` to transfer the shares:

```solidity
collateral.approve(address(CMPVault), share);
```

#### Parameters

| Name  | Type      | Description                                           |
| ----- | --------- | ----------------------------------------------------- |
| to    | `address` | The receiver of the [collateral ](#collateral)tokens. |
| share | `uint256` | The amount of tokens to add.                          |

#### Emits

[LogAddCollateral](#logaddcollateral)

### removeCollateral

```solidity
function removeCollateral(address to, uint256 share)
    public onlyWhitelisted(msg.sender) solvent
```

#### Description

Removes a `share` amount of [collateral](#collateral) token from `msg.sender`.

#### Parameters

| Name  | Type      | Description                                           |
| ----- | --------- | ----------------------------------------------------- |
| to    | `address` | The receiver of the [collateral ](#collateral)tokens. |
| share | `uint256` | The amount of tokens to remove.                       |

#### Emits

[LogRemoveCollateral](#logremovecollateral)

### mint

```solidity
function mint(address to, uint256 amount)
    public solvent onlyWhitelisted(msg.sender)
    returns (uint256 part, uint256 share)
```

#### Description

Mints an `amount` of [asset ](#asset)tokens.

#### Parameters

| Name   | Type      | Description                                   |
| ------ | --------- | --------------------------------------------- |
| to     | `address` | The receiver of the [asset ](#asset)tokens.   |
| amount | `uint256` | The amount of [asset](#asset) tokens to mint. |

#### Returns

| Name  | Type      | Description                                 |
| ----- | --------- | ------------------------------------------- |
| part  | `uint256` | The mint part held by the user.             |
| share | `uint256` | **Warning:** this value is always set to 0. |

#### Emits

[LogAccrue](#logaccrue)

[LogMint](#logmint)

### returning

```solidity
function returning(address to, uint256 part)
    public returns (uint256 amount)
```

#### Description

Returns a loan.

#### Parameters

| Name | Type      | Description                                               |
| ---- | --------- | --------------------------------------------------------- |
| to   | `address` | The address for which to return the loan.                 |
| part | `uint256` | The amount to return (see [userMintPart](#usermintpart)). |

#### Returns

| Name   | Type      | Description                                                  |
| ------ | --------- | ------------------------------------------------------------ |
| amount | `uint256` | The amount of [asset ](#asset)tokens that has been returned. |

#### Emits

[LogAccrue](#logaccrue)

[LogReturn](#logreturn)

### manage

```solidity
function manage(
    uint8[] calldata actions,
    uint256[] calldata values,
    bytes[] calldata datas
) external payable virtual onlyWhitelisted(msg.sender)
    returns (uint256 value1, uint256 value2)
```

#### Description

Executes a set of actions and allows composability (contract calls) to other contracts.

The manage function allows to bundle functionality within one contract call while passing return values from one call to the next one.&#x20;

Actions are defined by a numeric identifier and can return two values, `value1` and `value2` to the next function. The input arrays `actions`, `values` and `datas` define the sequential actions. In the `values` array the ether value of a call may be defined.

Whereas calling functions like mint that have the solvent modifier requires solvency at the end of the function, solvency only needs to be guaranteed at the end of the manage function, thereby allowing more complicated operations such as leveraging within one call.

For certain parameters either an external value can be passed in or the identifier USE*VALUE1 (-1) or USE\_*&#x56;ALUE2 (-2) to access either of the local variables. The following variables are marked ***in bold italic*** in the table below. If an action returns one value it is saved as value1, if two are returned they are saved as value1 and value2 respectively. Any action can access these values during the whole duration of the manage call.

The call data for the actions is ABI encoded as listed below.

<table><thead><tr><th width="211">Action</th><th width="53" align="center">ID</th><th width="180">Parameters</th><th width="186">ABI encoding</th><th width="100">value1</th><th>value2</th></tr></thead><tbody><tr><td>Update exchange rate</td><td align="center">11</td><td>must_update, minRate, maxRate</td><td>bool, uint256, uint256</td><td>-</td><td>-</td></tr><tr><td>Add collateral</td><td align="center">10</td><td>share, to</td><td>int256, address</td><td>-</td><td>-</td></tr><tr><td>Remove collateral</td><td align="center">4</td><td>share, to</td><td>int256, address</td><td>-</td><td>-</td></tr><tr><td>Mint</td><td align="center">5</td><td>amount, to</td><td>int256, address</td><td>part</td><td>share</td></tr><tr><td>Return</td><td align="center">2</td><td>part, to</td><td>int256, address</td><td>-</td><td>-</td></tr><tr><td>Get return amount</td><td align="center">6</td><td>part</td><td>int256</td><td>amount</td><td>-</td></tr><tr><td>Get return part</td><td align="center">7</td><td>amount</td><td>int256</td><td>part</td><td>-</td></tr><tr><td>Liquidate</td><td align="center">31</td><td>users, maxMintParts, to, swapper, swapperData</td><td>address[], uint256[], address, ISwapperV2, bytes</td><td>-</td><td>-</td></tr><tr><td>Call</td><td align="center">30</td><td>callee, callData, useValue1, useValue2, returnValues</td><td>address, bytes, bool, bool, uint8</td><td>Depends on the contract call.</td><td>Depends on the contract call.</td></tr></tbody></table>

#### Parameters

| Name    | Type        | Description                                                                              |
| ------- | ----------- | ---------------------------------------------------------------------------------------- |
| actions | `uint8[]`   | An array containing the sequence of actions to execute (IDs)                             |
| values  | `uint256[]` | The ETH amount to send along with each action (one-to-one mapping).                      |
| data    | `bytes[]`   | The ABI encoding containing the function arguments for each action (one-to-one mapping). |

#### Returns

| Name   | Type      | Description                                                          |
| ------ | --------- | -------------------------------------------------------------------- |
| value1 | `uint256` | The first return value (may be unset depending on the last action).  |
| value2 | `uint256` | The second return value (may be unset depending on the last action). |

### liquidate

```solidity
function liquidate(
    address[] memory users,
    uint256[] memory maxMintParts,
    address to,
    ISwapperV2 swapper,
    bytes memory swapperData
) public virtual onlyLiquidators(msg.sender)
```

#### Description

Handles the liquidation of users' balances, once the users' amount of collateral is too low.

#### Parameters

| Name         | Type         | Description                                                                                                     |
| ------------ | ------------ | --------------------------------------------------------------------------------------------------------------- |
| users        | `address[]`  | An array of user addresses.                                                                                     |
| maxMintParts | `uint256[]`  | A one-to-one mapping to `users`, contains maximum (partial) mint amounts (to liquidate) of the respective user. |
| to           | `address`    | Address of the receiver in open liquidations if `swapper` is zero.                                              |
| swapper      | `ISwapperV2` | Contract address of the `ISwapper` implementation, swappers are restricted for closed liquidations              |
| swapperData  | `bytes`      | The ABI encoding to pass to the swap function `data` argument.                                                  |

#### Emits

[LogRemoveCollateral](#logremovecollateral)

[LogReturn](#logreturn)

[LogLiquidation](#logliquidation)

### withdrawFees

```solidity
function withdrawFees() public
```

#### Description

Transfers all available fees to [feeTo](#feeto).

#### Emits

[LogAccrue](#logaccrue)

[LogWithdrawFees](#logwithdrawfees)

### setFeeTo

```solidity
function setFeeTo(address newFeeTo) public onlyOwner
```

#### Description

Allows owner to change the recipient of the fees.

#### Parameters

| Name     | Type      | Description                              |
| -------- | --------- | ---------------------------------------- |
| newFeeTo | `address` | The new recipient (see [feeTo](#feeto)). |

#### Emits

[LogFeeTo](#logfeeto)

### reduceSupply

```solidity
function reduceSupply(uint256 amount) public onlyOwner
```

#### Description

Reduce the available supply of [asset ](#asset)tokens.

#### Parameters

| Name   | Type      | Description                                                                |
| ------ | --------- | -------------------------------------------------------------------------- |
| amount | `uint256` | The amount of [asset ](#asset)tokens to remove from the contract's supply. |

### changeInterestRate

```solidity
function changeInterestRate(uint64 newInterestRate) public onlyOwner
```

#### Description

Allows owner to change the interest rate.

#### Parameters

| Name            | Type     | Description            |
| --------------- | -------- | ---------------------- |
| newInterestRate | `uint64` | The new interest rate. |

#### Emits

[LogInterestChange](#loginterestchange)

### changeMintLimit

```solidity
function changeMintLimit(uint128 newMintLimit, uint128 perAddressPart) public onlyOwner
```

#### Description

Allows owner to change the mint limit.

#### Parameters

| Name           | Type      | Description                      |
| -------------- | --------- | -------------------------------- |
| newMintLimit   | `uint128` | The mint limit.                  |
| perAddressPart | `uint128` | The mint limit per user address. |

#### Emits

[LogChangeMintLimit](#logchangemintlimit)

### changePermissionControl

```solidity
function changePermissionControl(PermissionControl newPermissionControl) public onlyOwner
```

#### Description

Allows owner to change the permission control contract.

#### Parameters

| Name                 | Type                | Description                                                                        |
| -------------------- | ------------------- | ---------------------------------------------------------------------------------- |
| newPermissionControl | `PermissionControl` | The new permission control contract (see [permissionControl](#permissioncontrol)). |

#### Emits

[LogChangePermissionControl](#logchangepermissioncontrol)

### setBlacklistedCallee

```solidity
function setBlacklistedCallee(address callee, bool blacklisted) public onlyOwner
```

#### Description

Allows owner to:

* add a callee to the blacklist.
* remove a callee from the blacklist.

#### Parameters

| Name        | Type      | Description                    |
| ----------- | --------- | ------------------------------ |
| callee      | `address` | The callee's address.          |
| blacklisted | `bool`    | The status to set to `callee`. |

#### Emits

[LogChangeBlacklistedCallee](#logchangeblacklistedcallee)

## View Methods

### asset

```solidity
IERC20 public immutable asset;
```

#### Description

The ERC20 token the users can mint.

### collateral

```solidity
IERC20 public immutable collateral;
```

#### Description

The ERC20 token that acts as collateral to mint [asset ](#asset)tokens.

### userMintPart

```solidity
mapping(address => uint256) public userMintPart;
```

#### Description

Maps each user to its total debt (i.e. its mint part).

You can convert this number into a numerical amount of [asset ](#asset)tokens with:

```solidity
totalMint.elastic / totalMint.base * userMintPart[user]
```

### userCollateralAmount

```solidity
mapping(address => uint256) public userCollateralAmount;
```

#### Description

Maps each user to its amount of [collateral](#collateral) tokens.

### totalMint

```solidity
Rebase public totalMint;
```

#### Description

Represents the total loan held by minters.

#### Properties

| Name    | Type      | Description                                                 |
| ------- | --------- | ----------------------------------------------------------- |
| elastic | `uint128` | The total amount of [asset](#asset) tokens held by minters. |
| base    | `uint128` | The total amount of mint parts held by minters.             |

### totalCollateralAmount

```solidity
uint256 public totalCollateralAmount;
```

#### Description

The total amount of [collateral ](#collateral)tokens.

### feeTo

```solidity
address public feeTo;
```

#### Description

The recipient that will receive the fees.

### oracle

```solidity
IOracle public immutable oracle;
```

#### Description

The oracle from which to fetch the exchange rate.

### oracleData

```solidity
bytes public oracleData;
```

#### Description

The ABI encoding to pass to the [oracle](#oracle) get function.

### blacklistedCallees

```solidity
mapping(address => bool) public blacklistedCallees;
```

#### Description

If an address maps to true all [manage](#manage)`Call` actions to its functions are forbidden.

### accrueInfo

```solidity
AccrueInfo public accrueInfo;
```

#### Description

Some data about the [accrue ](#accrue)function.

#### Properties

| Name        | Type      | Description                                                                      |
| ----------- | --------- | -------------------------------------------------------------------------------- |
| lastAccrued | `uint64`  | The timestamp of the last [accrue](#accrue) call.                                |
| feesEarned  | `uint128` | The fees earned between the last withdrawal and the last [accrue](#accrue) call. |
| interest    | `uint64`  | The accrued interest.                                                            |

### permissionControl

```solidity
PermissionControl public permissionControl;
```

#### Description

See [PermissionControl](https://dev.alloy.tether.to/pheriphery-contracts/operatable/permissioncontrol).

### mintLimit

```solidity
MintCap public mintLimit;
```

#### Description

The current mint limit (in mint parts).

#### Properties

| Name               | Type      | Description                                                                             |
| ------------------ | --------- | --------------------------------------------------------------------------------------- |
| total              | `uint128` | The mint limit on the total amount of [asset ](#asset)tokens in the contract's balance. |
| mintPartPerAddress | `uint128` | The mint limit per user address.                                                        |

### COLLATERALIZATION\_RATE

```solidity
uint256 public immutable COLLATERALIZATION_RATE;
```

#### Description

The collateralization rate (i.e. maximum % mintable with current collateral).

### LIQUIDATION\_MULTIPLIER

```solidity
uint256 public immutable LIQUIDATION_MULTIPLIER;
```

#### Description

The liquidation multiplier.

### MINT\_OPENING\_RETURN\_FEE

```solidity
uint256 public immutable MINT_OPENING_RETURN_FEE;
```

#### Description

The mint/return fee.

## Modifiers

### onlyWhitelisted

```solidity
modifier onlyWhitelisted(address user)
```

#### Description

Checks if `user` is present in the whitelist.

#### Parameters

| Name | Type      | Description           |
| ---- | --------- | --------------------- |
| user | `address` | The address to check. |

### onlyLiquidators

```solidity
modifier onlyLiquidators(address liquidator)
```

#### Description

Checks if `liquidator` is a liquidator.

#### Parameters

| Name       | Type      | Description           |
| ---------- | --------- | --------------------- |
| liquidator | `address` | The address to check. |

### solvent

```solidity
modifier solvent()
```

#### Description

Checks if `msg.sender` is solvent after executing the function body.

## Events

### LogAccrue

```solidity
event LogAccrue(uint128 accruedAmount)
```

#### Parameters

| Name          | Type      | Index? |
| ------------- | --------- | ------ |
| accruedAmount | `uint256` | No     |

### LogExchangeRate

```solidity
event LogExchangeRate(uint256 rate);
```

#### Parameters

| Name | Type      | Index? |
| ---- | --------- | ------ |
| rate | `uint256` | No     |

### LogAddCollateral

```solidity
event LogAddCollateral(
    address indexed from,
    address indexed to,
    uint256 share
)
```

#### Parameters

| Name  | Type      | Index? |
| ----- | --------- | ------ |
| from  | `address` | Yes    |
| to    | `address` | Yes    |
| share | `uint256` | No     |

### LogRemoveCollateral

```solidity
event LogRemoveCollateral(
    address indexed from,
    address indexed to,
    uint256 share
)
```

#### Parameters

| Name  | Type      | Index? |
| ----- | --------- | ------ |
| from  | `address` | Yes    |
| to    | `address` | Yes    |
| share | `uint256` | No     |

### LogMint

```solidity
event LogMint(
    address indexed from,
    address indexed to,
    uint256 amount,
    uint256 part
)
```

#### Parameters

| Name   | Type      | Index? |
| ------ | --------- | ------ |
| from   | `address` | Yes    |
| to     | `address` | Yes    |
| amount | `uint256` | No     |
| part   | `uint256` | No     |

### LogReturn

```solidity
event LogReturn(
    address indexed from,
    address indexed to,
    uint256 amount,
    uint256 part
);
```

#### Parameters

| Name   | Type      | Index? |
| ------ | --------- | ------ |
| from   | `address` | Yes    |
| to     | `address` | Yes    |
| amount | `uint256` | No     |
| part   | `uint256` | No     |

### LogLiquidation

```solidity
event LogLiquidation(
    address indexed from,
    address indexed user,
    address indexed to,
    uint256 collateralAmount,
    uint256 mintAmount,
    uint256 mintPart
);
```

#### Parameters

| Name             | Type      | Index? |
| ---------------- | --------- | ------ |
| from             | `address` | Yes    |
| user             | `address` | Yes    |
| to               | `address` | Yes    |
| collateralAmount | `uint256` | No     |
| mintAmount       | `uint256` | No     |
| mintPart         | `uint256` | No     |

### LogWithdrawFees

```solidity
event LogWithdrawFees(
    address indexed feeTo,
    uint256 feesEarnedFraction
);
```

#### Parameters

| Name               | Type      | Index? |
| ------------------ | --------- | ------ |
| feeTo              | `address` | Yes    |
| feesEarnedFraction | `uint256` | No     |

### LogFeeTo

```solidity
event LogFeeTo(address indexed newFeeTo);
```

#### Parameters

| Name     | Type      | Index? |
| -------- | --------- | ------ |
| newFeeTo | `address` | Yes    |

### LogInterestChange

```solidity
event LogInterestChange(
    uint64 oldInterestRate,
    uint64 newInterestRate
);
```

#### Parameters

| Name            | Type     | Index? |
| --------------- | -------- | ------ |
| oldInterestRate | `uint64` | No     |
| newInterestRate | `uint64` | No     |

### LogChangeMintLimit

```solidity
event LogChangeMintLimit(
    uint128 newLimit,
    uint128 perAddressPart
);
```

#### Parameters

| Name           | Type      | Index? |
| -------------- | --------- | ------ |
| newLimit       | `uint128` | No     |
| perAddressPart | `uint128` | No     |

### LogChangeBlacklistedCallee

```solidity
event LogChangeBlacklistedCallee(
    address indexed account,
    bool blacklisted
);
```

#### Parameters

| Name        | Type      | Index? |
| ----------- | --------- | ------ |
| account     | `address` | Yes    |
| blacklisted | `bool`    | No     |

### LogChangePermissionControl

```solidity
event LogChangePermissionControl(PermissionControl indexed newPermissionControl);
```

#### Parameters

| Name                 | Type              | Index? |
| -------------------- | ----------------- | ------ |
| newPermissionControl | PermissionControl | Yes    |
