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

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

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

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

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

(当前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、故障信息

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

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;发文时比特币价格: ¥58760.12特别声明

原文:https://compound.finance/developers/ctokens
作者:compound
编译:洒脱喜
稿源(译):巴比特资讯(http://www.8btc.com/compound-ctoken)