# Contract Interactions

## Market Membership

### Enter Markets

Enable supplied assets as collateral. You must enter a market before you can borrow against it. You can enter multiple markets in a single call.

```solidity
function enterMarkets(address[] memory mTokens) public returns (uint[] memory)
```

| Parameter   | Type        | Description                                      |
| ----------- | ----------- | ------------------------------------------------ |
| `mTokens`   | `address[]` | The list of mToken addresses to enter            |
| **returns** | `uint[]`    | An array of error codes per market (0 = success) |

**Solidity**

```solidity
Comptroller comptroller = Comptroller(0x...);

address[] memory markets = new address[](2);
markets[0] = address(mUSDC);
markets[1] = address(mWETH);

uint[] memory errors = comptroller.enterMarkets(markets);
require(errors[0] == 0 && errors[1] == 0, "enterMarkets failed");
```

***

### Exit Market

Remove an asset from your collateral set. This will fail if you have an outstanding borrow in this market, or if exiting would make your position undercollateralized.

```solidity
function exitMarket(address mTokenAddress) external returns (uint)
```

| Parameter       | Type      | Description                                           |
| --------------- | --------- | ----------------------------------------------------- |
| `mTokenAddress` | `address` | The mToken to exit                                    |
| **returns**     | `uint`    | 0 on success, otherwise an [Error code](#error-codes) |

***

### Check Membership

Check whether an account has entered a specific market.

```solidity
function checkMembership(address account, MToken mToken) external view returns (bool)
```

***

### Get Assets In

Get the list of markets an account has entered.

```solidity
function getAssetsIn(address account) external view returns (MToken[] memory)
```

| Parameter   | Type       | Description                                       |
| ----------- | ---------- | ------------------------------------------------- |
| `account`   | `address`  | The account to query                              |
| **returns** | `MToken[]` | Array of mToken addresses the account has entered |

***

## Liquidity & Liquidation

### Get Account Liquidity

Calculate an account's available borrowing capacity (or shortfall if underwater). Values are denominated in USD with 18 decimals of precision.

```solidity
function getAccountLiquidity(address account) public view returns (uint, uint, uint)
```

| Parameter   | Type                 | Description                     |
| ----------- | -------------------- | ------------------------------- |
| `account`   | `address`            | The account to evaluate         |
| **returns** | `(uint, uint, uint)` | `(error, liquidity, shortfall)` |

* If `liquidity > 0`: the account can borrow up to this USD value
* If `shortfall > 0`: the account is underwater and can be liquidated

**Solidity**

```solidity
Comptroller comptroller = Comptroller(0x...);

(uint err, uint liquidity, uint shortfall) = comptroller.getAccountLiquidity(account);
require(err == 0, "liquidity check failed");

if (shortfall > 0) {
    // Account is liquidatable
} else {
    // Account can borrow up to `liquidity` USD worth
}
```

***

### Get Hypothetical Account Liquidity

Calculate what an account's liquidity would be if a hypothetical redeem or borrow were executed. Useful for simulating whether an action would make a position unsafe.

```solidity
function getHypotheticalAccountLiquidity(
    address account,
    address mTokenModify,
    uint redeemTokens,
    uint borrowAmount
) public view returns (uint, uint, uint)
```

| Parameter      | Type                 | Description                                             |
| -------------- | -------------------- | ------------------------------------------------------- |
| `account`      | `address`            | The account to simulate                                 |
| `mTokenModify` | `address`            | The mToken market to hypothetically interact with       |
| `redeemTokens` | `uint`               | The number of mTokens to hypothetically redeem          |
| `borrowAmount` | `uint`               | The amount of underlying to hypothetically borrow       |
| **returns**    | `(uint, uint, uint)` | `(error, hypotheticalLiquidity, hypotheticalShortfall)` |

***

### Liquidation Calculate Seize Tokens

Calculate how many collateral mTokens a liquidator would seize for a given repay amount.

```solidity
function liquidateCalculateSeizeTokens(
    address mTokenBorrowed,
    address mTokenCollateral,
    uint actualRepayAmount
) external view returns (uint, uint)
```

| Parameter           | Type           | Description                                                        |
| ------------------- | -------------- | ------------------------------------------------------------------ |
| `mTokenBorrowed`    | `address`      | The market in which the borrow is being repaid                     |
| `mTokenCollateral`  | `address`      | The market in which collateral will be seized                      |
| `actualRepayAmount` | `uint`         | The amount of underlying being repaid                              |
| **returns**         | `(uint, uint)` | `(error, seizeTokens)` - the number of collateral mTokens to seize |

***

## Market Information

### Get All Markets

Returns the list of all mToken markets currently listed in the protocol.

```solidity
function getAllMarkets() public view returns (MToken[] memory)
```

***

### Markets

Query the collateral factor and listing status of a specific market.

```solidity
function markets(address mToken) external view returns (bool isListed, uint collateralFactorMantissa)
```

| Return                     | Type   | Description                                                    |
| -------------------------- | ------ | -------------------------------------------------------------- |
| `isListed`                 | `bool` | Whether the market is listed in the Comptroller                |
| `collateralFactorMantissa` | `uint` | The collateral factor, scaled by `1e18` (e.g. `0.75e18` = 75%) |

***

### Close Factor

The maximum percentage of a borrower's debt that can be repaid in a single liquidation.

```solidity
function closeFactorMantissa() public view returns (uint)
```

Scaled by `1e18`. For example, `0.5e18` means a liquidator can repay up to 50% of the borrow in one transaction.

Typical range: `0.05e18` (5%) to `0.9e18` (90%). Note: the setter performs an admin check only - range validation is **not enforced on-chain**.

***

### Liquidation Incentive

The discount on collateral that liquidators receive, expressed as a multiplier.

```solidity
function liquidationIncentiveMantissa() public view returns (uint)
```

Scaled by `1e18`. For example, `1.1e18` means liquidators receive a 10% discount on seized collateral.

***

### Borrow Caps

```solidity
function borrowCaps(address mToken) public view returns (uint)
```

Returns the maximum amount of underlying that can be borrowed from a market. A value of `0` means no cap.

***

### Supply Caps

```solidity
function supplyCaps(address mToken) public view returns (uint)
```

Returns the maximum amount of underlying that can be supplied to a market. A value of `0` means no cap.

***

## Rewards

### Claim Reward

Claim accrued WELL rewards. Multiple overloads are available depending on how targeted you want the claim to be.

```solidity
// Claim all rewards for msg.sender across all markets
function claimReward() public

// Claim all rewards for a specific account
function claimReward(address holder) public

// Claim rewards for a specific account in specific markets
function claimReward(address holder, MToken[] memory mTokens) public

// Claim rewards for multiple accounts, specifying markets and sides
function claimReward(
    address[] memory holders,
    MToken[] memory mTokens,
    bool borrowers,
    bool suppliers
) public
```

| Parameter   | Type        | Description                          |
| ----------- | ----------- | ------------------------------------ |
| `holders`   | `address[]` | The accounts to claim for            |
| `mTokens`   | `MToken[]`  | The markets to claim from            |
| `borrowers` | `bool`      | Whether to claim borrow-side rewards |
| `suppliers` | `bool`      | Whether to claim supply-side rewards |

**Solidity**

```solidity
Comptroller comptroller = Comptroller(0x...);

// Simple: claim everything for yourself
comptroller.claimReward();

// Targeted: claim supply-side rewards only, for specific markets
MToken[] memory markets = new MToken[](1);
markets[0] = MToken(mUSDC);
address[] memory holders = new address[](1);
holders[0] = msg.sender;
comptroller.claimReward(holders, markets, false, true);
```

***

## Events

| Event                     | Parameters                                                                                 |
| ------------------------- | ------------------------------------------------------------------------------------------ |
| `MarketListed`            | `MToken mToken`                                                                            |
| `MarketEntered`           | `MToken mToken, address account`                                                           |
| `MarketExited`            | `MToken mToken, address account`                                                           |
| `NewCloseFactor`          | `uint oldCloseFactorMantissa, uint newCloseFactorMantissa`                                 |
| `NewCollateralFactor`     | `MToken mToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa`        |
| `NewLiquidationIncentive` | `uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa`               |
| `NewPriceOracle`          | `PriceOracle oldPriceOracle, PriceOracle newPriceOracle`                                   |
| `NewPauseGuardian`        | `address oldPauseGuardian, address newPauseGuardian`                                       |
| `ActionPaused`            | `string action, bool pauseState`                                                           |
| `ActionPaused`            | `MToken mToken, string action, bool pauseState`                                            |
| `NewBorrowCap`            | `MToken indexed mToken, uint newBorrowCap`                                                 |
| `NewBorrowCapGuardian`    | `address oldBorrowCapGuardian, address newBorrowCapGuardian`                               |
| `NewSupplyCap`            | `MToken indexed mToken, uint newSupplyCap`                                                 |
| `NewSupplyCapGuardian`    | `address oldSupplyCapGuardian, address newSupplyCapGuardian`                               |
| `NewRewardDistributor`    | `MultiRewardDistributor oldRewardDistributor, MultiRewardDistributor newRewardDistributor` |

***

## Error Codes

All Comptroller functions that return a `uint` use `0` for success. Non-zero values correspond to:

| Code | Name                            | Description                                  |
| ---- | ------------------------------- | -------------------------------------------- |
| 0    | `NO_ERROR`                      | Success                                      |
| 1    | `UNAUTHORIZED`                  | Caller is not authorized                     |
| 2    | `COMPTROLLER_MISMATCH`          | mToken's comptroller does not match          |
| 3    | `INSUFFICIENT_SHORTFALL`        | Account is not underwater (cannot liquidate) |
| 4    | `INSUFFICIENT_LIQUIDITY`        | Not enough liquidity for the operation       |
| 5    | `INVALID_CLOSE_FACTOR`          | Close factor is outside valid range          |
| 6    | `INVALID_COLLATERAL_FACTOR`     | Collateral factor exceeds maximum (90%)      |
| 7    | `INVALID_LIQUIDATION_INCENTIVE` | Liquidation incentive is invalid             |
| 8    | `MARKET_NOT_ENTERED`            | Account has not entered this market          |
| 9    | `MARKET_NOT_LISTED`             | Market is not listed in the Comptroller      |
| 10   | `MARKET_ALREADY_LISTED`         | Market has already been listed               |
| 11   | `MATH_ERROR`                    | Internal math error                          |
| 12   | `NONZERO_BORROW_BALANCE`        | Cannot exit market with outstanding borrows  |
| 13   | `PRICE_ERROR`                   | Oracle returned an invalid price             |
| 14   | `REJECTION`                     | Comptroller rejected the operation           |
| 15   | `SNAPSHOT_ERROR`                | Account snapshot failed                      |
| 16   | `TOO_MANY_ASSETS`               | Account has entered too many markets         |
| 17   | `TOO_MUCH_REPAY`                | Repay amount exceeds allowed close amount    |

***

## Failure Info

The `info` field in the `Failure` event provides granular context. These correspond to the `ComptrollerErrorReporter.FailureInfo` enum:

| 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_GAS_AMOUNT_OWNER_CHECK`                  |
