科普 | Compound的cToken及相关核心函数

关键词:区块链 6354 2019-10-15

去中心化金融(DeFi)协议Compound支持的所有资产,都是通过cToken智能合约来封装集成的,用户通过铸造代币(cToken)向协议提供资产,然后你只要持有cToken,就可以赚取到利息,而当你选择赎回后,每个cToken都可兑换成相应的基础资产。

可以说,cToken是与Compound协议交互的主要方式。每个cToken合约都创造了自己的货币市场,而用户铸币、赎回、借款、偿还借款、清算借款或转让cToken时,他们将使用到cToken合约。

目前,Compound协议有两种类型的cToken:CErc20和CEther,其中CErc20封装的是ERC-20资产,而CEther则封装的是以太币。

4

(当前Compound协议支持的7种cToken及对应合约地址)

而在这篇文章中,我们将了解Compound协议的核心函数: Mint(铸币); Redeem(赎回); Redeem Underlying(赎回基础资产); Borrow(借款); Repay Borrow(偿还借款); Repay Borrow Behalf; Liquidate Borrow(清算借款); 故障信息 Exchange Rate(兑换汇率); Get Cash(获取Cash); Total Borrow(借款总额); Borrow Balance(借款余额); Borrow Rate(借款利率); Total Supply(总供给量); Supply Balance(供应余额); Supply Balance Underlying(基础资产供应余额); Supply Rate(供应率); Total Reserves(总储备金); Reserve Factor(储备金率);   1、铸币(Mint)  

铸币(Mint)函数负责将资产转移到货币市场,后者根据资产的当前供应率计算利息。铸造的代币数量,根据用户所提供的基础资产数量除以当前汇率得出。

铸币(Mint)相当于Compound 协议的供应来源。

CErc20 function mint(uint mintAmount) returns (uint) msg.sender : 提供资产并拥有铸造cToken的帐户; mintAmount : 以基础资产为单位进行铸币的金额; RETURN:返回0表示成功,其它则是错误代码; 在提供资产之前,用户必须首先批准cToken以访问其代币余额;

CEther function mint() payable msg.value (payable):以太币待提供金额,单位为wei; msg.sender:提供以太币并拥有铸造cToken的账户; RETURN : 没有返回,出错时还原; 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});   2、赎回  

赎回函数负责将基础资产从货币市场转移至用户,以交换之前铸造的cToken。基础资产赎回金额根据cToken的数量乘以当前汇率得出。赎回金额必须小于用户帐户的流动性以及市场的可用流动性。

赎回相当于Compound 协议的退出功能。

CErc20 / CEther function redeem(uint redeemTokens) returns (uint) msg.sender : 赎回资金转移账户; redeemTokens : 要赎回的cToken数量; RETURN : 返回0表示成功,其它则是错误代码; 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: ...});   3、赎回基础资产  

赎回基础资产函数,负责将基础资产从货币市场转移给用户,以换取之前铸造的CToken。cToken赎回的数量是基础资产的金额除以当前汇率。赎回金额必须小于用户帐户的流动性和市场的可用流动性。

CErc20 / CEther function redeemUnderlying(uint redeemAmount) returns (uint) msg.sender : 赎回资金转移账户; redeemAmount : 要赎回的基础资产金额; RETURN : 返回0表示成功,其它则是错误代码; 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: ...});   4、借款  

借款函数负责将资产从货币市场转移给用户,并创建一个借款余额,该余额根据资产的借款利率累积利息。

借款金额必须少于用户的借款能力以及市场的可用流动性。用户必须维持一个抵押品要求以避免清算。

请注意,借款人将收到一笔基础资产交易。对CEther来说,这将是以太币,因此借款人必须是可偿付的。

CErc20 / CEther function borrow(uint borrowAmount) returns (uint) msg.sender : 借款资金转移账户; borrowAmount : 待借基础资产金额; RETURN :返回0表示成功,其它则是错误代码; 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});   5、偿还借款  

偿还函数负责将资产转移到货币市场,以减少用户的借款余额。

CErc20 function repayBorrow(uint repayAmount) returns (uint) msg.sender : 借用资产并应偿还借款的账户; repayAmount : 待偿还标的借款资产的金额,值-1 (即2^256 -1)可用于偿还全部金额; RETURN : 返回0表示成功,其它则是错误代码; 在提供资产之前,用户必须首先批准cToken以访问其代币余额;

CEther function repayBorrow() payable msg.value (payable):偿还的以太币数量,单位为wei; msg.sender:借用资产,并应偿还借款的账户; RETURN : 没有return,出错时还原; 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: ...});   6、偿还Borrow Behalf  

该偿还函数负责将资产转移到货币市场,以减少用户的借款余额。

CErc20 function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint) msg.sender : 应偿还借款的账户; borrower : 借用待偿还资产的账户; repayAmount : 待偿还标的借款资产的金额,值-1 (即2^256 -1)可用于偿还全部金额; RETURN : 返回0表示成功,其它则是错误代码; 在提供资产之前,用户必须首先批准cToken以访问其代币余额;

CEther function repayBorrowBehalf(address borrower) payable msg.value (payable):偿还的以太币数量,单位为wei; msg.sender:应偿还借款的账户; borrower : 借用偿还资产的账户; RETURN : 没有return,出错时还原; 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});   7、清算借款  

账户流动性为负的用户将被协议的其他用户清算,以使其账户流动性恢复为正(即高于抵押品要求)。当清算发生时,清算人可代表借款人偿还部分或全部未偿还借款,作为回报,清算人可获得借款人持有的抵押物,这被定义为清算激励。

清算人可将“清算账户”(即低于抵押品要求的账户)的任何未偿还借款的某一固定百分比结清。与v1不同的是,清算人必须与每个cToken合约进行互动,在这些合约中,他们希望偿还借款并扣押另一资产作为抵押品。当抵押品被扣押时,清算人被转移至cToken,他们可赎回这些抵押品,就像他们自己提供了资产一样。用户在将资金转入合约之前,必须先批准每个cToken合约,然后才能进行清算。

CErc20 function liquidateBorrow(address borrower, uint amount, address collateral) returns (uint) msg.sender : 通过偿还债务和扣押抵押品清算借款人的账户; borrower : 应清算的账户流动性为负的账户; repayAmount : 以标的借款资产为单位,待偿还的借款金额; cTokenCollateral : 清算人应扣押的借款人持有的cToken地址; RETURN : 返回0表示成功,其它则是错误代码; 在提供资产之前,用户必须首先批准cToken以访问其代币余额;

CEther function liquidateBorrow(address borrower, address cTokenCollateral) payable msg.value (payable):待偿还且被转换为抵押品的以太币,单位为wei; msg.sender : 通过偿还债务和扣押抵押品,用于清算借款人的账户; borrower : 应清算的账户流动性为负的账户; cTokenCollateral :清算人应扣押的,借款人目前作为抵押品持有的cToken地址; RETURN : 没有return,出错时还原; 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});   8、故障信息  

45 55 56 9、兑换汇率  

随着市场利息的增加,每个cToken都可转换成(不断增长的)基础资产。cToken与基础资产之间的汇率等于: exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply() CErc20 / CEther function exchangeRateCurrent() returns (uint) RETURN : 当前汇率为无符号整数,按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; 提示:注意使用call和send从链外调用该函数,则不会产生gas成本。

  10、Get Cash  

Cash是该cToken合约所拥有的基础资产余额。人们可查询这个市场目前可用的cash总额。

CErc20 / CEther function getCash() returns (uint) RETURN : 合约所拥有基础资产的数量。

Solidity CErc20 cToken = CToken(0x3FDA...); uint cash = cToken.getCash(); Web3 1.0 const cToken = CEther.at(0x3FDB...); const cash = (await cToken.methods.getCash().call());   11、借款总额  

借款总额是指市场目前借出的基础资产总金额,加上相应的利息金额。

CErc20 / CEther function totalBorrowsCurrent() returns (uint) RETURN : 加上利息的基础资产借款总额;

Solidity CErc20 cToken = CToken(0x3FDA...); uint borrows = cToken.totalBorrowsCurrent(); Web3 1.0 const cToken = CEther.at(0x3FDB...); const borrows = (await cToken.methods.totalBorrowsCurrent().call());   12、借款余额  

从协议中借款的用户,将根据当前借款利率支付累计利息。利息是每个区块累积计算的,我们可使用此函数获得用户(带利息)借款余额的当前值;

CErc20 / CEther function borrowBalanceCurrent(address account) returns (uint) account : 借用资产的账户; RETURN : 用户当前的标的资产借款余额(含利息); 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();   13、借款利率  

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

CErc20 / CEther function borrowRatePerBlock() returns (uint) RETURN :当前借款利率为无符号整数,按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; 14、总供给量  

所谓总供给量,是指当前在这个cToken市场上流通的代币数量。它是cToken合约EIP-20接口的一部分。

CErc20 / CEther function totalSupply() returns (uint) RETURN : 市场流通的代币总数。

Solidity CErc20 cToken = CToken(0x3FDA...); uint tokens = cToken.totalSupply(); Web3 1.0 const cToken = CEther.at(0x3FDB...); const tokens = (await cToken.methods.totalSupply().call());   15、供应余额  

向协议提供资产的用户,将收到利息代币作为报酬。在任何给定时间,我们可通过汇率查询带息代币的价值。我们还可以查询特定用户拥有的代币数量,这是cToken合约EIP-20接口的一部分。

CErc20 / CEther function balanceOf(address account) returns (uint) account : 获取代币余额的账户; RETURN : 帐户当前拥有的代币数; 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();   16、基础资产供应余额  

CToken还有一种方便的方法,可根据基础资产金额(即供应余额乘以汇率)来确定供应余额。

CErc20 / CEther function balanceOfUnderlying(address account) returns (uint) account : 要获取基础资产余额的帐户; RETURN : 帐户当前拥有的基础资产金额; 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();   17、供应率  

在任何时候,人们都可以查询合约,以获得每个区块的当前供应率。供应率由借款利率、储备金率以及借款总额得出。

CErc20 / CEther function supplyRatePerBlock() returns (uint) RETURN : 当前供应率为无符号整数,按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;   18、总储备金  

储备金是协议本身的权益,以便为其运作提供资金。储备金也构成了cash的一部分,可用于贷给市场上的借款人。借款人的一小部分利息计入协议,而它是由准备金率决定的。

CErc20 / CEther function totalReserves() returns (uint) RETURN : 协议持有的储备金总额;

Solidity CErc20 cToken = CToken(0x3FDA...); uint reserves = cToken.totalReserves(); Web3 1.0 const cToken = CEther.at(0x3FDB...); const reserves = (await cToken.methods.totalReserves().call());   19、储备金率  

储备金率定义了应计入储备金的一小部分利息。

CErc20 / CEther function reserveFactorMantissa() returns (uint) RETURN : 当前储备金率为无符号整数,按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;

>快讯
3月28日 星期四
相关资讯