Getting Started

The Compound protocol is currently deployed on Mainnet and the Rinkeby testnet.

ContractABIAddress
MoneyMarketJSON
0x3fda67f7583380e67ef93072294a7fac882fd7e7
PriceOracleJSON
0x02557a5e05defeffd4cae6d83ea3d173b272c904
InterestRateModelJSON
0xd25c029a607ee888bdbdbe054515e25ec6f3fff9

Money Market

The Money Market is the primary smart contract used to interact with the Compound Protocol. The primary functions of the protocol are as follows:

Supply

functionsupply(address asset,uint amount)publicreturns(uint)
  • asset- The address of the ERC-20 token to be supplied.
  • amount- The amount of the asset to be supplied specified in the smallest unit available for the asset. For example, amount should be specified in wei for a user for wrapped ether.
  • RETURN- 0 on success, otherwise an error code.

Before supplying an asset, users must first approvethe Money Market to access their token balance.

The supply function transfers an asset into the Money Market, which begins accumulating interest based on the current supply rate for the asset.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);ERC20token =ERC20(0xToken);token.approve(address(MoneyMarket),100);uint errorCode =moneyMarket.supply(token,100);assert(errorCode ==0);
Web3 1.0
constaccount =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.supply(token.address,50).send({from:account }).on('transactionHash',(trxHash)=>{console.log(`View your supply trx at: https://etherscan.io/tx/${trxHash}`);});

Withdraw

functionwithdraw(address asset,uint requestedAmount)publicreturns(uint)
  • asset- The address of the ERC-20 token to be withdrawn.
  • amount- The amount of the asset to be withdrawn specified in the smallest unit available for the asset. For example, amount should be specified in wei for a user withdrawing wrapped ether. A value of -1can be used to withdraw the maximum amount allowed.
  • RETURN- 0 on success, otherwise an error code.

The withdraw function transfers an asset from the Money Market to the user, reducing the user's supply balance.

The amount withdrawn must be less than the user's account liquidityand the market's available liquidity. Specifying an amount of -1withdraws the maximum quantity of tokens available.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);// Ensure you have a balance which was supplied, see `supply` aboveuint errorCode =moneyMarket.withdraw(token,100);assert(errorCode ==0);
Web3 1.0
constaccount =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.withdraw(token.address,50).send({from:account }).on('transactionHash',(trxHash)=>{console.log(`View your withdraw trx at: https://etherscan.io/tx/${trxHash}`);});

Borrow

functionborrow(address asset,uint amount)publicreturns(uint)
  • asset- The address of the ERC-20 token to be borrowed.
  • amount- The amount of the asset to be borrowed specified in the smallest unit available for the asset. For example, amount should be specified in wei for a user borrowing wrapped ether.
  • RETURN- 0 on success, otherwise an error code.

The borrow function transfers an asset from the Money Market to the user, which begins accumulating interest based on the current borrow rate for the asset.

The amount borrowed must be less than the user's borrow capacityand the market's available liquidity.

Users must maintain a collateral requirementto avoid liquidation.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);// Ensure you have a balance which was supplied, see `supply` aboveuint errorCode =moneyMarket.borrow(tokenB,100);assert(errorCode ==0);assert(tokenB.balance(msg.caller)==100);
Web3 1.0
constaccount =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.borrow(tokenB.address,50).send({from:account }).on('transactionHash',(trxHash)=>{console.log(`View your borrow trx at: https://etherscan.io/tx/${trxHash}`);});

Repay Borrow

functionrepayBorrow(address asset,uint amount)publicreturns(uint)
  • Asset- The address of the ERC-20 token to be repaid.
  • Amount- The amount of the asset to be repaid specified in the smallest unit available for the asset. For example, amount should be specified in Wei for a user desiring to repay Wrapped Ether. A value of -1 can be used to repay the maximum amount allowed.
  • RETURN- 0 on Success, otherwise a failure.

Before repaying a borrowed asset, users must first approvethe Money Market to access their token balance.

The repay function transfers an asset into the Money Market, reducing the user's borrow balance. Users may specify an amount of -1in order to repay the maximum tokens available.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);ERC20token =ERC20(0xToken);token.approve(address(MoneyMarket),100);uint errorCode =moneyMarket.repayBorrow(tokenB,100);assert(errorCode ==0);assert(tokenB.balance(msg.caller)==0);assert(moneyMarket.borrowBalance(msg.caller,tokenB)==0);
Web3 1.0
constaccount =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.repayBorrow(tokenB.address,50).send({from:account }).on('transactionHash',(trxHash)=>{console.log(`View your repay borrow trx at: https://etherscan.io/tx/${trxHash}`);});

Get Account Liquidity

functiongetAccountLiquidity(address account)view publicreturns(int)
  • account- The address of the user's Compound Protocol account.
  • RETURN- Signed integer where a positive value indicates the user's available account liquidity. A negative value, however, indicates the user is below his/her collateral requirementand this shortfall may be liquidated to bring the user back to a positive account liquidity.

Within the Compound Protocol, account liquidity is defined as the total value of a user's supply balances subtracted by the total value of that user's borrow balances multiplied by the protocol collateral ratio. 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. A negative value for account liquidity also means the user is subject to liquidation to bring their account liquidity back to zero.

The return value of this function is a signed integer denominated in eth-wei (i.e. a real scaled by 1e18 and truncated). For example, a user who has only supplied 0.1 eth into the protocol and has no outstanding borrows would have an account liquidity of 0.1e18 = 1e17 = 100000000000000000.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);// user does supplies and borrowsint accountLiquidity =moneyMarket.getAccountLiquidity(msg.caller);// assert user's account is in good standingassert(accountLiquidity >=0);
Web3 1.0
constaccount =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.getAccountLiquidity(account).call().then((liquidity)=>{console.log(`Account ${account}has ${liquidity}liquidity. This account is ${liquidity >0?'safe':'at risk'}.`);})

Get Supply Balance

functiongetSupplyBalance(address account,address asset)view publicreturns(uint)
  • account- The address of the user's Compound Protocol account where he/she originally supplied assets from
  • asset- The address of the ERC-20 token originally supplied by the user for which to obtain the current balance
  • RETURN- The user's current supply balance (with interest) for the specified asset given in the smallest unit available for the asset

A user who supplies assets into the protocol accumulates interest based on the continuous supply rate. Interest is accumulated every block and integrations may use `getSupplyBalance` to check the user's supply balance with interest.

Note: a user may not be able to withdraw his or her entire supply balance if that user has an outstanding borrow and therefore must maintain a collateral requirement.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);// user does supplies and borrowsuint currentSupplyBalance =moneyMarket.getSupplyBalance(msg.caller);// assert user's account has a non-zero supplyassert(currentSupplyBalance >=0);
Web3 1.0
constaccount =...;constasset =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.getSupplyBalance(account,asset).call().then((supplyBalance)=>{console.log(`Account ${account}has ${supplyBalance}supply balance of ${asset}`);});

Get Borrow Balance

functiongetBorrowBalance(address account,address asset)view publicreturns(uint)
  • account- The address of the user's Compound Protocol account where he/she originally borrowed assets from
  • asset- The address of the ERC-20 token originally borrowed by the user for which to obtain the current balance for
  • RETURN- The user's current borrow balance (with interest) for the specified asset given in the smallest unit available for the asset

A user who borrows assets from the protocol is subject to accumulated interest based on the current continuous borrow rate. Interest is accumulated every block and integrations may use `getBorrowBalance` to obtain the current value of a user's borrow balance with interest, which will be updated every block.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);// user does supplies and borrowsuint currentBorrowBalance =moneyMarket.getBorrowBalance(msg.caller);// assert user's account has a non-zero borrowassert(currentBorrowBalance >=0);
Web3 1.0
constaccount =...;constasset =...;constmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.getBorrowBalance(account,asset).call().then((borrowBalance)=>{console.log(`Account ${account}has ${borrowBalance}borrow balance of ${asset}`);});

Liquidate

functionliquidateBorrow(address targetAccount,address assetBorrow,address assetCollateral,uint requestedAmountClose)publicreturns(uint)
  • targetAccount- The address of the liquidatee's Compound Protocol account that currently has negative account liquidity
  • assetBorrow- The address of an ERC-20 token originally borrowed by the liquidatee which currently has an outstanding balance
  • assetCollateral- The address of an ERC-20 token currently held as collateral by a liquidatee that the liquidator wishes to seize
  • requestedAmountClose- The amount of the borrowed asset to be repaid specified in the smallest unit available for the asset. For example, amount should be specified in wei for a liquidator desiring to liquidate a wrapped ether borrow. A value of -1can be used to liquidate the maximum amount allowed of the liquidatee's outstanding borrow balance given their current collateral balance and negative account liquidityremaining.
  • RETURN- 0 on success, otherwise an error code.

A user who has negative account liquidityis subject to liquidationby other users of the protocol to return his/her account liquidity back to 0 (i.e., exactly at the collateral requirement), reducing the risk of that account. When a liquidation occurs, a liquidator may repay some or all of an outstanding borrow on behalf of a liquidatee and in return receive a discounted amount of collateral held by the liquidatee; this discount is defined as the liquidation discount, and at launch will be 5%.

As with many other functions, you can specify -1to close as much of the borrow as possible. This is provided since it's impossible to know exactlyhow much can be liquidated given the prices can move and interest grows in a few blocks before a transaction is accepted by Ethereum. Note, however, that you need a sufficient balance to close the entire position if you specify max. Otherwise: you should simply close the most that you can provide.

Solidity
MoneyMarket moneyMarket =MoneyMarket(0x3FDA...);ERC20assetBorrow =...;// asset target borrowed (in default)ERC20assetCollateral =...;// asset target supplied as collateraladdress targetAccount =...;// user to liquidateuint requestAmountClose =....;// amount (in wei) of asset borrow to close// track positions prior to liqudationuint myBorrowWalletBalance =assetBorrow.balanceOf(msg.sender);uint myCollateralSupplyBalance =moneyMarket.supplyBalance(msg.sender);uint targetCollateralSupplyBalance =moneyMarket.supplyBalance(targetAccount);uint errorCode =moneyMarket.liquidateBorrow(targetAccount,address(assetBorrow),address(assetCollateral),requestAmountClose);assert(errorCode ==0);// Liquidators wallet balance should decrease by amount of borrow closedassert(assetBorrow.balanceOf(msg.sender)=myBorrowWalletBalance -requestAmountClose);// Delta in my (liquidators) supply balance in Compound as signed integerint mySupplyChange =int(moneyMarket.supplyBalance(msg.sender))-myCollateralSupplyBalance;assert(mySupplyChange >0);int targetSupplyChange =int(moneyMarket.supplyBalance(targetAccount))-targetCollateralSupplyBalance;// Verify liquidator received the target's collateral as supply balanceassert(mySupplyChange =-1*targetSupplyChange);
Web3 1.0
constmyAccount =...;// account of liquidatorconsttargetAccount =...;// account in defaultconstassetBorrow =...;// asset target borrowed (in default)constassetCollateral =...;// asset target supplied as collateralconstrequestAmountClose =....;// amount (in wei) of asset borrow to closeconstmoneyMarket MoneyMarket.at(0x3FDA...);moneyMarket.methods.liquidiate(targetAccount,assetBorrow,assetCollateral,requestAmountClose).send({from:myAccount }).on('transactionHash',(trxHash)=>{console.log(`View your liquidation trx at: https://etherscan.io/tx/${trxHash}`);});

Defintions

ConstantDescription
collateral ratioThe amount of supply value required to be held for each unit of borrow value to initiate an action (borrow, withdraw), must be strictly greater than 1, e.g. 2.0.
liquidation discountA multiplier representing the percent value that a user calling liquidate receives, e.g. 0.05 for 5%
borrow feeThe percent fee that a user originating a borrow has added to their balance, e.g. 0.0005.

ValueDescription
supply currentThe user’s supply of a given asset, including accrued interest as of the current block
borrow currentThe user’s borrow of a given asset, including accrued interest as of the current block
account liquidityThe value of a user’s account, denominated in Ether, above the user’s collateral requirement
collateral requirementSimilar to account liquidity above, but as a ratio of total supply value divided by total borrow value. Thus an account with collateralRequirement greater than collateralRatio is in good standing.
withdraw capacityThe quantity of tokens, denominated in the specified asset, that the user is able to withdraw from Compound, or accountLiquidity divided by the oracle price of the asset.
borrow capacityThe quantity of tokens, denominated in the specified asset, that the user is able to borrow from Compound
shortfallThe amount of value, denominated in Ether, that a target user can have seized
amount closeThe amount of asset that a target user can have closed
amount seizeThe amount of collateral, denominated in its own asset, to seize from a target user
total supplyThe sum of supply of an asset in its respective money market, excluding accrued interest
total borrowThe sum of borrow of an asset in its respective money market, excluding accrued interest
ItemDescription
-12256- 1, or the maximum value that can be stored in a 256-bit integer (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF). The binary representation of the signed integer -1, so in Solidity, we often cast `uint(-1)` to obtain this value. In the Compound Protocol, the value of an operation may depend on the exact block it's mined in (e.g. if you want to withdraw, you accumlate interest each block, so you do not know how much exactlyhow much balance you will have when your transaction is mined). For this reason, we allow users to specify this value in some operations to mean "as much as possible." Thus, withdraw(asset, uint(-1))will withdraw all available funds at the time the transaction is mined.

Error Codes

ErrorDescription of ErrorFurther Details
0NO_ERRORNot a failure.
1OPAQUE_ERRORAn error has occured in a third-party contract (see Detail field for more information)
2UNAUTHORIZEDYou are not authorized for this action.
3INTEGER_OVERFLOWTried to add two numbers that summed greater than 10^32. (See Info for details)
4INTEGER_UNDERFLOWTried to subtract a larger number from a smaller number (See Info for details)
5DIVISION_BY_ZERODivision by zero is undefined.
6BAD_INPUTUnused
7TOKEN_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.
8TOKEN_INSUFFICIENT_BALANCEYou do not have sufficient balance in ERC-20 contract to complete the desired action.
9TOKEN_TRANSFER_FAILEDFailure in ERC-20 when transfering token into Compound Money Market.
10MARKET_NOT_SUPPORTEDThis market is not supported by Compound.
11SUPPLY_RATE_CALCULATION_FAILEDInternal error in Compound.
12BORROW_RATE_CALCULATION_FAILEDInternal error in Compound.
13TOKEN_INSUFFICIENT_CASHThe Money Market does not, itself, have a sufficient cash balance to complete the transaction. You may attempt this transaction again later.
14TOKEN_TRANSFER_OUT_FAILEDAn error occured in the ERC-20 contract's `transfer` function.
15INSUFFICIENT_LIQUIDITYYou would violate your collateral ratio requirements by executing this withdraw, borrow or liquidate action.
16INSUFFICIENT_BALANCEYou do not have a sufficient balance to complete with withdraw.
17INVALID_COLLATERAL_RATIOInternal error in Compound.
18MISSING_ASSET_PRICEThe Price Oracle has encountered an error or is paused
19EQUITY_INSUFFICIENT_BALANCEInternal error in Compound.
20INVALID_CLOSE_AMOUNT_REQUESTEDYou are attempting to liquidate a borrow beyond just bringing it back to even.
21ASSET_NOT_PRICEDInternal error in Compound.
22INVALID_LIQUIDATION_DISCOUNTInternal error in Compound.
23INVALID_COMBINED_RISK_PARAMETERSInternal error in Compound.
24ZERO_ORACLE_ADDRESSInternal error in Compound.
25CONTRACT_PAUSEDInternal error in Compound.

Compound API

The Compound API input and output formats are specified by Protocol Buffers, known colloquially as protobufs. Unlike typical protobufs endpoints, the Compound endpoints support JSON for input and output in addition to the protobufs binary format. To use JSON in both the input and the output, specify the headers "Content-Type: application/json"and "Accept: application/json"in the request.

Please request an API key from Compound in the #development channel in our Discord. It should be included in the HTTP header compound-api-key. We require separate api keys for staging and production.

Risk API

(View Protobuf)

Compound provides a Risk API that lists the ETH-equivalent values of supplies and borrows for accounts using the protocol. The underlying data is read from the blockchain and cached on Compound servers. It is updated very frequently but, to support quickly listing multiple accounts at once, is not read in real-time from the blockchain. The freshness of the data for each account is indicated by the block_updatedelement given for that account.

get_top_account_values

get_top_account_valueslists the top 100 accounts by ETH-equivalent borrow value, sorted in ascending order of collateral ratio. The prices used to compute the supply and borrow values are from the Compound Price Oracle as of the block_updatedelement for each account.

Request (curl)
curl--header "Accept: application/json"\  --header "compound-api-key: YOUR_API_KEY"\"https://api.compound.finance/api/risk/v1/get_top_account_values"
Response (JSON)
{"error":null,"account_values":[{"total_supply_value_in_eth":{"value":"81553945090485352055.24170417"},"total_borrow_value_in_eth":{"value":"16693079517105956316.92135530"},"block_updated":2934324,"address":"0x6646f6636d15381ad847dacb8e69cd765b17d899"},{"total_supply_value_in_eth":{"value":"8936991420766432438.660994608"},"total_borrow_value_in_eth":{"value":"4365064464045375106.433805073"},"block_updated":2934324,"address":"0x3605780992537dcaae52a8da39238d6d883b7009"}]}

get_account_values

get_account_valuesreturns a paginated list of accounts, sorted in ascending order of collateral ratio. The prices used to compute the supply and borrow values are from the Compound Price Oracle as of the block_updated element for each account. The request object allows the client to specify the page size, the page number (starting from 1) and, optionally:

  • a minimum borrow value (defaults to 0 if not provided by caller)
  • a maximum collateral ratio (defaults to 2 if not provided by caller) Accounts with a borrow value <= the specified minimum will not be included in the results. Accounts with a collateral ratio > the specified max will not be included in the results.

Please note that min_borrow_value_in_ethshould be given in wei units.

Request (curl)
curl--header "Content-Type: application/json"--header "Accept: application/json"\--header "compound-api-key: YOUR_API_KEY"--request POST \--data '{"page_size":100,"page_number":1, "min_borrow_value_in_eth":{"value":"0"}, "max_collateral_ratio":{"value":"2"}}'\"https://api.compound.finance/api/risk/v1/get_account_values"
Response (JSON)
{"request":{"page_size":100,"page_number":1,"min_borrow_value_in_eth":{"value":"0"},"max_collateral_ratio":{"value":"2"}},"pagination_summary":{"total_pages":1,"total_entries":5,"page_size":100,"page_number":1},"error":null,"account_values":[{"total_supply_value_in_eth":{"value":"468372752391553739.9868634122"},"total_borrow_value_in_eth":{"value":"248190748151699414.7614623254"},"block_updated":3231505,"address":"0xfd72981e24356f3b2b01e1d0c18cc7fead37f432"},{"total_supply_value_in_eth":{"value":"23704306155318340590.84549900"},"total_borrow_value_in_eth":{"value":"11969103774659244013.22283866"},"block_updated":3231503,"address":"0xb50eb12ecbe6371401f9b56c2aa12fe75c129d85"},{"total_supply_value_in_eth":{"value":"20640026912585.00000000000000"},"total_borrow_value_in_eth":{"value":"10379520700003.00000000000000"},"block_updated":3231505,"address":"0x0e73f1de0f0ef81a315da59a40fa3a7c46cc8806"},{"total_supply_value_in_eth":{"value":"32380495046773.00000000000000"},"total_borrow_value_in_eth":{"value":"16230334067560.00000000000000"},"block_updated":3231505,"address":"0xc88b963239b6918f74c3298bb1dc079b92671e42"},{"total_supply_value_in_eth":{"value":"1001596347901916851.000000000"},"total_borrow_value_in_eth":{"value":"501560339915348717.4224994298"},"block_updated":3231505,"address":"0xd840d02bb3a715027343fc8428b61a7f83dcb6e7"}]}

The request element echoes the inputs. The pagination_summaryelement provides the information needed to make subsequent requests to get more results. The account_valueselement holds the account value results for the current page.

get_account_value

get_account_valuereturns the value for a specified account. Note that it may take a few minutes for balances to be populated for a new account. Until that happens, total_supply_value_in_ethand total_borrow_value_in_ethwill be null.

Request (curl)
curl--header "Content-Type: application/json"--header "Accept: application/json"\--header "compound-api-key: YOUR_API_KEY"--request POST \--data '{"account_address":"0xc88b963239b6918f74c3298bb1dc079b92671e42"}'\"https://api.compound.finance/api/risk/v1/get_account_value"
Response (JSON)
{"error":null,"account_value":{"total_supply_value_in_eth":{"value":"32380577799103.00000000000000"},"total_borrow_value_in_eth":{"value":"16230478797408.00000000000000"},"block_updated":3231602,"address":"0xc88b963239b6918f74c3298bb1dc079b92671e42"}}

Market History API

(View Protobuf)

Compound's Market History API provides graph data of the Compound Money Market interest rates, as well as total supplies and borrows. The caller of the API can choose the given time period and resolution of the data (e.g. 24 buckets over the last 24 hours).

get_market_history_graph

get_market_history_graph(and similarly post_market_history_graph) is the main function of the market history API. You should specify the address of the assetto pull interest rates for, min_block_timestampand max_block_timestampfor a time range, and a num_bucketsspecifying the number of points to return in the graph.

The result will pull the interest rates, total supplies and total borrows for that asset over that period and return the average interest rate for each bucket. For instance, if we specified a window of the last 24-hours and asked for 24 buckets, the API would return the average interest rate, total supply and total borrows, per hour, over the last day.

Request (curl)
curl--header "Accept: application/json"\--header "compound-api-key: YOUR_API_KEY"\"https://api.compound.finance/api/market_history/v1/graph?asset=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&min_block_timestamp=1540858322&max_block_timestamp=1541463122&num_buckets=2"
Response (JSON)
{"total_supply_history":[{"total":{"value":"8981126226710001902616"},"block_timestamp":1540858325,"block_number":6608318},{"total":{"value":"8981049821028419745151"},"block_timestamp":1540873110,"block_number":6609334}],"total_borrows_history":[{"total":{"value":"272244478219433219687"},"block_timestamp":1540858325,"block_number":6608318},{"total":{"value":"272310439587543455907"},"block_timestamp":1540873110,"block_number":6609334}],"supply_rates":[{"rate":0.0017359425269574235,"block_timestamp":1540858325,"block_number":6608318},{"rate":0.0017364723271263496,"block_timestamp":1540873110,"block_number":6609334}],"error":{"message":"","field_errors":{},"error_code":0},"borrow_rates":[{"rate":0.06363898632293184,"block_timestamp":1540858325,"block_number":6608318},{"rate":0.06364240698739985,"block_timestamp":1540873110,"block_number":6609334}],"asset":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}

Support

For support requests, please reach out to us in the #development channel in our Discord. We're happy to help out and build the Compound community.