Compound Presidio

Compound v2 (a.k.a. Presidio) is a set of smart contracts deployed on the Ethereum blockchain, which allows supplying and borrowing of ERC-20 tokens. This page details the on-chain function 'ABI' for developing smart contracts or building Web3-enabled dApps.

For information on the Compound API, please visit the Compound API docs.

Getting Started

The Compound Protocol v2 is currently deployed on the following networks:

MainNet

ContractABIAddress
cBATJSON
0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e
cDAIJSON
0xf5dce57282a584d2746faf1593d3121fcac444dc
cETHJSON
0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5
cREPJSON
0x158079ee67fce2f58472a96584a73c7ab9ac95c1
cUSDCJSON
0x39aa39c021dfbae8fac545936693ac917d5e7563
cZRXJSON
0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407
PriceOracleJSON
0x02557a5e05defeffd4cae6d83ea3d173b272c904
ComptrollerJSON
0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b
WhitePaperInterestRateModelJSON
0xc64c4cba055efa614ce01f4bad8a9f519c4f8fab
WhitePaperInterestRateModelJSON
0xbae04cbf96391086dc643e842b517734e214d698
WhitePaperInterestRateModelJSON
0xa1046abfc2598f48c44fb320d281d3f3c0733c9a

Rinkeby

ContractABIAddress
cBATJSON
0xebf1a11532b93a529b5bc942b4baa98647913002
cDAIJSON
0x6d7f0754ffeb405d23c51ce938289d4835be3b14
cETHJSON
0xd6801a1dffcd0a410336ef88def4320d6df1883e
cREPJSON
0xebe09eb3411d18f4ff8d859e096c533cac5c6b60
cUSDCJSON
0x5b281a6dda0b271e91ae35de655ad301c976edb1
cWBTCJSON
0x0014f450b8ae7708593f4a46f8fa6e5d50620f96
cZRXJSON
0x52201ff1720134bbbbb2f6bc97bf3715490ec19b
PriceOracleJSON
0xd2b1eca822550d9358e97e72c6c1a93ae28408d0
ComptrollerJSON
0x2eaa9d77ae4d8f9cdd9faacd44016e746485bddb
WhitePaperInterestRateModelJSON
0x1a43bfd39b15dcf444e17ab408c4b5be32deb7f5
WhitePaperInterestRateModelJSON
0x6330d442a2d7ee4dc66c0adb9969e8702aefc9fe
WhitePaperInterestRateModelJSON
0xe12630c8fdd7d0096c9cd72cd228598aebe58795

Kovan

ContractABIAddress
cBATJSON
0xb5e5d0f8c0cba267cd3d7035d6adc8eba7df7cdd
cDAIJSON
0x0a1e4d0b5c71b955c0a5993023fc48ba6e380496
cETHJSON
0xd83f707f003a1f0b1535028ab356fce2667ab855
cREPJSON
0x8a9447df1fb47209d36204e6d56767a33bf20f9f
cUSDCJSON
0xdff375162cfe7d77473c1bec4560dede974e138c
cWBTCJSON
0x189ca88be39c9c1b8c8dd437f5ff1db1f584b14b
cZRXJSON
0x9636246bf34e688c6652af544418b38eb51d2c43
PriceOracleJSON
0x5c46cbeea623dad6e08560ee487d5ac5afd57997
ComptrollerJSON
0x142d11cb90a2b40f7d0c55ed1804988dfc316fae
WhitePaperInterestRateModelJSON
0xb081cf57b1e422b3e627544ec95992cbe8eaf9cb
WhitePaperInterestRateModelJSON
0xe622db19d5bf1f4e61dd57fb11fe887100e5e59e
WhitePaperInterestRateModelJSON
0x5dea9621f23e79003ecc294b4cc1e4c9362dfecc

Ropsten

ContractABIAddress
cBATJSON
0x189ca88be39c9c1b8c8dd437f5ff1db1f584b14b
cDAIJSON
0x2b536482a01e620ee111747f8334b395a42a555e
cETHJSON
0x42a628e0c5f3767930097b34b08dcf77e78e4f2b
cREPJSON
0xa3c2c1618214549281e1b15dee9d682c8aa0dc1c
cUSDCJSON
0x43a1363afb28235720fcbdf0c2dab7759091f7e0
cWBTCJSON
0x06e728d7907c164649427d2acfd4c81669d453bf
cZRXJSON
0xdff375162cfe7d77473c1bec4560dede974e138c
PriceOracleJSON
0x5dea9621f23e79003ecc294b4cc1e4c9362dfecc
ComptrollerJSON
0xb081cf57b1e422b3e627544ec95992cbe8eaf9cb
WhitePaperInterestRateModelJSON
0x5592ec0cfb4dbc12d3ab100b257153436a1f0fea
WhitePaperInterestRateModelJSON
0x6e894660985207feb7cf89faf048998c71e8ee89
WhitePaperInterestRateModelJSON
0xbf7a7169562078c96f0ec1a8afd6ae50f12e5a99

goerli

ContractABIAddress
cBATJSON
0xc31211101e6d98bea24f1f32cbeba3e9ac7c9749
cDAIJSON
0xd9fd9e875c9c1d567825e431dd6ed4f0e51aa8bf
cETHJSON
0x2b2aa9c7967efad4b73bfd8801333928806409a1
cREPJSON
0x0812e50f3740b89899ce889c2ab913ea2565f626
cUSDCJSON
0xd9ffe966a831089981bd1539503c9d3cb45e5aab
cWBTCJSON
0xe43d693c6d063bdf4a9681f9a6d9d1439344f4f7
cZRXJSON
0xf412f4d0ee1d96eb486c6c2836bedc4912ba294e
PriceOracleJSON
0x9f8376931cd4c3c38c0128a77082ba40e8d4a8a1
ComptrollerJSON
0xe884dcc3167613a5d6a6ef96f90b74e411f32c8a
WhitePaperInterestRateModelJSON
0x23e8731b39e46941f73951b7f39d921bfd6c2e05
WhitePaperInterestRateModelJSON
0x8cd09af719a93fb3b52a05dbc4ec0fa559eec9c2
WhitePaperInterestRateModelJSON
0x63cfb6469408a64d6713c28231c8d90a609aeb23

cTokens

Every asset supported by the Compound Protocol is now integrated through a cToken smart contract, which is an EIP-20 compliant representation of balances supplied to the protocol. Users supply to the protocol by minting tokens (cTokens), which strictly increase in value relative to their underlying asset.

cTokens are the primary way of interacting with the Compound Protocol. Each cToken contract creates its own money market. When a user mints, redeems, borrows, repays a borrow, liquidates a borrow, or transfers cTokens, she will do so using the cToken contract.

There are currently two types of cTokens: CErc20 and CEther. Though both types expose the EIP-20 interface, CErc20 wraps an underlying ERC-20 asset, while CEther simply wraps Ether itself. As such, the core functions which involve transferring an asset into the protocol have slightly different interfaces depending on the type, each of which is shown below.

Mint

The mint function transfers an asset into the money market, which begins accumulating interest based on the current supply rate for the asset. The number of tokens minted is the amount of underlying asset being provided divided by the current exchange rate

Mint is analagous to supply from the Compound v1 Protocol.

CErc20
function mint(uint mintAmount) returns (uint)
  • msg.sender - The account which shall supply the asset, and own the minted cTokens.
  • mintAmount - The amount of the asset to be supplied, in units of the underlying asset.
  • RETURN - 0 on success, otherwise an Error codes

Before supplying an asset, users must first approve the cToken to access their token balance.

CEther
function mint() payable
  • msg.value - The amount of ether to be supplied, in wei.
  • msg.sender - The account which shall supply the ether, and own the minted cTokens.
  • RETURN - No return, reverts on error.
Solidity
Erc20 underlying = Erc20(0xToken...); // get a handle for the underlying asset contract
CErc20 cToken = CErc20(0x3FDA...); // get a handle for the corresponding cToken contract
underlying.approve(address(cToken), 100); // approve the transfer
assert(cToken.mint(100) == 0); // mint the cTokens and assert there is no error
Web3 1.0
const cToken = CEther.at(0x3FDB...);
await cToken.methods.mint().send({from: myAccount, value: 50});

Redeem

The redeem function transfers the underlying asset from the money market to the user in exchange for previously minted cTokens. The amount of underlying redeemed is the number of cTokens multiplied by the current Exchange Rate. The amount redeemed must be less than the user's account liquidity and the market's available liquidity.

Redeem is analagous to withdraw from the Compound v1 Protocol.

CErc20 / CEther
function redeem(uint redeemTokens) returns (uint)
  • msg.sender - The account to which redeemed funds shall be transferred.
  • redeemTokens - The number of cTokens to be redeemed.
  • RETURN - 0 on success, otherwise an Error codes
Solidity
CEther cToken = CEther(0x3FDB...);
require(cToken.redeem(7) == 0, "something went wrong");
Web3 1.0
const cToken = CErc20.at(0x3FDA...);
cToken.methods.redeem(1).send({from: ...});

Redeem Underlying

The redeem underlying function transfers the underlying asset from the money market to the user in exchange for previously minted cTokens. The number of cTokens redeemed is the amount of underlying divided by the current Exchange Rate. The amount redeemed must be less than the user's account liquidity and the market's available liquidity.

CErc20 / CEther
function redeemUnderlying(uint redeemAmount) returns (uint)
  • msg.sender - The account to which redeemed funds shall be transferred.
  • redeemAmount - The amount of underlying to be redeemed.
  • RETURN - 0 on success, otherwise an Error codes
Solidity
CEther cToken = CEther(0x3FDB...);
require(cToken.redeemUnderlying(50) == 0, "something went wrong");
Web3 1.0
const cToken = CErc20.at(0x3FDA...);
cToken.methods.redeemUnderlying(10).send({from: ...});

Borrow

The borrow function transfers an asset from the money market to the user, and creates a borrow balance which begins accumulating interest based on the borrow rate for the asset.

The amount borrowed must be less than the user's borrow capacity and the market's available liquidity. Users must maintain a collateral requirement to avoid liquidation.

Note that the borrower will receive a transfer of the underlying asset. For CEther, this will be ether and thus the borrower must be payable (for Solidity).

CErc20 / CEther
function borrow(uint borrowAmount) returns (uint)
  • msg.sender - The account to which borrowed funds shall be transferred.
  • borrowAmount - The amount of the underlying asset to be borrowed.
  • RETURN - 0 on success, otherwise an Error codes
Solidity
CErc20 cToken = CErc20(0x3FDA...);
require(cToken.borrow(100) == 0, "got collateral?");
Web3 1.0
const cToken = CEther.at(0x3FDB...);
await cToken.methods.borrow(50).send({from: 0xMyAccount});

Repay Borrow

The repay function transfers an asset into the money market, reducing the user's borrow balance.

CErc20
function repayBorrow(uint repayAmount) returns (uint)
  • msg.sender - The account which borrowed the asset, and shall repay the borrow.
  • repayAmount - The amount of the underlying borrowed asset to be repaid. A value of -1 (i.e. 2256 - 1) can be used to repay the full amount.
  • RETURN - 0 on success, otherwise an Error codes

Before supplying an asset, users must first approve the cToken to access their token balance.

CEther
function repayBorrow() payable
  • msg.value - The amount of ether to be repaid, in wei.
  • msg.sender - The account which borrowed the asset, and shall repay the borrow.
  • RETURN - No return, reverts on error.
Solidity
CEther cToken = CEther(0x3FDB...);
require(cToken.repayBorrow.value(100)() == 0, "transfer approved?");
Web3 1.0
const cToken = CErc20.at(0x3FDA...);
cToken.methods.repayBorrow(10000).send({from: ...});

Repay Borrow Behalf

The repay function transfers an asset into the money market, reducing the user's borrow balance.

CErc20
function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint)
  • msg.sender - The account which shall repay the borrow.
  • borrower - The account which borrowed the asset to be repaid.
  • repayAmount - The amount of the underlying borrowed asset to be repaid. A value of -1 (i.e. 2256 - 1) can be used to repay the full amount.
  • RETURN - 0 on success, otherwise an Error codes

Before supplying an asset, users must first approve the cToken to access their token balance.

CEther
function repayBorrowBehalf(address borrower) payable
  • msg.value - The amount of ether to be repaid, in wei.
  • msg.sender - The account which shall repay the borrow.
  • borrower - The account which borrowed the asset to be repaid.
  • RETURN - No return, reverts on error.
Solidity
CEther cToken = CEther(0x3FDB...);
require(cToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?");
Web3 1.0
const cToken = CErc20.at(0x3FDA...);
await cToken.methods.repayBorrowBehalf(0xBorrower, 10000).send({from: 0xPayer});

Liquidate Borrow

A user who has negative account liquidity is subject to liquidation by other users of the protocol to return his/her account liquidity back to positive (i.e. above the collateral requirement). When a liquidation occurs, a liquidator may repay some or all of an outstanding borrow on behalf of a borrower and in return receive a discounted amount of collateral held by the borrower; this discount is defined as the liquidation incentive.

A liquidator may close up to a certain fixed percentage (i.e. close factor) of any individual outstanding borrow of the underwater account. Unlike in v1, liquidators must interact with each cToken contract in which they wish to repay a borrow and seize another asset as collateral. When collateral is seized, the liquidator is transferred cTokens, which they may redeem the same as if they had supplied the asset themselves. Users must approve each cToken contract before calling liquidate (i.e. on the borrowed asset which they are repaying), as they are transferring funds into the contract.

CErc20
function liquidateBorrow(address borrower, uint amount, address collateral) returns (uint)
  • msg.sender - The account which shall liquidate the borrower by repaying their debt and seizing their collateral.
  • borrower - The account with negative account liquidity that shall be liquidated.
  • repayAmount - The amount of the borrowed asset to be repaid and converted into collateral, specified in units of the underlying borrowed asset.
  • cTokenCollateral - The address of the cToken currently held as collateral by a borrower, that the liquidator shall seize.
  • RETURN - 0 on success, otherwise an Error codes

Before supplying an asset, users must first approve the cToken to access their token balance.

CEther
function liquidateBorrow(address borrower, address cTokenCollateral) payable
  • msg.value - The amount of ether to be repaid and converted into collateral, in wei.
  • msg.sender - The account which shall liquidate the borrower by repaying their debt and seizing their collateral.
  • borrower - The account with negative account liquidity that shall be liquidated.
  • cTokenCollateral - The address of the cToken currently held as collateral by a borrower, that the liquidator shall seize.
  • RETURN - No return, reverts on error.
Solidity
CEther cToken = CEther(0x3FDB...);
CErc20 cTokenCollateral = CErc20(0x3FDA...);
require(cToken.liquidateBorrow.value(100)(0xBorrower, cTokenCollateral) == 0, "borrower underwater??");
Web3 1.0
const cToken = CErc20.at(0x3FDA...);
const cTokenCollateral = CEther.at(0x3FDB...);
await cToken.methods.liquidateBorrow(0xBorrower, 33, cTokenCollateral).send({from: 0xLiquidator});

Key Events

EventDescription
Mint(address minter, uint mintTokens, uint mintAmount)Emitted upon a successful Mint.
Redeem(address redeemer, uint redeemTokens, uint redeemAmount)Emitted upon a successful Redeem.
Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows)Emitted upon a successful Borrow.
RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows)Emitted upon a successful Repay Borrow.
LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens)Emitted upon a successful Liquidate Borrow.

Error Codes

Error CodeError NameFurther Details
0NO_ERRORNot a failure.
1UNAUTHORIZEDThe sender is not authorized to perform this action.
2BAD_INPUTAn invalid argument was supplied by the caller.
3COMPTROLLER_REJECTIONThe action would violate the comptroller policy.
4COMPTROLLER_CALCULATION_ERRORAn internal calculation has failed in the comptroller.
5INTEREST_RATE_MODEL_ERRORThe interest rate model returned an invalid value.
6INVALID_ACCOUNT_PAIRThe specified combination of accounts is invalid.
7INVALID_CLOSE_AMOUNT_REQUESTEDThe amount to liquidate is invalid.
8INVALID_COLLATERAL_FACTORThe collateral factor is invalid.
9MATH_ERRORA math calculation error occurred.
10MARKET_NOT_FRESHInterest has not been properly accrued.
11MARKET_NOT_LISTEDThe market is not currently listed by its comptroller.
12TOKEN_INSUFFICIENT_ALLOWANCEERC-20 contract must *allow* Money Market contract to call `transferFrom`. The current allowance is either 0 or less than the requested supply, repayBorrow or liquidate amount.
13TOKEN_INSUFFICIENT_BALANCECaller does not have sufficient balance in the ERC-20 contract to complete the desired action.
14TOKEN_INSUFFICIENT_CASHThe market does not have a sufficient cash balance to complete the transaction. You may attempt this transaction again later.
15TOKEN_TRANSFER_IN_FAILEDFailure in ERC-20 when transfering token into the market.
16TOKEN_TRANSFER_OUT_FAILEDFailure in ERC-20 when transfering token out of the market.

Failure Info

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

cToken Helpers

In addition to the core market functions, the cToken contracts implement a number of helper functions to aid developers in building on top of the protocol.

Exchange Rate

Each cToken is convertible into an ever increasing quantity of the underlying asset, as interest accrues in the market. The exchange rate between a cToken and the underlying asset is equal to:

exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply()
CErc20 / CEther
function exchangeRateCurrent() returns (uint)
  • RETURN - The current exchange rate as an unsigned integer, scaled by 1e18.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint exchangeRateMantissa = cToken.exchangeRateCurrent();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const exchangeRate = (await cToken.methods.exchangeRateCurrent().call()) / 1e18;

Tip: note the use of call vs. send to invoke the function from off-chain without incurring gas costs.

Get Cash

Cash is the amount of underlying balance owned by this cToken contract. One may query the total amount of cash currently available to this market.

CErc20 / CEther
function getCash() returns (uint)
  • RETURN - The quantity of underlying asset owned by the contract.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint cash = cToken.getCash();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const cash = (await cToken.methods.getCash().call());

Total Borrow

Total Borrows is the amount of underlying currently loaned out by the market, and the amount upon which interest is accumulated to suppliers of the market.

CErc20 / CEther
function totalBorrowsCurrent() returns (uint)
  • RETURN - The total amount of borrowed underlying, with interest.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint borrows = cToken.totalBorrowsCurrent();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const borrows = (await cToken.methods.totalBorrowsCurrent().call());

Borrow Balance

A user who borrows assets from the protocol is subject to accumulated interest based on the current borrow rate. Interest is accumulated every block and integrations may use this function to obtain the current value of a user's borrow balance with interest.

CErc20 / CEther
function borrowBalanceCurrent(address account) returns (uint)
  • account - The account which borrowed the assets.
  • RETURN - The user's current borrow balance (with interest) in units of the underlying asset.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint borrows = cToken.borrowBalanceCurrent(msg.caller);
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const borrows = await cToken.methods.borrowBalanceCurrent(account).call();

Borrow Rate

At any point in time one may query the contract to get the current borrow rate per block.

CErc20 / CEther
function borrowRatePerBlock() returns (uint)
  • RETURN - The current borrow rate as an unsigned integer, scaled by 1e18.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint borrowRateMantissa = cToken.borrowRatePerBlock();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const borrowRate = (await cToken.methods.borrowRatePerBlock().call()) / 1e18;

Total Supply

Total Supply is the number of tokens currently in circulation in this cToken market. It is part of the EIP-20 interface of the cToken contract.

CErc20 / CEther
function totalSupply() returns (uint)
  • RETURN - The total number of tokens in circulation for the market.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint tokens = cToken.totalSupply();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const tokens = (await cToken.methods.totalSupply().call());

Supply Balance

A user who supplies assets to the protocol receives tokens which accumulate interest based on the current supply rate. At any given time, the value of a token with interest may be queried via the exchange rate. The number of tokens owned by a particular user may also be queried, which is part of the EIP-20 interface of the cToken contract.

CErc20 / CEther
function balanceOf(address account) returns (uint)
  • account - The account to get the token balance of.
  • RETURN - The number of tokens currently owned by the account.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint tokens = cToken.balanceOf(msg.caller);
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const tokens = await cToken.methods.balanceOf(account).call();

Supply Balance Underlying

CTokens also have a convenience method for determining the supply balance in terms of the amount of underlying (i.e. supply balance multiplied by the exchange rate).

CErc20 / CEther
function balanceOfUnderlying(address account) returns (uint)
  • account - The account to get the underlying balance of.
  • RETURN - The amount of underlying currently owned by the account.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint tokens = cToken.balanceOfUnderlying(msg.caller);
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const tokens = await cToken.methods.balanceOfUnderlying(account).call();

Supply Rate

At any point in time one may query the contract to get the current supply rate per block. The supply rate is derived from the borrow rate, reserve factor and the amount of total borrows.

CErc20 / CEther
function supplyRatePerBlock() returns (uint)
  • RETURN - The current supply rate as an unsigned integer, scaled by 1e18.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint supplyRateMantissa = cToken.supplyRatePerBlock();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const supplyRate = (await cToken.methods.supplyRatePerBlock().call()) / 1e18;

Total Reserves

Reserves are the equity accrued to the protocol itself, in order to fund its operation. Reserves also form part of the cash which may be loaned out to borrowers in the market. A small portion of borrower interest accrues into the protocol, determined by the reserve factor.

CErc20 / CEther
function totalReserves() returns (uint)
  • RETURN - The total amount of reserves held by the protocol.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint reserves = cToken.totalReserves();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const reserves = (await cToken.methods.totalReserves().call());

Reserve Factor

The reserve factor defines the small slice of interest that is accrued into reserves.

CErc20 / CEther
function reserveFactorMantissa() returns (uint)
  • RETURN - The current reserve factor as an unsigned integer, scaled by 1e18.
Solidity
CErc20 cToken = CToken(0x3FDA...);
uint reserveFactorMantissa = cToken.reserveFactorMantissa();
Web3 1.0
const cToken = CEther.at(0x3FDB...);
const reserveFactor = (await cToken.methods.reserveFactorMantissa().call()) / 1e18;

Comptroller

The comptroller contract manages the risk associated with the Compound Protocol v2. It is responsible for determining when account's are underwater and can be liquidated. It determines how much collateral can be seized in exchange for liquidating an underwater account. It also provides a defense mechanism to protect the protocol against unforeseen future attacks on the market.

In order to borrow from a market, users are required to supply collateral in some other market(s). Collateral protects the borrowed market, by incentivizing the borrower and/or a liquidator to repay debt. In v1, all markets had the same collateral factor. In addition, any market an account supplied to automatically became collateral for any borrows opened by that account.

In v2, we open the door for each market to determine what is sufficient collateral for a borrow of its asset. We also require that users explicitly enter the markets which they wish to either use as collateral or borrow from. This cuts down on the cost of supporting a large number of markets, while giving users the choice to not use all of their assets as collateral. The cost is a small bit of management overhead for users wishing to borrow, since they must now enter and exit markets.

Enter Markets

Enter into a list of markets - it is not an error to enter the same market more than once. In order to supply collateral or borrow in a market, it must be entered first.

Comptroller
function enterMarkets(address[] calldata cTokens) returns (uint[] memory)
  • msg.sender - The account which shall enter the given markets.
  • cTokens - The addresses of the cToken markets to enter.
  • RETURN - For each market, returns an error code indicating whether or not it was entered. Each is 0 on success, otherwise an Error codes.
Solidity
Comptroller troll = Comptroller(0xABCD...);
CToken[] memory cTokens = new CToken[](2);
cTokens[0] = CErc20(0x3FDA...);
cTokens[1] = CEther(0x3FDB...);
uint[] memory errors = troll.enterMarkets(cTokens);
Web3 1.0
const troll = Comptroller.at(0xABCD...);
const cTokens = [CErc20.at(0x3FDA...), CEther.at(0x3FDB...)];
const errors = await troll.methods.enterMarkets(cTokens).send({from: ...});

Exit Market

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

Comptroller
function exitMarket(address cToken) returns (uint)
  • msg.sender - The account which shall exit the given market.
  • cTokens - The addresses of the cToken market to exit.
  • RETURN - 0 on success, otherwise an Error codes.
Solidity
Comptroller troll = Comptroller(0xABCD...);
uint error = troll.exitMarket(CToken(0x3FDA...));
Web3 1.0
const troll = Comptroller.at(0xABCD...);
const errors = await troll.methods.exitMarket(CEther.at(0x3FDB...)).send({from: ...});

Get Assets In

Get the list of markets an account is currently entered into. In order to supply collateral or borrow in a market, it must be entered first. Entered markets count towards account liquidity calculations.

Comptroller
function getAssetsIn(address account) view returns (address[] memory)
  • account - The account whose list of entered markets shall be queried.
  • RETURN - The address of each market which is currently entered into.
Solidity
"Comptroller troll = Comptroller(0xABCD...);
address[] memory markets = troll.getAssetsIn(0xMyAccount);
Web3 1.0
const troll = Comptroller.at(0xABCD...);
const markets = await troll.methods.getAssetsIn(cTokens).call();

Get Assets In

Within the Compound Protocol, account liquidity is defined as the total estimated ether value of an account's collateral (supply balances multiplied by the protocol collateral factor, minus the total value of that account's borrow balances. These values are calculated using only the markets which the account has entered into.

Users who do not have positive account liquidity do not have the ability to withdraw or borrow any assets until they bring their account liquidity back positive by supplying more assets or paying back outstanding borrows.

Sometimes account liquidity refers to a single signed value, rather than two unsigned values - however the Compound Protocol only deals with unsigned integers. A negative value for account liquidity also means the user is subject to liquidation to bring their account liquidity back to zero.

function getAccountLiquidity(address account) view returns (uint, uint, uint)
  • account - The account whose liquidity shall be calculated.
  • RETURN - Tuple of values (error, liquidity, shortfall). The error shall be 0 on success, otherwise an error code. A non-zero liquidity value indicates the account has available account liquidity. A non-zero shortfall value indicates the account is currently below his/her collateral requirement and is subject to liquidation. At most one of liquidity or shortfall shall be non-zero.
Solidity
Comptroller troll = Comptroller(0xABCD...);
(uint error, uint liquidity, uint shortfall) = troll.getAccountLiquidity(msg.caller);
require(error == 0, "join the Discord");
require(shortfall == 0, "account underwater");
require(liquidity > 0, "account has excess collateral");
Web3 1.0
const troll = Comptroller.at(0xABCD...);
const result = await troll.methods.getAccountLiquidity(0xBorrower).call();
const {0: error, 1: liquidity, 2: shortfall} = result;

Key Events

EventDescription
MarketEntered(CToken cToken, address account)Emitted upon a successful Enter Market.
MarketExited(CToken cToken, address account)Emitted upon a successful Exit Market.

Error Codes

Error CodeError NameFurther Details
0NO_ERRORNot a failure.
1UNAUTHORIZEDThe sender is not authorized to perform this action.
2COMPTROLLER_MISMATCHLiquidation cannot be performed in markets with different comptrollers.
3INSUFFICIENT_SHORTFALLThe account does not have sufficient shortfall to perform this action.
4INSUFFICIENT_LIQUIDITYThe account does not have sufficient liquidity to perform this action.
5INVALID_CLOSE_FACTORThe close factor is not valid.
6INVALID_COLLATERAL_FACTORThe collateral factor is not valid.
7INVALID_LIQUIDATION_INCENTIVEThe liquidation incentive is invalid.
8MARKET_NOT_ENTEREDThe market has not been entered by the account.
9MARKET_NOT_LISTEDThe market is not currently listed by the comptroller.
10MARKET_ALREADY_LISTEDAn admin tried to list the same market more than once.
11MATH_ERRORA math calculation error occurred.
12NONZERO_BORROW_BALANCEThe action cannot be performed since the account carries a borrow balance.
13PRICE_ERRORThe comptroller could not obtain a required price of an asset.
14REJECTIONThe comptroller rejects the action requested by the market.
15SNAPSHOT_ERRORThe comptroller could not get the account borrows and exchange rate from the market.
16TOO_MANY_ASSETSAttempted to enter more markets than are currently supported.
17TOO_MUCH_REPAYAttempted to repay more than is allowed by the protocol.

Failure Info

Failure CodeFailure Name
0ACCEPT_ADMIN_PENDING_ADMIN_CHECK
1ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK
2EXIT_MARKET_BALANCE_OWED
3EXIT_MARKET_REJECTION
4SET_CLOSE_FACTOR_OWNER_CHECK
5SET_CLOSE_FACTOR_VALIDATION
6SET_COLLATERAL_FACTOR_OWNER_CHECK
7SET_COLLATERAL_FACTOR_NO_EXISTS
8SET_COLLATERAL_FACTOR_VALIDATION
9SET_COLLATERAL_FACTOR_WITHOUT_PRICE
10SET_IMPLEMENTATION_OWNER_CHECK
11SET_LIQUIDATION_INCENTIVE_OWNER_CHECK
12SET_LIQUIDATION_INCENTIVE_VALIDATION
13SET_MAX_ASSETS_OWNER_CHECK
14SET_PENDING_ADMIN_OWNER_CHECK
15SET_PENDING_IMPLEMENTATION_OWNER_CHECK
16SET_PRICE_ORACLE_OWNER_CHECK
17SUPPORT_MARKET_EXISTS
18SUPPORT_MARKET_OWNER_CHECK

Appendix

Supplementary discussion of some considerations for using the protocol. If you have other questions which are not answered here, please feel free to reach out for support.

Collateral

In order to borrow from the protocol, accounts must provide enough collateral. One of the greatest motivating factors for Compound v2: Presidio was the ability to set different collateral requirements, depending on the asset being borrowed. With Presidio, the protocol no longer has a global collateral requirement and instead opens it up to individual asset communities to determine what is sufficient collateral in order to borrow their asset.

More details about how this works now and how it will evolve will be coming in the next few weeks as we prepare for mainnet launch.

Exponential Math

The Compound smart contracts use a system of exponential math in order to represent fractional quantities with sufficient precision. Throughout the documentation and code we make reference to mantissas, which are unsigned integers scaled up by a factor of 1e18 from their nominal value. By using mantissas within our contracts, we may perform basic mathematical operations like multiplication and division at a higher resolution than working with the unscaled quantities directly as integers. To gain a better understanding of how this works, see Exponential.sol.

Gas Costs

The gas usage of the protocol functions may fluctuate by market and user. External calls, such as to underlying ERC-20 tokens, may use an arbitrary amount of gas. Any calculations that involve checking account liquidity, have gas costs that increase with the number of entered markets. Thus, while it can be difficult to provide any guarantees about costs, we provide the table below for guidance:

FunctionTypical Gas Cost
Mint< 90K
Redeem, Transfer< 250K if borrowing, otherwise < 90K
Borrow< 300K
Repay Borrow< 90K
Liquidate Borrow< 400K

Glossary

TermDescription
Collateral FactorThe amount of an asset that may be borrowed for each unit of collateral provided. The collateral factor is defined per market.
Close FactorThe portion of a borrow in a single market that may be closed by a liquidator during a single liquidation. For example, if Joe borrows 100 ZRX and the close factor is 0.3, then a liquidator may close 30 ZRX. The close factor is globally defined across all markets.
Liquidation IncentiveThe 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 borrowers collateral for every unit they close. The liquidation incentive is globally defined across all markets.

Support

For support requests, please reach out to us in the #development channel in our Discord. We're happy to help out and grow the Compound community. Your questions help us improve, so please don't hesitate to ask if you can't find what you are looking for here.