# Comptroller

## Core methods

This section contains the primary methods for interacting with the Comptroller for the Cozy protocol.

### Create protection markets

Anyone can create new protection markets with the Comptroller's `deployProtectionMarket` methods. For more information on creating protection markets, see the [Create a protection Mmrket](https://v1-docs.cozy.finance/for-developers/guides/how-do-i-create-a-protection-market) guide.

### Entering and exiting markets

When supplying assets to a money market, those funds are not automatically available as collateral for borrowing. Instead, you must specify when you want supplied assets to be used as collateral. Telling the protocol you want to use a certain asset as collateral is known as "entering the market".

{% hint style="info" %}
All protection markets have collateral factors of zero, meaning funds supplied to protection markets cannot be used as collateral. Therefore, you should only explicitly enter markets for funds supplied to a money market.
{% endhint %}

To enter a market, call the `enterMarkets` method on the Comptroller, where `cTokens` is an array of Cozy money market addresses.

```javascript
function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory);
```

When you no longer want to use supplied funds in a market as collateral, you can exit the market with the `exitMarket` method described below. Notice that you can enter multiple markets in a single transaction, but you can only exit one market per call. When exiting a market, your transaction will fail with an error code if you have an outstanding borrow balance in that market, or if exiting the market would result in insufficient [account liquidity](#account-liquidity).

```javascript
function exitMarket(address cTokenAddress) external returns (uint256);
```

Note that borrowing from a market automatically enters you into that market, since liquidity calculations loop through all entered markets to determine if you have sufficient account liquidity.

Both the `enterMarkets` method and the `exitMarket` methods return a `uint256` value of 0 for a successful call, and return an [error code](https://v1-docs.cozy.finance/for-developers/error-codes) for an unsuccessful call.

## View methods

This section contains the primary methods for viewing information managed by the Comptroller.

### Account assets

You can use the `getAssetsIn` method to return a list of markets that a user has [entered](#entering-and-exiting-markets). The method takes the user's address as an input and returns the full set of markets for the specified user in an array. The array of markets returned by this method is the full set of markets used for liquidity calculations.

```javascript
function getAssetsIn(address account) external view returns (CToken[] memory);
```

### Collateral factors

Every market has a collateral factor that represents how much borrow power is increased by when that market's assets are used as collateral. This collateral factor can range from 0% to 90% and can be interpreted as:

* A value of 0% means using that an asset cannot be used as collateral, as it gives you no borrowing power.
* A value of 90% means supplying $100 of that asset allows you to borrow up to $90 of another asset.

All protection markets have collateral factors of 0%, and money markets can have collateral factors anywhere in the 0–90% range.

You can retrieve the collateral factor for a given market with the following `markets` function by providing a Cozy token market address as input:

```javascript
function markets(address cTokenAddress) view returns (bool, uint256, bool)
```

The function returns the first `bool` value for the `isListed` property as `true` if the market is recognized by the Comptroller or `false` if it is not.

The `uint256` returned by the function is an 18 decimal number for the `collateralFactorMantissa` property described above. A value of 0.9 means that you can supply this market's assets as collateral to borrow up to 90% of the supplied value.

The second `bool` value is for the `isComped` property that is not currently used and can be safely ignored.

### Listed markets

You can use the `getAllMarkets` method to return an array of all Cozy token markets supported by the Comptroller as follows:

```javascript
function getAllMarkets() external view returns (CToken[] memory);
```

The addresses returned from this array can be directly passed as inputs to the `markets` function described in the [CollateralFactors](#collateral-factors) section to retrieve various metadata for the specified market.

### Account liquidity

Account liquidity specifies a user's borrowing power in USD. If you borrow too much (for example, if the value of your collateral falls), your account liquidity can fall below zero and can result in your account being liquidated.

Account liquidity is based on [all markets entered](#account-assets) by a user. For each of those assets, the collateral quantity is converted to USD and multiplied by that asset's collateral factor. Summing these values and subtracting current borrow balances results in the current account liquidity for a user.

You can query the account liquidity for a user as follows:

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

The first `uint256` returned is zero on success or an [error code](https://v1-docs.cozy.finance/for-developers/error-codes) on failure.

If the account queried has positive account liquidity, that is, the user can borrow more assets, the second `uint256` will equal the user's account liquidity and the third `uint256` will equal zero. If the account queried has negative account liquidity, that is, the user has a shortfall and can be liquidated, the second `uint256` will be zero and the third `uint256` will equal the shortfall amount.

### Liquidation incentive

To incentivize liquidations of accounts that have a shortfall, the `liquidationIncentiveMantissa` method specifies additional collateral that liquidators receive. For example, if the liquidation incentive is 1.08e18, then liquidators receive 8% more collateral than the borrow amount they closed.

To illustrate how the incentive works, assume a liquidator repays $1000 worth of a user's borrows. If the liquidation incentive is 1.08e18, then the liquidator will receive $1000 \* 1.08 = $1080 of the user's collateral. The liquidation incentive is the same for all markets, and can be changed. You can read the current value as follows:

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

### Close factor

When liquidating an account, you cannot necessarily repay the full borrow amount and entirely liquidate the borrower. Instead, the close factor specifies what portion of their account can be repaid in a single liquidation. This value applies to individual borrowed assets, not the overall position. The close factor is the same for all markets, and can be changed. You can read the current value as follows:

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

## Events

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

```javascript
// Emitted when a third party adds a protection market
event ProtectionMarketListed(CToken cToken, address trigger);

// Emitted when an account enters a market
event MarketEntered(CToken cToken, address account);

// Emitted when an account exits a market
event MarketExited(CToken cToken, address account);
```

## Error handling

This section contains information about error codes and failure messages that you might see when calling methods on the Comptroller.

### Error codes

The following table below contains a list of error codes that you might see when calling methods on the Comptroller.

| Code | Name                              | Description                                                                         |
| ---- | --------------------------------- | ----------------------------------------------------------------------------------- |
| 0    | `NO_ERROR`                        | Call succeeded                                                                      |
| 1    | `UNAUTHORIZED`                    | Caller is not authorized                                                            |
| 2    | `COMPTROLLER_MISMATCH`            | Cannot liquidate across markets with different comptrollers                         |
| 3    | `INSUFFICIENT_SHORTFALL`          | The account cannot be liquidated since it has no shortfall                          |
| 4    | `INSUFFICIENT_LIQUIDITY`          | Redeem or borrow not allowed because the account has insufficient liquidity         |
| 5    | `INVALID_CLOSE_FACTOR`            | Outdated, not used                                                                  |
| 6    | `INVALID_COLLATERAL_FACTOR`       | Cannot set new collateral factor, as specified value is invalid                     |
| 7    | `INVALID_LIQUIDATION_INCENTIVE`   | Outdated, not used                                                                  |
| 8    | `MARKET_NOT_ENTERED`              | Outdated, not used                                                                  |
| 9    | `MARKET_NOT_LISTED`               | The specified market is not listed by the Comptroller                               |
| 10   | `MARKET_ALREADY_LISTED`           | Specified market already exists                                                     |
| 11   | `MATH_ERROR`                      | An error occurred in a math operation                                               |
| 12   | `NONZERO_BORROW_BALANCE`          | Cannot exit market if borrow balance is above zero                                  |
| 13   | `PRICE_ERROR`                     | The Comptroller could not get a valid price for an asset                            |
| 14   | `REJECTION`                       | The Comptroller rejected the action specified by a Cozy token                       |
| 15   | `SNAPSHOT_ERROR`                  | Unable to read a user's account borrows and market exchange rate                    |
| 16   | `TOO_MANY_ASSETS`                 | Cannot enter a number of markets greater than \`maxAssets'                          |
| 17   | `TOO_MUCH_REPAY`                  | Cannot repay more than the protocol will allow                                      |
| 18   | `INVALID_TRIGGER`                 | The specified trigger is not valid so a protection market cannot be created with it |
| 19   | `PROTECTION_MARKET_FACTORY_ERROR` | The specified ProtectionMarketFactory address is not valid                          |

### Failure codes and logged messages

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

| Code | Name                                           |
| ---- | ---------------------------------------------- |
| 0    | `ACCEPT_ADMIN_PENDING_ADMIN_CHECK`             |
| 1    | `ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK`  |
| 2    | `EXIT_MARKET_BALANCE_OWED`                     |
| 3    | `EXIT_MARKET_REJECTION`                        |
| 4    | `SET_CLOSE_FACTOR_OWNER_CHECK`                 |
| 5    | `SET_CLOSE_FACTOR_VALIDATION`                  |
| 6    | `SET_COLLATERAL_FACTOR_OWNER_CHECK`            |
| 7    | `SET_COLLATERAL_FACTOR_NO_EXISTS`              |
| 8    | `SET_COLLATERAL_FACTOR_VALIDATION`             |
| 9    | `SET_COLLATERAL_FACTOR_WITHOUT_PRICE`          |
| 10   | `SET_IMPLEMENTATION_OWNER_CHECK`               |
| 11   | `SET_LIQUIDATION_INCENTIVE_OWNER_CHECK`        |
| 12   | `SET_LIQUIDATION_INCENTIVE_VALIDATION`         |
| 13   | `SET_MAX_ASSETS_OWNER_CHECK`                   |
| 14   | `SET_PENDING_ADMIN_OWNER_CHECK`                |
| 15   | `SET_PENDING_IMPLEMENTATION_OWNER_CHECK`       |
| 16   | `SET_PRICE_ORACLE_OWNER_CHECK`                 |
| 17   | `SUPPORT_MARKET_EXISTS`                        |
| 18   | `SUPPORT_MARKET_OWNER_CHECK`                   |
| 19   | `SET_PAUSE_GUARDIAN_OWNER_CHECK`               |
| 20   | `SET_TRIGGER_CHECK`                            |
| 21   | `SET_PROTECTION_WITH_INVALID_UNDERLYING`       |
| 22   | `SET_PROTECTION_UNDERLYING_WITHOUT_PRICE`      |
| 23   | `SET_PROTECTION_MARKET_FACTORY_OWNER_CHECK`    |
| 24   | `SET_PROTECTION_MARKET_FACTORY_VALIDITY_CHECK` |
| 25   | `SET_RESERVE_GUARDIAN_OWNER_CHECK`             |
