Compound 与 cToken 合约 交互

Compound 协议所支持的每项资产都通过 cToken 合约进行整合,cToken 合约是提供给协议的余额的 EIP-20 合格表示。

> 请注意,在翻译时遇到一个单词 `Underlying` 相关的词组有 `Underlying Balance`和`Underlying assets`。个人觉得翻译成基础余额、底层余额、底层资产、基础资产等听着不对味,所以我根据理解,将其翻译为标的余额、标的资产。有来喷的吗?点击右侧加号可以留言!cToken 就是对 Token 的封装,这个 Token 就可以视为交易的标的物。 ## 介绍 Compound 协议所支持的每项资产都通过 cToken 合约进行整合,cToken 合约是提供给协议的余额的 [EIP-20](https://eips.ethereum.org/EIPS/eip-20) 合格表示。通过铸造 cToken,用户(1)通过 cToken 的汇率赚取利息,该汇率相对于标的资产的价值增加,以及(2)获得试用 cToken 作为抵押品的能力。 cToken 是与 Compound 协议交互的主要手段;当用户在使用 cToken 合约时,会使用 cToken 合约来进行铸币(mint)、赎回(redeem)、借款(borrow)、偿还借款(repay)、清算借款(liquidate)或者划转 cToken (transfer)。 目前有两种类型的 cToken : CErc20 和 CEther。尽管两者都暴露了 EIP-20 接口,但 CErc20 封装了 ERC-20 标的资产,而 CEther 只是封装了 Ether 本身。因此,根据类型的不同,涉及将资产传输到协议中的核心功能的接口也略有不同,每种类型的接口如下所示。 ## 铸币(Mint) mint 方法将一个资产转移到协议中,协议开始根据该资产的当前[供应率]()开始累积利息。用户收到的 cToken 数量等于标的代币数量除以当前[汇率]()。 **CErc20** ``` 1 function mint(uint mintAmount) returns (uint) ``` - msg.sender : 供应资产并拥有已铸 cToken 的账户。 - mintAmount : 供应的资产金额,单位为标的资产的单位。 - RETURN : 成功时为0,否则是[错误代码]()。 供应资产前,用户必须先 [批准(approve)](https://eips.ethereum.org/EIPS/eip-20#approve), cToken 才能访问其代币余额。 **CEther** ``` 1 function mint() payable ``` - msg.value : 供应的 ETH 数量,单位 wei。 - msg.sender : 供应 ETH 并拥有已铸 cToken 的账户。 - RETURN : 无返回值,错误时还原。 **Solidity** ``` 1 Erc20 underlying = Erc20(0xToken...); // 获取标的资产合约句柄 2 CErc20 cToken = CErc20(0x3FDA...); // 获取相应 cToken 合约的句柄 3 underlying.approve(address(cToken), 100); // 批准划转 4 assert(cToken.mint(100) == 0); // 铸 cToken 币,并断言是否有错误 ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 await cToken.methods.mint().send({from: myAccount, value: 50}); ``` ## 赎回(Redeem) redeem 方法将指定数量的 cToken 转换为标的资产,并将其返还给用户。收到的标的数量等于赎回的 cToken 数量乘以当前[汇率]()。赎回额必须小于用户的[账户流动性](https://compound.finance/docs/comptroller#account-liquidity)和市场可用的流动性。 **CErc20 / CEther** ``` function redeem(uint redeemTokens) returns (uint) ``` - msg.sender : 应将赎回的标的资产转入的账户。 - redeemTokens : 将被赎回的 cToken 数量。 - RETURN : 成功时为0,否则是[错误代码]()。 **Solidity** ``` 1 CEther cToken = CEther(0x3FDB...); 2 require(cToken.redeem(7) == 0, "something went wrong"); ``` ## 赎回标的(Redeem Underlying) redeem underlying 方法将 cToken兑换成指定数量的标的资产,并返回给用户。赎回的 cToken的数量等于收到的标的数量除以当前[汇率]()。赎回额必须小于用户的[账户流动性](https://compound.finance/docs/comptroller#account-liquidity)和市场可用的流动性。 **CErc20 / CEther** ``` 1 function redeemUnderlying(uint redeemAmount) returns (uint) ``` - msg.sender : 应将赎回的标的资产转入的账户。 - redeemAmount : 将被赎回的标的资产数量。 - RETURN : 成功时为0,否则是[错误代码]()。 **Solidity** ``` 1 CEther cToken = CEther(0x3FDB...); 2 require(cToken.redeemUnderlying(50) == 0, "something went wrong"); ``` **Web3 1.0** ``` 1 const cToken = CErc20.at(0x3FDA...); 2 cToken.methods.redeemUnderlying(10).send({from: ...}); ``` ## 借款(Borrow) borrow 方法将协议中的资产转移给用户,并创建一个借款余额,根据该资产的[借款利率]()开始累积利息。借款额必须小于用户的[账户流动性](https://compound.finance/docs/comptroller#account-liquidity)和市场可用的流动性。 要想借入以太,借款人必须是 'payable' (Solidity)。 **CErc20 / CEther** ``` 1 function borrow(uint borrowAmount) returns (uint) ``` - msg.sender : 应将借款资金转入的账户。 - borrowAmount : 标的资产借款数量。 - ETURN : 成功时为0,否则是[错误代码]()。 **Solidity** ``` 1 CErc20 cToken = CErc20(0x3FDA...); 2 require(cToken.borrow(100) == 0, "got collateral?"); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 await cToken.methods.borrow(50).send({from: 0xMyAccount}); ``` ## 偿还借款(Repay Borrow) repay 方法将资产转移到协议中,并减少用户的借款余额。 **CErc20** ``` 1 function repayBorrow(uint repayAmount) returns (uint) ``` - msg.sender : 借入资产的账户,应偿还借款。 - repayAmount : 拟偿还的标的资产借款金额。值为-1(即2256-1)表示偿还全部借款额。 - RETURN : 成功时为0,否则是[错误代码]()。 偿还资产前,用户必须先 [批准(approve)](https://eips.ethereum.org/EIPS/eip-20#approve), cToken 才能访问其代币余额。 **CEther** ``` 1 function repayBorrow() payable ``` - msg.value : 用于偿还的 ETH 数量,单位 wei。 - msg.sender : 借入资产的账户,应偿还借款。 - RETURN : 无返回值,错误时还原。 **Solidity** ``` 1 CEther cToken = CEther(0x3FDB...); 2 require(cToken.repayBorrow.value(100)() == 0, "transfer approved?"); ``` **Web3 1.0** ``` 1 const cToken = CErc20.at(0x3FDA...); 2 cToken.methods.repayBorrow(10000).send({from: ...}); ``` ## 代偿还借款(Repay Borrow Behalf) repay 方法将资产转移到协议中,并减少目标用户的借款余额。 **CErc20** ``` 1 function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint) ``` - msg.sender : 偿还借款的账户。 - borrower : 借入资产要偿还的账户。 - repayAmount : 拟偿还的标的资产借款金额。值为-1(即2256-1)表示偿还全部借款额。 - RETURN : 成功时为0,否则是[错误代码]()。 偿还资产前,用户必须先 [批准(approve)](https://eips.ethereum.org/EIPS/eip-20#approve), cToken 才能访问其代币余额。 **CEther** ``` 1 function repayBorrowBehalf(address borrower) payable ``` - msg.value : 用于偿还的 ETH 数量,单位 wei。 - msg.sender : 偿还借款的账户。 - borrower : 借入资产要偿还的账户。 - RETURN : 无返回值,错误时还原。 **Solidity** ``` 1 CEther cToken = CEther(0x3FDB...); 2 require(cToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?"); ``` **Web3 1.0** ``` 1 const cToken = CErc20.at(0x3FDA...); 2 await cToken.methods.repayBorrowBehalf(0xBorrower, 10000).send({from: 0xPayer}); ``` ## 清算借款(Liquidate Borrow) [账户流动性](https://compound.finance/docs/comptroller#account-liquidity)为负值的用户,由协议的其他用户进行[清算](),使其账户流动性恢复到正值(即高于抵押品要求)。当发生清算时,清算人(liquidator)可以代表借款人偿还部分或全部未偿还的借款,作为回报,可以获得借款人持有的抵押品的折价;这种折价被定义为清算奖励。 清算人可将水下账户的任何一个未偿还借款以一定的固定比例(即结算系数)进行结算。与 V1 中不同的是,清算者必须与每一个 cToken 合约中偿还借款并扣押另一项资产作为抵押品的 cToken 进行交互。当抵押品被扣押时,清算人会被转移 cToken,他们可以赎回这些 cToken,就像他们自己提供资产一样。用户必须在调用清算前批准每个 cToken 合约(即在他们要偿还的借款资产上),因为他们正在将资金转移到合约中。 **CErc20** ``` 1 function liquidateBorrow(address borrower, uint amount, address collateral) returns (uint) ``` - msg.sender : 应通过偿还借款人的债务和扣押抵押品来结算借款人的账户。 - borrower : 应予清算的负[账户流动性](https://compound.finance/docs/comptroller#account-liquidity)账户。 - repayAmount : 借款资产的偿还和转换为抵押品的金额,以标的抵押资产的单位为单位。 - cTokenCollateral : 清算人应扣押借款人目前作为抵押品持有的 cToken 地址。 - RETURN : 成功时为0,否则是[错误代码]()。 偿还资产前,用户必须先 [批准(approve)](https://eips.ethereum.org/EIPS/eip-20#approve), cToken 才能访问其代币余额。 **CEther** ``` 1 function liquidateBorrow(address borrower, address cTokenCollateral) payable ``` - msg.value : 转换为抵押品的 ETH 金额,单位 wei 。 - msg.sender : 应通过偿还借款人的债务和扣押抵押品来结算借款人的账户。 - borrower : 应予清算的负[账户流动性](https://compound.finance/docs/comptroller#account-liquidity)账户。 - cTokenCollateral : 清算人应扣押借款人目前作为抵押品持有的 cToken 地址。 - RETURN : 成功时为0,否则是[错误代码]()。 **Solidity** ``` 1 CEther cToken = CEther(0x3FDB...); 2 CErc20 cTokenCollateral = CErc20(0x3FDA...); 3 require(cToken.liquidateBorrow.value(100)(0xBorrower, cTokenCollateral) == 0, "borrower underwater??"); ``` **Web3 1.0** ``` 1 const cToken = CErc20.at(0x3FDA...); 2 const cTokenCollateral = CEther.at(0x3FDB...); 3 await cToken.methods.liquidateBorrow(0xBorrower, 33, cTokenCollateral).send({from: 0xLiquidator}); ``` ## 主要事件(Key Events) | Event | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | | Mint(address minter, uint mintAmount, uint mintTokens) | [铸币](https://compound.devdapp.cn/kai-fa-zhe-wen-dang/ctoken#zhu-bi-mint)成功后发出 | | Redeem(address redeemer, uint redeemAmount, uint redeemTokens) | [赎回]()成功后发出 | | Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows) | [借款](https://compound.devdapp.cn/kai-fa-zhe-wen-dang/ctoken#jie-kuan-borrow)成功后发出 | | RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows) | [偿还借款]()成功后发出 | | LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens) | [借款清算]()成功后发出 | ## 错误代码(Error Codes) | Code | Name | Description | | ---- | ------------------------------ | ------------------------------------------------------------ | | 0 | NO_ERROR | 不是失败。 | | 1 | UNAUTHORIZED | 发件人无权实施这一操作。 | | 2 | BAD_INPUT | 调用者提供了一个无效参数。 | | 3 | COMPTROLLER_REJECTION | 该操作将违反审计官政策。 | | 4 | COMPTROLLER_CALCULATION_ERROR | 审计内部计算失败 。 | | 5 | INTEREST_RATE_MODEL_ERROR | 利率模型返回了一个无效值。 | | 6 | INVALID_ACCOUNT_PAIR | 指定的账户组合是无效的。 | | 7 | INVALID_CLOSE_AMOUNT_REQUESTED | 清算金额无效。 | | 8 | INVALID_COLLATERAL_FACTOR | 抵押因子无效。 | | 9 | MATH_ERROR | 出现了数学计算错误。 | | 10 | MARKET_NOT_FRESH | 利息没有正确产生。 | | 11 | MARKET_NOT_LISTED | 目前,市场没有由审计员列出。 | | 12 | TOKEN_INSUFFICIENT_ALLOWANCE | ERC-20 合约必须**允许(allow)**货币市场合约调用`transferForm`。当前 allow 额为0或小于请求的供给、偿还借款或清算金额。 | | 13 | TOKEN_INSUFFICIENT_BALANCE | 调用者在 ERC-20 合约中没有足够的余额来完成所需的操作。 | | 14 | TOKEN_INSUFFICIENT_CASH | 市场上没有足够的现金金额来完成交易。您可以稍后再尝试此项交易。 | | 15 | TOKEN_TRANSFER_IN_FAILED | 在 ERC-20 代币转入市场时失败。 | | 16 | TOKEN_TRANSFER_OUT_FAILED | 在 ERC-20 代币转出市场时失败。 | ## 失败信息(Failure Info) | Code | Name | | ---- | ---------------------------------------------------------- | | 0 | ACCEPT_ADMIN_PENDING_ADMIN_CHECK | | 1 | ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED | | 2 | ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED | | 3 | ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED | | 4 | ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED | | 5 | ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED | | 6 | ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED | | 7 | BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED | | 8 | BORROW_ACCRUE_INTEREST_FAILED | | 9 | BORROW_CASH_NOT_AVAILABLE | | 10 | BORROW_FRESHNESS_CHECK | | 11 | BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED | | 12 | BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED | | 13 | BORROW_MARKET_NOT_LISTED | | 14 | BORROW_COMPTROLLER_REJECTION | | 15 | LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED | | 16 | LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED | | 17 | LIQUIDATE_COLLATERAL_FRESHNESS_CHECK | | 18 | LIQUIDATE_COMPTROLLER_REJECTION | | 19 | LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED | | 20 | LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX | | 21 | LIQUIDATE_CLOSE_AMOUNT_IS_ZERO | | 22 | LIQUIDATE_FRESHNESS_CHECK | | 23 | LIQUIDATE_LIQUIDATOR_IS_BORROWER | | 24 | LIQUIDATE_REPAY_BORROW_FRESH_FAILED | | 25 | LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED | | 26 | LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED | | 27 | LIQUIDATE_SEIZE_COMPTROLLER_REJECTION | | 28 | LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER | | 29 | LIQUIDATE_SEIZE_TOO_MUCH | | 30 | MINT_ACCRUE_INTEREST_FAILED | | 31 | MINT_COMPTROLLER_REJECTION | | 32 | MINT_EXCHANGE_CALCULATION_FAILED | | 33 | MINT_EXCHANGE_RATE_READ_FAILED | | 34 | MINT_FRESHNESS_CHECK | | 35 | MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED | | 36 | MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED | | 37 | MINT_TRANSFER_IN_FAILED | | 38 | MINT_TRANSFER_IN_NOT_POSSIBLE | | 39 | REDEEM_ACCRUE_INTEREST_FAILED | | 40 | REDEEM_COMPTROLLER_REJECTION | | 41 | REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED | | 42 | REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED | | 43 | REDEEM_EXCHANGE_RATE_READ_FAILED | | 44 | REDEEM_FRESHNESS_CHECK | | 45 | REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED | | 46 | REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED | | 47 | REDEEM_TRANSFER_OUT_NOT_POSSIBLE | | 48 | REDUCE_RESERVES_ACCRUE_INTEREST_FAILED | | 49 | REDUCE_RESERVES_ADMIN_CHECK | | 50 | REDUCE_RESERVES_CASH_NOT_AVAILABLE | | 51 | REDUCE_RESERVES_FRESH_CHECK | | 52 | REDUCE_RESERVES_VALIDATION | | 53 | REPAY_BEHALF_ACCRUE_INTEREST_FAILED | | 54 | REPAY_BORROW_ACCRUE_INTEREST_FAILED | | 55 | REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED | | 56 | REPAY_BORROW_COMPTROLLER_REJECTION | | 57 | REPAY_BORROW_FRESHNESS_CHECK | | 58 | REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED | | 59 | REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED | | 60 | REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE | | 61 | SET_COLLATERAL_FACTOR_OWNER_CHECK | | 62 | SET_COLLATERAL_FACTOR_VALIDATION | | 63 | SET_COMPTROLLER_OWNER_CHECK | | 64 | SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED | | 65 | SET_INTEREST_RATE_MODEL_FRESH_CHECK | | 66 | SET_INTEREST_RATE_MODEL_OWNER_CHECK | | 67 | SET_MAX_ASSETS_OWNER_CHECK | | 68 | SET_ORACLE_MARKET_NOT_LISTED | | 69 | SET_PENDING_ADMIN_OWNER_CHECK | | 70 | SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED | | 71 | SET_RESERVE_FACTOR_ADMIN_CHECK | | 72 | SET_RESERVE_FACTOR_FRESH_CHECK | | 73 | SET_RESERVE_FACTOR_BOUNDS_CHECK | | 74 | TRANSFER_COMPTROLLER_REJECTION | | 75 | TRANSFER_NOT_ALLOWED | | 76 | TRANSFER_NOT_ENOUGH | | 77 | TRANSFER_TOO_MUCH | ## 汇率(Exchange Rate) 每个cToken 都可以兑换成数量不断增加的标的资产,因为在市场上会产生利息。cToken 与相关资产之间的汇率等于: ``` 1 exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply() ``` **CErc20 / CEther** ``` 1 function exchangeRateCurrent() returns (uint) ``` - 返回值 : 当前的汇率,为无符号整数,按 1e18 缩放; **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint exchangeRateMantissa = cToken.exchangeRateCurrent(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const exchangeRate = (await cToken.methods.exchangeRateCurrent().call()) / 1e18; ``` > 请注意,对比 send 使用 `call` 是在链外调用方法,而不需要导致 Gas 成本。 ## 获取现金(Get Cash) 现金是指该 cToken 合约所拥有的标的资产余额。人民可以查询到目前这个市场上的现金总量。 **CErc20 / CEther** 1 function getCash() returns (uint) - 返回值 : 该 cToken 合约所拥有的标的资产数量。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint cash = cToken.getCash(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const cash = (await cToken.methods.getCash().call()); ``` ## 总借款(Total Borrow) 总借贷额是指目前市场上借出的标的额,以及累计向市场上的供应商支付的利息。 **CErc20 / CEther** ``` 1 function totalBorrowsCurrent() returns (uint) ``` - 返回值:借出的标的总额与利息。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint borrows = cToken.totalBorrowsCurrent(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const borrows = (await cToken.methods.totalBorrowsCurrent().call()); ``` ## 借款余额(Borrow Balance) 从协议中借入资产的用户要根据借款利率进行累计利息。利息是每块都要累计的,集成商可以通过这个功能来获得用户的借款余额的当前价值与利息。 **CErc20 / CEther** ``` 1 function borrowBalanceCurrent(address account) returns (uint) ``` - account : 借入资产的账户。 - 返回值 : 用户的当前借款余额(与利息),单位是标的资产的单位。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint borrows = cToken.borrowBalanceCurrent(msg.caller); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const borrows = await cToken.methods.borrowBalanceCurrent(account).call(); ``` ## 借款利率(Borrow Rate) 在任何时候,任何人都可以通过查询合约来获取当前每个区块的借款利率。 **CErc20 / CEther** ``` 1 function borrowRatePerBlock() returns (uint) ``` - 返回值 : 当前借款利率,为一个无符号整数,按 1e18 缩放。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint borrowRateMantissa = cToken.borrowRatePerBlock(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const borrowRate = (await cToken.methods.borrowRatePerBlock().call()) / 1e18; ``` ## 总供应量(Total Supply) 总供应量是指目前在 cToken 市场上流通的代币数量。它是 cToken 合约的 EIP-20 接口的一部分 。 **CErc20 / CEther** ``` 1 function totalSupply() returns (uint) ``` - 返回值 : 在市场上流通的代币总数量。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint tokens = cToken.totalSupply(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const tokens = (await cToken.methods.totalSupply().call()); ``` ## 标的余额 Balance 用户的标的月,代币他们在协议中的资产,等于用户的 cToken 余额乘以[汇率]()。 **CErc20 / CEther** ``` 1 function balanceOfUnderlying(address account) returns (uint) ``` - account : 获取标的余额的账户。 - 返回值 : 该账户当前拥有的标的数量。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint tokens = cToken.balanceOfUnderlying(msg.caller); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const tokens = await cToken.methods.balanceOfUnderlying(account).call(); ``` ## 供给率(Supply Rate) 在任何时候,人们都可以通过查询合约来获取当前每块的供给率。供给率是由[借款利率]()、准备金系数([reserve factor](https://compound.finance/docs/ctokens#reserve-factor))和[总借款额]()得出的。 **CErc20 / CEther** ``` 1 function supplyRatePerBlock() returns (uint) ``` - 返回值 : 当前供给率,为一个无符号整数,按 1e18 缩放。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint supplyRateMantissa = cToken.supplyRatePerBlock(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const supplyRate = (await cToken.methods.supplyRatePerBlock().call()) / 1e18; ``` ## 总储备金(Total Reserves) 储备金是每个 cToken 合约中的会计分录,代币历史利息的一部分,作为现金预留,可以通过协议的治理来提取或转移。借款人利息的一小部分应计入协议中,由准备金系数 [reserve factor](https://compound.finance/docs/ctokens#reserve-factor)决定。 **CErc20 / CEther** ``` 1 function totalReserves() returns (uint) ``` - 返回值 : 市场上持有的储备金总额。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2 uint reserves = cToken.totalReserves(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const reserves = (await cToken.methods.totalReserves().call()); ``` ## 储备金系数(Reserve Factor) 准备金系数确定了借款人利息中转化为准备金的部分。 **CErc20 / CEther** ``` 1 function reserveFactorMantissa() returns (uint) ``` - 返回值 : 当前市场准备金系数,为一个无符号整数,按 1e18 缩放。 **Solidity** ``` 1 CErc20 cToken = CToken(0x3FDA...); 2uint reserveFactorMantissa = cToken.reserveFactorMantissa(); ``` **Web3 1.0** ``` 1 const cToken = CEther.at(0x3FDB...); 2 const reserveFactor = (await cToken.methods.reserveFactorMantissa().call()) / 1e18; ```

请注意,在翻译时遇到一个单词 Underlying 相关的词组有 Underlying BalanceUnderlying assets。个人觉得翻译成基础余额、底层余额、底层资产、基础资产等听着不对味,所以我根据理解,将其翻译为标的余额、标的资产。有来喷的吗?点击右侧加号可以留言!cToken 就是对 Token 的封装,这个 Token 就可以视为交易的标的物。

介绍

Compound 协议所支持的每项资产都通过 cToken 合约进行整合,cToken 合约是提供给协议的余额的 EIP-20 合格表示。通过铸造 cToken,用户(1)通过 cToken 的汇率赚取利息,该汇率相对于标的资产的价值增加,以及(2)获得试用 cToken 作为抵押品的能力。

cToken 是与 Compound 协议交互的主要手段;当用户在使用 cToken 合约时,会使用 cToken 合约来进行铸币(mint)、赎回(redeem)、借款(borrow)、偿还借款(repay)、清算借款(liquidate)或者划转 cToken (transfer)。

目前有两种类型的 cToken : CErc20 和 CEther。尽管两者都暴露了 EIP-20 接口,但 CErc20 封装了 ERC-20 标的资产,而 CEther 只是封装了 Ether 本身。因此,根据类型的不同,涉及将资产传输到协议中的核心功能的接口也略有不同,每种类型的接口如下所示。

铸币(Mint)

mint 方法将一个资产转移到协议中,协议开始根据该资产的当前[供应率]()开始累积利息。用户收到的 cToken 数量等于标的代币数量除以当前[汇率]()。

CErc20

1 function mint(uint mintAmount) returns (uint)
  • msg.sender : 供应资产并拥有已铸 cToken 的账户。
  • mintAmount : 供应的资产金额,单位为标的资产的单位。
  • RETURN : 成功时为0,否则是[错误代码]()。

供应资产前,用户必须先 批准(approve), cToken 才能访问其代币余额。

CEther

1 function mint() payable
  • msg.value : 供应的 ETH 数量,单位 wei。
  • msg.sender : 供应 ETH 并拥有已铸 cToken 的账户。
  • RETURN : 无返回值,错误时还原。

Solidity

1 Erc20 underlying = Erc20(0xToken...);     // 获取标的资产合约句柄 
2 CErc20 cToken = CErc20(0x3FDA...);        // 获取相应 cToken 合约的句柄 
3 underlying.approve(address(cToken), 100); // 批准划转 
4 assert(cToken.mint(100) == 0);            // 铸 cToken 币,并断言是否有错误

Web3 1.0

1 const cToken = CEther.at(0x3FDB...); 
2 await cToken.methods.mint().send({from: myAccount, value: 50});

赎回(Redeem)

redeem 方法将指定数量的 cToken 转换为标的资产,并将其返还给用户。收到的标的数量等于赎回的 cToken 数量乘以当前[汇率]()。赎回额必须小于用户的账户流动性和市场可用的流动性。

CErc20 / CEther

function redeem(uint redeemTokens) returns (uint)
  • msg.sender : 应将赎回的标的资产转入的账户。
  • redeemTokens : 将被赎回的 cToken 数量。
  • RETURN : 成功时为0,否则是[错误代码]()。

Solidity

1 CEther cToken = CEther(0x3FDB...);
2 require(cToken.redeem(7) == 0, "something went wrong");

赎回标的(Redeem Underlying)

redeem underlying 方法将 cToken兑换成指定数量的标的资产,并返回给用户。赎回的 cToken的数量等于收到的标的数量除以当前[汇率]()。赎回额必须小于用户的账户流动性和市场可用的流动性。

CErc20 / CEther

1 function redeemUnderlying(uint redeemAmount) returns (uint)
  • msg.sender : 应将赎回的标的资产转入的账户。
  • redeemAmount : 将被赎回的标的资产数量。
  • RETURN : 成功时为0,否则是[错误代码]()。

Solidity

1 CEther cToken = CEther(0x3FDB...);
2 require(cToken.redeemUnderlying(50) == 0, "something went wrong");

Web3 1.0

1 const cToken = CErc20.at(0x3FDA...);
2 cToken.methods.redeemUnderlying(10).send({from: ...});

借款(Borrow)

borrow 方法将协议中的资产转移给用户,并创建一个借款余额,根据该资产的[借款利率]()开始累积利息。借款额必须小于用户的账户流动性和市场可用的流动性。

要想借入以太,借款人必须是 'payable' (Solidity)。

CErc20 / CEther

1 function borrow(uint borrowAmount) returns (uint)
  • msg.sender : 应将借款资金转入的账户。
  • borrowAmount : 标的资产借款数量。
  • ETURN : 成功时为0,否则是[错误代码]()。

Solidity

1 CErc20 cToken = CErc20(0x3FDA...);
2 require(cToken.borrow(100) == 0, "got collateral?");

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 await cToken.methods.borrow(50).send({from: 0xMyAccount});

偿还借款(Repay Borrow)

repay 方法将资产转移到协议中,并减少用户的借款余额。

CErc20

1 function repayBorrow(uint repayAmount) returns (uint)
  • msg.sender : 借入资产的账户,应偿还借款。
  • repayAmount : 拟偿还的标的资产借款金额。值为-1(即2256-1)表示偿还全部借款额。
  • RETURN : 成功时为0,否则是[错误代码]()。

偿还资产前,用户必须先 批准(approve), cToken 才能访问其代币余额。

CEther

1 function repayBorrow() payable
  • msg.value : 用于偿还的 ETH 数量,单位 wei。
  • msg.sender : 借入资产的账户,应偿还借款。
  • RETURN : 无返回值,错误时还原。

Solidity

1 CEther cToken = CEther(0x3FDB...);

2 require(cToken.repayBorrow.value(100)() == 0, "transfer approved?");

Web3 1.0

1 const cToken = CErc20.at(0x3FDA...);

2 cToken.methods.repayBorrow(10000).send({from: ...});

代偿还借款(Repay Borrow Behalf)

repay 方法将资产转移到协议中,并减少目标用户的借款余额。

CErc20

1 function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint)
  • msg.sender : 偿还借款的账户。
  • borrower : 借入资产要偿还的账户。
  • repayAmount : 拟偿还的标的资产借款金额。值为-1(即2256-1)表示偿还全部借款额。
  • RETURN : 成功时为0,否则是[错误代码]()。

偿还资产前,用户必须先 批准(approve), cToken 才能访问其代币余额。

CEther

1 function repayBorrowBehalf(address borrower) payable
  • msg.value : 用于偿还的 ETH 数量,单位 wei。
  • msg.sender : 偿还借款的账户。
  • borrower : 借入资产要偿还的账户。
  • RETURN : 无返回值,错误时还原。

Solidity

1 CEther cToken = CEther(0x3FDB...);
2 require(cToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?");

Web3 1.0

1 const cToken = CErc20.at(0x3FDA...);
2 await cToken.methods.repayBorrowBehalf(0xBorrower, 10000).send({from: 0xPayer});

清算借款(Liquidate Borrow)

账户流动性为负值的用户,由协议的其他用户进行[清算](),使其账户流动性恢复到正值(即高于抵押品要求)。当发生清算时,清算人(liquidator)可以代表借款人偿还部分或全部未偿还的借款,作为回报,可以获得借款人持有的抵押品的折价;这种折价被定义为清算奖励。

清算人可将水下账户的任何一个未偿还借款以一定的固定比例(即结算系数)进行结算。与 V1 中不同的是,清算者必须与每一个 cToken 合约中偿还借款并扣押另一项资产作为抵押品的 cToken 进行交互。当抵押品被扣押时,清算人会被转移 cToken,他们可以赎回这些 cToken,就像他们自己提供资产一样。用户必须在调用清算前批准每个 cToken 合约(即在他们要偿还的借款资产上),因为他们正在将资金转移到合约中。

CErc20

1 function liquidateBorrow(address borrower, uint amount, address collateral) returns (uint)
  • msg.sender : 应通过偿还借款人的债务和扣押抵押品来结算借款人的账户。
  • borrower : 应予清算的负账户流动性账户。
  • repayAmount : 借款资产的偿还和转换为抵押品的金额,以标的抵押资产的单位为单位。
  • cTokenCollateral : 清算人应扣押借款人目前作为抵押品持有的 cToken 地址。
  • RETURN : 成功时为0,否则是[错误代码]()。

偿还资产前,用户必须先 批准(approve), cToken 才能访问其代币余额。

CEther

1 function liquidateBorrow(address borrower, address cTokenCollateral) payable
  • msg.value : 转换为抵押品的 ETH 金额,单位 wei 。
  • msg.sender : 应通过偿还借款人的债务和扣押抵押品来结算借款人的账户。
  • borrower : 应予清算的负账户流动性账户。
  • cTokenCollateral : 清算人应扣押借款人目前作为抵押品持有的 cToken 地址。
  • RETURN : 成功时为0,否则是[错误代码]()。

Solidity

1 CEther cToken = CEther(0x3FDB...); 
2 CErc20 cTokenCollateral = CErc20(0x3FDA...);
3  require(cToken.liquidateBorrow.value(100)(0xBorrower, cTokenCollateral) == 0, "borrower underwater??");

Web3 1.0

1 const cToken = CErc20.at(0x3FDA...); 
2 const cTokenCollateral = CEther.at(0x3FDB...);
3  await cToken.methods.liquidateBorrow(0xBorrower, 33, cTokenCollateral).send({from: 0xLiquidator});

主要事件(Key Events)

Event Description
Mint(address minter, uint mintAmount, uint mintTokens) 铸币成功后发出
Redeem(address redeemer, uint redeemAmount, uint redeemTokens) [赎回]()成功后发出
Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows) 借款成功后发出
RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows) [偿还借款]()成功后发出
LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens) [借款清算]()成功后发出

错误代码(Error Codes)

Code Name Description
0 NO_ERROR 不是失败。
1 UNAUTHORIZED 发件人无权实施这一操作。
2 BAD_INPUT 调用者提供了一个无效参数。
3 COMPTROLLER_REJECTION 该操作将违反审计官政策。
4 COMPTROLLER_CALCULATION_ERROR 审计内部计算失败 。
5 INTEREST_RATE_MODEL_ERROR 利率模型返回了一个无效值。
6 INVALID_ACCOUNT_PAIR 指定的账户组合是无效的。
7 INVALID_CLOSE_AMOUNT_REQUESTED 清算金额无效。
8 INVALID_COLLATERAL_FACTOR 抵押因子无效。
9 MATH_ERROR 出现了数学计算错误。
10 MARKET_NOT_FRESH 利息没有正确产生。
11 MARKET_NOT_LISTED 目前,市场没有由审计员列出。
12 TOKEN_INSUFFICIENT_ALLOWANCE ERC-20 合约必须允许(allow)货币市场合约调用transferForm。当前 allow 额为0或小于请求的供给、偿还借款或清算金额。
13 TOKEN_INSUFFICIENT_BALANCE 调用者在 ERC-20 合约中没有足够的余额来完成所需的操作。
14 TOKEN_INSUFFICIENT_CASH 市场上没有足够的现金金额来完成交易。您可以稍后再尝试此项交易。
15 TOKEN_TRANSFER_IN_FAILED 在 ERC-20 代币转入市场时失败。
16 TOKEN_TRANSFER_OUT_FAILED 在 ERC-20 代币转出市场时失败。

失败信息(Failure Info)

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

汇率(Exchange Rate)

每个cToken 都可以兑换成数量不断增加的标的资产,因为在市场上会产生利息。cToken 与相关资产之间的汇率等于:

1 exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply()

CErc20 / CEther

1 function exchangeRateCurrent() returns (uint)
  • 返回值 : 当前的汇率,为无符号整数,按 1e18 缩放;

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint exchangeRateMantissa = cToken.exchangeRateCurrent();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...); 
2 const exchangeRate = (await cToken.methods.exchangeRateCurrent().call()) / 1e18;

请注意,对比 send 使用 call 是在链外调用方法,而不需要导致 Gas 成本。

获取现金(Get Cash)

现金是指该 cToken 合约所拥有的标的资产余额。人民可以查询到目前这个市场上的现金总量。

CErc20 / CEther

1 function getCash() returns (uint)

  • 返回值 : 该 cToken 合约所拥有的标的资产数量。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint cash = cToken.getCash();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const cash = (await cToken.methods.getCash().call());

总借款(Total Borrow)

总借贷额是指目前市场上借出的标的额,以及累计向市场上的供应商支付的利息。

CErc20 / CEther

1 function totalBorrowsCurrent() returns (uint)
  • 返回值:借出的标的总额与利息。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint borrows = cToken.totalBorrowsCurrent();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const borrows = (await cToken.methods.totalBorrowsCurrent().call());

借款余额(Borrow Balance)

从协议中借入资产的用户要根据借款利率进行累计利息。利息是每块都要累计的,集成商可以通过这个功能来获得用户的借款余额的当前价值与利息。

CErc20 / CEther

1 function borrowBalanceCurrent(address account) returns (uint)
  • account : 借入资产的账户。
  • 返回值 : 用户的当前借款余额(与利息),单位是标的资产的单位。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint borrows = cToken.borrowBalanceCurrent(msg.caller);

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const borrows = await cToken.methods.borrowBalanceCurrent(account).call();

借款利率(Borrow Rate)

在任何时候,任何人都可以通过查询合约来获取当前每个区块的借款利率。

CErc20 / CEther

1 function borrowRatePerBlock() returns (uint)
  • 返回值 : 当前借款利率,为一个无符号整数,按 1e18 缩放。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint borrowRateMantissa = cToken.borrowRatePerBlock();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const borrowRate = (await cToken.methods.borrowRatePerBlock().call()) / 1e18;

总供应量(Total Supply)

总供应量是指目前在 cToken 市场上流通的代币数量。它是 cToken 合约的 EIP-20 接口的一部分 。

CErc20 / CEther

1 function totalSupply() returns (uint)
  • 返回值 : 在市场上流通的代币总数量。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2  uint tokens = cToken.totalSupply();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const tokens = (await cToken.methods.totalSupply().call());

标的余额 Balance

用户的标的月,代币他们在协议中的资产,等于用户的 cToken 余额乘以[汇率]()。

CErc20 / CEther

1 function balanceOfUnderlying(address account) returns (uint)
  • account : 获取标的余额的账户。
  • 返回值 : 该账户当前拥有的标的数量。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint tokens = cToken.balanceOfUnderlying(msg.caller);

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const tokens = await cToken.methods.balanceOfUnderlying(account).call();

供给率(Supply Rate)

在任何时候,人们都可以通过查询合约来获取当前每块的供给率。供给率是由[借款利率]()、准备金系数(reserve factor)和[总借款额]()得出的。

CErc20 / CEther

1 function supplyRatePerBlock() returns (uint)
  • 返回值 : 当前供给率,为一个无符号整数,按 1e18 缩放。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint supplyRateMantissa = cToken.supplyRatePerBlock();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const supplyRate = (await cToken.methods.supplyRatePerBlock().call()) / 1e18;

总储备金(Total Reserves)

储备金是每个 cToken 合约中的会计分录,代币历史利息的一部分,作为现金预留,可以通过协议的治理来提取或转移。借款人利息的一小部分应计入协议中,由准备金系数 reserve factor决定。

CErc20 / CEther

1 function totalReserves() returns (uint)
  • 返回值 : 市场上持有的储备金总额。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2 uint reserves = cToken.totalReserves();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...);
2 const reserves = (await cToken.methods.totalReserves().call());

储备金系数(Reserve Factor)

准备金系数确定了借款人利息中转化为准备金的部分。

CErc20 / CEther

1 function reserveFactorMantissa() returns (uint)
  • 返回值 : 当前市场准备金系数,为一个无符号整数,按 1e18 缩放。

Solidity

1 CErc20 cToken = CToken(0x3FDA...);
2uint reserveFactorMantissa = cToken.reserveFactorMantissa();

Web3 1.0

1 const cToken = CEther.at(0x3FDB...); 
2 const reserveFactor = (await cToken.methods.reserveFactorMantissa().call()) / 1e18;

区块链技术网。

  • 发表于 2021-01-25 11:38
  • 阅读 ( 175 )
  • 学分 ( 0 )
  • 分类:DeFi
  • 专栏:Compound 研究

评论