Comptroller

The comptroller is the management layer of a pool. Each pool has its own unique comptroller and these are deployed by the PoolDirectory contract.

It manages many aspects of a pool, including but not limited to:

  • Assets/Tokens that are listed in a pool and if they can be supplied/borrowed

  • LTVs, it helps manage the risk of the pool by managing the amount of debt which can be issued against a particular collateral

  • User Collateral, it manages which assets supplied by a user are explicitly used as collateral against their debt

  • Price Oracle, it maps the token balances into prices using a PriceOracle

Implementation

The comptroller is implemented in a proxy-contract fashion, where the Unitroller contract proxies all interactions/logic from the Comptroller while using the storage of Unitroller. To learn more about upgradable proxies, read Proxy Upgrade Pattern by OpenZeppelin.

Some Important Terms

Close Factor

Valid range: 0.01*1e18 to 1*1e18 (corresponds to 1% to 100%)

The close factor decides what percentage of a liquidatable account's debt can be repaid in a single transaction. It applies to any single borrowed asset and not the aggregated value of a user’s outstanding borrowing.

For close factor less than 100%, this ensures positions aren't fully liquidated in one step, and partial liquidations take place.

Collateral Factor

Valid range: 0*1e18 to 0.90*1e18 (corresponds to 0% to 90%)

A mToken's collateral factor represents the proportionate increase in liquidity (borrow limit) that an account receives by minting the mToken.

Generally, large or liquid assets have high collateral factors, while small or illiquid assets have low collateral factors. If an asset has a 0% collateral factor, it can't be used as collateral (or seized in liquidation), though it can still be borrowed. This is often called an LTV ("Loan to Value") too.

Liquidation Incentive

Valid range: 1*1e18 to 1.2*1e18 (corresponds to 0% to 20% extra collateral)

The additional collateral given to liquidators as an incentive to perform liquidation of underwater accounts. For example, if the liquidation incentive is 1.1, liquidators receive an extra 10% of the borrower's collateral for every unit they close.

Supply / Borrow Cap

Caps basically set the max amount of tokens that can be supplied or borrowed from a pool. These are often referred to as ceilings, ie: borrow cap = debt ceiling

Structs

struct Market {
    bool isListed;
    uint collateralFactorMantissa;
}

The Market struct is used to map the relationship between an mToken and the pool comptroller.

  • isListed implies Whether or not this market is listed

  • collateralFactorMantissa

View Methods

getAllMarkets() -> mToken[]

function getAllMarkets() external view returns(mToken[] memory);

Returns list of mToken addresses corresponding to all assets that are supported in the pool.

getAllBorrowers() -> address[]

function getAllBorrowers() external view returns(address[] memory);

Returns list of users who have engaged in borrowing in the pool.

getWhitelist -> address[]

function getWhitelist() external view returns(address[] memory);

Returns list of users who are whitelisted/allowed to use the pool, if it has a whitelist.

getRewardDistributors -> address[]

function getRewardsDistributors() external view returns(address[] memory);

Returns all the reward distributor contract addresses that are actively distributing rewards in the pool.

oracle -> address

function oracle() external view returns(address);

Returns the address of the price oracle contract used in the pool.

closeFactorMantissa -> uint256

function closeFactorMantissa() external view returns(uint256);

Returns the closeFactor scaled to 18 decimals. 5% = 0.05e18.

liquidationIncentiveMantissa -> uint256

function liquidationIncentiveMantissa() external view returns(uint256);

Returns the liquidationIncentive scaled by 18 decimals.

markets(address) -> Market (Collateral Factor)

function markets(address mToken) external view returns(Market memory);

(, uint collateralFactor) = comptroller.markets(mUSDC);

Returns the official metadata for a particular mToken in the pool. Shares if it is listed and the collateral factor (or "LTV") of this mToken.

borrowCaps(address) -> uint

function borrowCaps(address mToken) external view returns(uint256);

Returns the borrow cap (or "debt ceiling") set on a particular mToken.

supplyCaps(address) -> uint

function supplyCaps(address mToken) external view returns(uint256);

Returns the supply cap set on a particular mToken.

Writeable Methods

enterMarkets(address[]) -> uint[]

function enterMarkets(address[] memory mTokens) external returns(uint[] memory);

Enter a list of mTokens whose markets you wish to enter. It is not an error to enter the same market more than once. In order to supply collateral or borrow in a market, you need to execute this first.

  • mTokens - list of mTokens/markets to set as collateral

  • returns - an error code for each market. 0 is success, and anything else is a Failure.

exitMarket(address) -> uint

function exitMarket(address mToken) external returns(uint);

Exit a market. It is not an error to exit a market which is not currently entered. Exited markets do not count towards account liquidity calculations.

  • mToken - The mToken/market to exclude out of the account liquidity calculations

  • returns - an error code for the market. 0 is success, and anything else is a Failure.

_addRewardsDistributor(address) -> uint

function _addRewardsDistributor(address distributor) external returns(uint);

Adds a rewards distributor, which can be used to incentivise supply/borrow.

  • distributor - The rewards distributor contract address

  • returns - an error code. 0 is success, and anything else is a Failure.

_setWhitelistEnforcement(bool) -> uint

function _setWhitelistEnforcement(bool state) external returns(uint);

Sets the enforcement of a pool's whitelist to true/false and thus enables/disables the pool whitelist.

  • state - The boolean state for enabling/disabling whitelist

  • returns - an error code. 0 is success, and anything else is a Failure.

_setWhitelistStatuses(address[], bool[]) -> uint

function _setWhitelistStatuses(
    address[] memory users, 
    bool[] memory state
) external returns(uint256);

Sets whitelist statuses for user accounts, this decides which users are on the whitelist and which users are not.

  • users - The list of users for toggling their status

  • returns - an error code. 0 is a success, and anything else is a Failure.

_setPriceOracle(address) -> uint

function _setPriceOracle(address newOracle) external returns(uint256);

Updates the PriceOracle contract used by the pool.

  • newOracle - The address of a new oracle to be set on the pool

  • returns - an error code. 0 is success and anything else is a Failure.

_setCloseFactor(uint) -> uint

function _setCloseFactor(
    uint256 newCloseFactorMantissa
) external returns(uint256);

Valid range: 0.01*1e18 to 1*1e18 (corresponds to 1% to 100%)

Sets specified close factor on the pool.

  • newCloseFactorMantissa - The new value to be set for close factor of the pool

  • returns - an error code. 0 is a success and anything else is a Failure.

_setCollateralFactor(address, uint) -> uint

function _setCollateralFactor(
    address mToken,
    uint256 newCollateralFactorMantissa
) external returns(uint256);

Valid range: 0*1e18 to 0.90*1e18 (corresponds to 0% to 90%)

Sets specified new collateral factor for a particular mToken in the pool.

  • mToken - The mToken for which the collateral factor is updated

  • newCollateralFactorMantissa - The new value to be set as collateral factor of the pool

  • returns - an error code. 0 is a success and anything else is a Failure.

_setLiquidationIncentive(uint) -> uint

function _setLiquidationIncentive(
    uint256 newLiquidationIncentiveMantissa
 ) external returns(uint256);

Valid range: 1*1e18 to 1.2*1e18 (corresponds to 0% to 20% extra collateral)

Sets specified new liquidation incentive for the pool.

  • newLiquidationIncentiveMantissa - The new value to be set as liquidation incentive of the pool

  • returns - an error code. 0 is a success and anything else is a Failure.

_deployMarket(bool, bytes, uint) -> uint

function _deployMarket(
    bool isCEther,
    bytes calldata constructorData,
    uint collateralFactorMantissa) external returns(uint);

Deploy an mToken for the pool. Can be called only by pool administrator.

  • isCEther - if the token is a native token, for example: MATIC on the polygon network

  • constructorData - the abi-encoded arguments to be passed to the constructor

  • collateralFactorMantissa - the collateral factor to be set on the new mToken

  • returns - an error code. 0 is a success and anything else is a Failure.

_unsupportMarket(address) -> uint

function _unsupportMarket(address mToken) external returns(uint);

Removes support for a particular mToken from the pool. Can be called only by pool administrator. Note that there should be no supply or debt in this mToken to be removed.

  • mToken - address of the mToken that has to be removed/unSupported.

  • returns - an error code. 0 is a success and anything else is a Failure.

_setMarketSupplyCaps(address[], uint[])

function _setMarketSupplyCaps(
    address[] memory mTokens,
    uint[] memory caps
) external;

Sets a supply cap / ceiling for mTokens. Can be called only by pool administrator.

  • mTokens - list of addresses of mTokens to set supply caps for.

  • caps - list of token amounts to be set as supply caps.

_setMarketBorrowCaps(address[], uint[])

function _setMarketBorrowCaps(
    address[] memory mTokens,
    uint[] memory caps
) external;

Sets a borrow cap / debt ceiling for mTokens. Can be called only by pool administrator.

  • mTokens - list of addresses of mTokens to set borrow caps for.

  • caps - list of token amounts to be set as borrow caps.

_setBorrowCapGuardian(address)

function _setBorrowCapGuardian(address newBorrowCapGuardian) external;

Sets a borrow cap guardian, which is an account that can change borrow/supply caps/ceilings in the pool in cases of emergency. Can be called only by pool administrator.

  • newBorrowCapGuardian - address of the account

_setPauseGuardian(address) -> uint

function _setPauseGuardian(address newPauseGuardian) external returns(uint);

Sets a pause guardian, which is an account that can pause/unpause borrow/supply in the pool in cases of emergency. Can be called only by pool administrator.

  • newPauseGuardian - address of the account

  • returns - an error code. 0 is a success, and anything else is a Failure.

_setMintPaused(address, bool) -> bool

function _setMintPaused(address mToken, bool state) external returns(bool);

Pauses all users' ability to supply in an mToken. Can be called by pool administrator or pauseGuardian.

  • mToken - address of the mToken to be supply paused

  • state - boolean state to be set to pause supply

  • returns - final boolean state of the supply, paused/unPaused

_setBorrowPaused(address, bool) -> bool

function _setBorrowPaused(address mToken, bool state) external returns(bool);

Pauses all users' ability to borrow in an mToken. Can be called by pool administrator or pauseGuardian.

  • mToken - address of the mToken to be borrow paused

  • state - boolean state to be set to pause borrow

  • returns - final boolean state of the borrow, paused/unPaused

Error Codes

CodeNameDescription

0

NO_ERROR

Success. Not an error.

1

UNAUTHORIZED

The sender is not authorized to perform this action.

2

COMPTROLLER_MISMATCH

Liquidation cannot be performed in markets with different comptrollers.

3

INSUFFICIENT_SHORTFALL

The account does not have sufficient shortfall to perform this action.

4

INSUFFICIENT_LIQUIDITY

The account does not have sufficient liquidity to perform this action.

5

INVALID_CLOSE_FACTOR

The close factor is not valid.

6

INVALID_COLLATERAL_FACTOR

The collateral factor is not valid.

7

INVALID_LIQUIDATION_INCENTIVE

The liquidation incentive is not valid.

8

MARKET_NOT_ENTERED

The market has not been entered by the account.

9

MARKET_NOT_LISTED

The market is not currently listed by the comptroller.

10

MARKET_ALREADY_LISTED

An admin tried to list the same market more than once.

11

MATH_ERROR

A math calculation error occurred.

12

NONZERO_BORROW_BALANCE

The action cannot be performed since the account carries a borrow balance.

13

PRICE_ERROR

The comptroller could not obtain a required price of an asset.

14

REJECTION

The comptroller rejects the action requested by the market/mToken.

15

SNAPSHOT_ERROR

The comptroller could not get the account borrows and exchange rate from the market.

16

TOO_MANY_ASSETS

Attempted to enter more markets than are currently supported.

17

TOO_MUCH_REPAY

Attempted to repay more than is allowed by the protocol.

18

SUPPLIER_NOT_WHITELISTED

The comptroller could not get the account borrows and exchange rate from the market.

19

BORROW_BELOW_MIN

Attempted to borrow less than the minimum allowed amount.

20

SUPPLY_ABOVE_MAX

Attempted to supply more than the maximum allowed amount.

21

NONZERO_TOTAL_SUPPLY

Admin attempted to unsupport a market that has some supply.

Failure Info

CodeName

0

ACCEPT_ADMIN_PENDING_ADMIN_CHECK

1

ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK

2

ADD_REWARDS_DISTRIBUTOR_OWNER_CHECK

3

EXIT_MARKET_BALANCE_OWED

4

EXIT_MARKET_REJECTION

5

TOGGLE_ADMIN_RIGHTS_OWNER_CHECK

6

TOGGLE_AUTO_IMPLEMENTATIONS_ENABLED_OWNER_CHECK

7

SET_CLOSE_FACTOR_OWNER_CHECK

8

SET_CLOSE_FACTOR_VALIDATION

9

SET_COLLATERAL_FACTOR_OWNER_CHECK

10

SET_COLLATERAL_FACTOR_NO_EXISTS

11

SET_COLLATERAL_FACTOR_VALIDATION

12

SET_COLLATERAL_FACTOR_WITHOUT_PRICE

13

SET_LIQUIDATION_INCENTIVE_OWNER_CHECK

14

SET_LIQUIDATION_INCENTIVE_VALIDATION

15

SET_MAX_ASSETS_OWNER_CHECK

16

SET_PENDING_ADMIN_OWNER_CHECK

17

SET_PENDING_IMPLEMENTATION_CONTRACT_CHECK

18

SET_PENDING_IMPLEMENTATION_OWNER_CHECK

19

SET_PRICE_ORACLE_OWNER_CHECK

20

SET_WHITELIST_ENFORCEMENT_OWNER_CHECK

21

SET_WHITELIST_STATUS_OWNER_CHECK

22

SUPPORT_MARKET_EXISTS

23

SUPPORT_MARKET_OWNER_CHECK

24

SET_PAUSE_GUARDIAN_OWNER_CHECK

25

UNSUPPORT_MARKET_OWNER_CHECK

26

UNSUPPORT_MARKET_DOES_NOT_EXIST

27

UNSUPPORT_MARKET_IN_USE

Last updated