# Cozy tokens

## Core methods

This section contains the primary methods for interacting with the Cozy protocol. Most methods in this section return a `uint256` value of zero (0) for a successful call, or return an [error code](https://v1-docs.cozy.finance/for-developers/error-codes) on a unsuccessful call. The main exceptions to this general rule are the methods that are part of the standard [ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20), such as the `transfer` and `balanceOf` methods.

### Mint

You use the `mint` function to transfer assets from your wallet to any Cozy market. You can use the `mint` function when you want to do the following:

* supply funds to use as collateral for protected borrowing.
* deposit funds to provide protection and earn interest.

Depending on whether you are minting tokens or ETH, use one of the following function signatures:

```javascript
// For markets with tokens as underlying
function mint(uint256 amount) external returns (uint256);

// For markets with ETH as underlying
function mint() external payable;
```

For tokens, the `amount` is the number of tokens to supply, denominated in units of the underlying token. For ETH, instead of specifying an amount, you send ETH along with the transaction and `msg.value` is used in place of `amount`.

Before supplying a token, remember to `approve` the Cozy market. A successful `mint` call returns a value of zero and transfers Cozy tokens to the caller's wallet. The number of Cozy tokens the user receives is equal to the supplied amount divided by the [exchange rate](#exchange-rate).

### Redeem

You use the `redeem` method to redeem Cozy tokens for the underlying supplying funds. The amount of underlying received is equal to the number of Cozy tokens redeemed multiplied by the [exchange rate](#exchange-rate). There are two methods you can use to redeem tokens:

```javascript
// Specify amount to redeem denominated in amount of Cozy tokens
function redeem(uint256 redeemTokens) external returns (uint256);

// Specify amount to redeem denominated in amount of underlying
function redeemUnderlying(uint256 redeemAmount) external returns (uint256);
```

A successful redeem burns the caller's Cozy tokens, transfers a proportional amount of the underlying asset, and returns a value of zero.

### Borrow

After supplying collateral with the `mint` method, you can use the `borrow` method to borrow funds from the Cozy protocol. Borrowed funds accrue interest at the current [borrow rate](#borrow-rate). If a borrower has insufficient account liquidity, however, the borrowed funds can be liquidated.

The method for borrowing funds from a market is:

```javascript
function borrow(uint256 borrowAmount) external returns (uint256);
```

where `borrowAmount` is specified in units of the token to borrow.

### Repay debt

You can use either the `repayBorrow` or `repayBorrowBehalf` function to repay borrowed funds as follows:

```javascript
// --- For markets with tokens as underlying ---
// Repays `repayAmount` of the underlying for `msg.sender`
function repayBorrow(uint256 repayAmount) external returns (uint256);

// Repays `repayAmount` of the underlying for `borrower`
function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);

// --- For markets with ETH as underlying ---
// Repays `msg.value` ETH for `msg.sender`
function repayBorrow() external payable;

// Repays `msg.value` ETH for `borrower`
function repayBorrowBehalf(address borrower) external payable;
```

To repay all token debt without leaving any dust, you can specify a `repayAmount` of`MAX_UINT256 = 2^256 - 1`.

To repay all ETH debt without leaving any dust, it is recommended to use a special helper contract called `Maximillion` and call the following method:

```javascript
function repayBehalfExplicit(address borrower, CEther cEther_) external payable;
```

where `borrower` is the address of the user to pay back debt for, and `cEther_` is the address of the market to pay back debt in (for example, the Cozy Ether money market, or a protection market with ETH as the underlying). When calling this method, send along more ETH than the debt amount, and after paying off the full debt, the excess ETH will be refunded.

The `Maximillion` contract is deployed on mainnet at [0xf859A1AD94BcF445A406B892eF0d3082f4174088](https://etherscan.io/address/0xf859A1AD94BcF445A406B892eF0d3082f4174088).

### Liquidate

You use the `liquidateBorrow` function to liquidate a user's assets when their account liquidity is negative. This action brings the user back to a solvent state. During a liquidation, the liquidator repays some or all of the user's borrow and, in return, receives a portion of their collateral, as Cozy tokens, at a discount.

The maximum portion of the borrow that can be liquidated is specified by the close factor in the Comptroller. As with mints and repays, liquidating pulls tokens from the caller, so the liquidator must `approve` the Cozy token contract before liquidating.

Liquidations can be executed with the following methods:

```javascript
// For markets with tokens as underlying
function liquidateBorrow(
    address borrower,
    uint256 repayAmount,
    CTokenInterface cTokenCollateral
) external returns (uint256);

// For markets with ETH as underlying
function liquidateBorrow(
    address borrower,
    CToken cTokenCollateral
) external payable;
```

where `borrower` is the account with a shortfall to liquidate and `cTokenCollateral` is the token being used by the borrower as collateral that the liquidator will receive. For token-based markets, `repayAmount` specifies how much of the borrowed asset to repay, and for ETH-based markets that amount is specified by `msg.value`.

### Transfer

All Cozy tokens are [ERC-20](https://eips.ethereum.org/EIPS/eip-20) compliant and can be transferred with both the `transfer` and `transferFrom` functions. They also implement [ERC-2612](https://eips.ethereum.org/EIPS/eip-2612) `permit` function to improve the approval flow.

{% hint style="info" %}
Token transfers fail if the transfer would put the account into an under-collateralized position.
{% endhint %}

## View methods

This section contains the primary methods for viewing information about Cozy markets.

### Exchange rate

Every Cozy token has it's own exchange rate, which is a function of the market's cash, borrows, reserves, and supply. This value is initialized to 0.02 when a market is created, and increases as the accrues interest. The exchange rate for a given market is calculated as:

```javascript
exchangeRate = ( getCash() + totalBorrows() - totalReserves() ) / totalSupply();
```

The exchange rate is represented as a mantissa (an 18 decimal number) with a precision of `18 + underlyingDecimals - cozyTokenDecimals`. For example, all Cozy tokens have 8 decimals. If the underlying token has 6 decimals, the initial exchange rate for that market would have 18 + 6 - 8 = 16 decimals. Querying the exchange rate of this market immediately after deployment would return `0.02e16 = 200000000000000`.

### Cash

Cash is the amount of the underlying token held by the Cozy token. You can read the cash held by the contract using the following function:

```javascript
function getCash() external view returns (uint256);
```

For markets with tokens as the underlying, this function returns the value of `underlyingToken.balanceOf(address(this));`. For markets with ETH as the underlying, the function returns `address(this).balance - msg.value`.

### Borrows

A market's total borrows is the amount of the underlying token actively borrowed. This amount is used when computing the accrued interest. It can be queried for a given market with the function below. When a market is triggered, this value is set to zero, so the below methods always returns zero after a trigger event.

```javascript
// View method which returns the last known borrow amount, `totalBorrows`
function totalBorrows() external view returns (uint256);

// Non-view method which accrues interest before returning `totalBorrows`.
// Because this version accrues interest first, it will be more up to date
function totalBorrowsCurrent() external returns (uint256);
```

The amount being borrowed by an individual user can be read with the method below. Both methods always returns a borrow balance of zero after a market is triggered.

```javascript
// View method which returns the last known borrow balance for `account`
function borrowBalanceStored(address account) external view returns (uint256);

// Non-view method which accrues interest before returning `borrowBalanceStored`.
// Because this version accrues interest first, it will be more up to date
function borrowBalanceCurrent(address account) external returns (uint256);
```

### Supply

A market's total supply is the number of Cozy tokens that have been minted and are currently in circulation. You can use the standard ERC-20 `totalSupply` method to return the number of Cozy tokens in a market as follows:

```javascript
function totalSupply() external view returns (uint256);
```

### Balances

To read a user's Cozy token balance, you can use the standard ERC-20 `balanceOf` method as follows:

```javascript
function balanceOf(address account) external view returns (uint256);
```

You can also read a user's balance with the `balanceOfUnderlying` function, which returns the user's Cozy token balance multiplied by the exchange rate.

```javascript
// Note that `balanceOfUnderlying` is not a view method
function balanceOfUnderlying(address account) external returns (uint256);
```

For example, if a user supplies 1000 USDC with an exchange rate of 0.02, she receives `1000 / 0.02 = 50,000` Cozy tokens. Calling `balanceOf` will return 50,000e8, and calling `balanceOfUnderlying` will return 1000e6, since Cozy tokens have 8 decimals and USDC has 6 decimals).

### Interest rates

You can use the `borrowRatePerBlock` function to read the current interest rate accrued by borrowers every block.

```javascript
function borrowRatePerBlock() external view returns (uint256);
```

The supply-rate-per-block is a function of the borrow-rate-per-block, as well the market's reserve factor and the its utilization rate. The utilization rate is the ratio of borrowed funds to supplied funds, calculated as `borrows / (cash + borrows - reserves)`. The supply rate is then calculated as `utilizationRate * (borrowRatePerBlock * (1 - reserveFactor))`. You can query this value as follows:

```javascript
function supplyRatePerBlock() external view returns (uint256);
```

Both the borrow rate and supply rate returned from these methods will always be zero after a market is triggered.

### Reserves

A portion of interest accrued from borrowers is set aside as cash, and cash from this source is known as reserves. The amount of reserves set aside is determined by the reserve factor. You can use the `reserveFactorMantissa` method to return the reserve factor. See the [Interest Rates](#interest-rates) section for more information on how the reserve factor is used.

```javascript
// Returns a mantissa, so it's scaled by 1e18
function reserveFactorMantissa() external view returns (uint256)
```

The total reserves in a given market can be read with:

```javascript
function totalReserves() external view returns (uint256)
```

Reserves can be withdrawn or transferred by the protocol administrator.

## Events

This sections contains the core events emitted by Cozy token contracts, and is not a comprehensive list.

```javascript
// Emitted when interest is accrued
event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);

// Emitted when tokens are minted
event Mint(address minter, uint256 mintAmount, uint256 mintTokens);

// Emitted when tokens are redeemed
event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);

// Emitted when underlying is borrowed
event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is repaid
event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows);

// Emitted when a borrow is liquidated
event LiquidateBorrow(
  address liquidator,
  address borrower,
  uint256 repayAmount,
  address cTokenCollateral,
  uint256 seizeTokens
);

// Emitted when trigger status is set. This is emitted once at
// construction and one more time when the trigger is toggled
event TriggerSet(bool isTriggered);
```

## Error handling

This section contains information about error codes and failure messages that may be returned when calling methods on a Cozy token contract.

### Error codes

The table below contains a list of error codes that may be returned when calling methods on a Cozy token contract.

| Code | Name                             | Description                                                          |
| ---- | -------------------------------- | -------------------------------------------------------------------- |
| 0    | `NO_ERROR`                       | Call succeeded                                                       |
| 1    | `UNAUTHORIZED`                   | Caller is not authorized                                             |
| 2    | `BAD_INPUT`                      | Caller provided bad arguments                                        |
| 3    | `COMPTROLLER_REJECTION`          | The Comptroller blocked this action                                  |
| 4    | `COMPTROLLER_CALCULATION_ERROR`  | A calculation failed in the Comptroller                              |
| 5    | `INTEREST_RATE_MODEL_ERROR`      | An invalid value was returned from the interest rate model           |
| 6    | `INVALID_ACCOUNT_PAIR`           | The borrower and liquidator are the same account                     |
| 7    | `INVALID_CLOSE_AMOUNT_REQUESTED` | The `MAX_UINT256` is passed as the `repayAmount` during liquidation  |
| 8    | `INVALID_COLLATERAL_FACTOR`      | Provided collateral factor is not allowed                            |
| 9    | `MATH_ERROR`                     | An error occurred in a math operation                                |
| 10   | `MARKET_NOT_FRESH`               | The market has not properly accrued interest                         |
| 11   | `MARKET_NOT_LISTED`              | The market is not supported by the Comptroller                       |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   | Caller has not approved the contract to spend enough tokens          |
| 13   | `TOKEN_INSUFFICIENT_BALANCE`     | Caller has an insufficient token balance to complete the transaction |
| 14   | `TOKEN_INSUFFICIENT_CASH`        | The market does not have enough cash at this time                    |
| 15   | `TOKEN_TRANSFER_IN_FAILED`       | ERC-20 token transfer to the market failed                           |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      | ERC-20 token transfer from the market failed                         |
| 17   | `INVALID_GUARDIAN`               | Reserve guardian cannot be the zero address                          |

### Failure codes and logged messages

The table below contains a list of error codes that may be emitted in `Failure` logs when calling methods on a Cozy token contract. These codes are descriptive so no additional description is provided.

| Code | Name                                                         |
| ---- | ------------------------------------------------------------ |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`                           |
| 1    | `ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED`    |
| 2    | `ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED`             |
| 3    | `ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED`        |
| 4    | `ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED`       |
| 5    | `ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED`      |
| 6    | `ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED`  |
| 7    | `BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`              |
| 8    | `BORROW_ACCRUE_INTEREST_FAILED`                              |
| 9    | `BORROW_CASH_NOT_AVAILABLE`                                  |
| 10   | `BORROW_FRESHNESS_CHECK`                                     |
| 11   | `BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`                |
| 12   | `BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED`       |
| 13   | `BORROW_MARKET_NOT_LISTED`                                   |
| 14   | `BORROW_COMPTROLLER_REJECTION`                               |
| 15   | `LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED`                    |
| 16   | `LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED`                |
| 17   | `LIQUIDATE_COLLATERAL_FRESHNESS_CHECK`                       |
| 18   | `LIQUIDATE_COMPTROLLER_REJECTION`                            |
| 19   | `LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED`        |
| 20   | `LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX`                         |
| 21   | `LIQUIDATE_CLOSE_AMOUNT_IS_ZERO`                             |
| 22   | `LIQUIDATE_FRESHNESS_CHECK`                                  |
| 23   | `LIQUIDATE_LIQUIDATOR_IS_BORROWER`                           |
| 24   | `LIQUIDATE_REPAY_BORROW_FRESH_FAILED`                        |
| 25   | `LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED`                   |
| 26   | `LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED`                   |
| 27   | `LIQUIDATE_SEIZE_COMPTROLLER_REJECTION`                      |
| 28   | `LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER`                     |
| 29   | `LIQUIDATE_SEIZE_TOO_MUCH`                                   |
| 30   | `MINT_ACCRUE_INTEREST_FAILED`                                |
| 31   | `MINT_COMPTROLLER_REJECTION`                                 |
| 32   | `MINT_EXCHANGE_CALCULATION_FAILED`                           |
| 33   | `MINT_EXCHANGE_RATE_READ_FAILED`                             |
| 34   | `MINT_FRESHNESS_CHECK`                                       |
| 35   | `MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`                |
| 36   | `MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                   |
| 37   | `MINT_TRANSFER_IN_FAILED`                                    |
| 38   | `MINT_TRANSFER_IN_NOT_POSSIBLE`                              |
| 39   | `REDEEM_ACCRUE_INTEREST_FAILED`                              |
| 40   | `REDEEM_COMPTROLLER_REJECTION`                               |
| 41   | `REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED`                  |
| 42   | `REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED`                  |
| 43   | `REDEEM_EXCHANGE_RATE_READ_FAILED`                           |
| 44   | `REDEEM_FRESHNESS_CHECK`                                     |
| 45   | `REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED`              |
| 46   | `REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED`                 |
| 47   | `REDEEM_TRANSFER_OUT_NOT_POSSIBLE`                           |
| 48   | `REDUCE_RESERVES_ACCRUE_INTEREST_FAILED`                     |
| 49   | `REDUCE_RESERVES_ADMIN_CHECK`                                |
| 50   | `REDUCE_RESERVES_CASH_NOT_AVAILABLE`                         |
| 51   | `REDUCE_RESERVES_FRESH_CHECK`                                |
| 52   | `REDUCE_RESERVES_VALIDATION`                                 |
| 53   | `REPAY_BEHALF_ACCRUE_INTEREST_FAILED`                        |
| 54   | `REPAY_BORROW_ACCRUE_INTEREST_FAILED`                        |
| 55   | `REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED`        |
| 56   | `REPAY_BORROW_COMPTROLLER_REJECTION`                         |
| 57   | `REPAY_BORROW_FRESHNESS_CHECK`                               |
| 58   | `REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED` |
| 59   | `REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED`          |
| 60   | `REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE`                      |
| 61   | `SET_COLLATERAL_FACTOR_OWNER_CHECK`                          |
| 62   | `SET_COLLATERAL_FACTOR_VALIDATION`                           |
| 63   | `SET_COMPTROLLER_OWNER_CHECK`                                |
| 64   | `SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED`             |
| 65   | `SET_INTEREST_RATE_MODEL_FRESH_CHECK`                        |
| 66   | `SET_INTEREST_RATE_MODEL_OWNER_CHECK`                        |
| 67   | `SET_MAX_ASSETS_OWNER_CHECK`                                 |
| 68   | `SET_ORACLE_MARKET_NOT_LISTED`                               |
| 69   | `SET_PENDING_ADMIN_OWNER_CHECK`                              |
| 70   | `SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED`                  |
| 71   | `SET_RESERVE_FACTOR_ADMIN_CHECK`                             |
| 72   | `SET_RESERVE_FACTOR_FRESH_CHECK`                             |
| 73   | `SET_RESERVE_FACTOR_BOUNDS_CHECK`                            |
| 74   | `TRANSFER_COMPTROLLER_REJECTION`                             |
| 75   | `TRANSFER_NOT_ALLOWED`                                       |
| 76   | `TRANSFER_NOT_ENOUGH`                                        |
| 77   | `TRANSFER_TOO_MUCH`                                          |
| 78   | `ADD_RESERVES_ACCRUE_INTEREST_FAILED`                        |
| 79   | `ADD_RESERVES_FRESH_CHECK`                                   |
| 80   | `ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE`                      |
| 81   | `REDUCE_RESERVES_GUARDIAN_NOT_SET`                           |
| 82   | `TRIGGER_ACTIVATED_BEFORE_REDEEM_OR_BORROW`                  |
