Comptroller – Compound 协议风险管理
Comptroller协议风险管理
## 介绍 Comptroller 是 Compound 协议的风险管理层;它决定了用户需要维持多少抵押品,以及是否可以(和多少)清算用户。每次用户与 cToken 交互时,Comptroller 都会被要求批准或拒绝交易。 Comptroller 将用户余额映射到价格(通过价格预言机),再映射到风险权重(称为[抵押系数]() )来进行判断。用户通过调用“[进入市场]()”和“[退出市场]()”,明确列出他们希望在风险评分中包括哪些资产。 ## 架构 Comptroller 作为一个可升级的代理实现。Unitroller 将所有逻辑都代理给 Comptroller 实现,但存储值是在 Unitroller 上设置的。要调用 Comptroller 方法,请使用 Unitroller 地址上的 Comptroller ABI。 ## 进入市场 进入一个市场的清单 -- 重复进入同一个市场,不是错误。要想在一个市场中提供抵押品或借贷,必须先进入市场。 **Comptroller** ``` 1 function enterMarkets(address[] calldata cTokens) returns (uint[] memory) ``` - msg.sender : 应进入特定市场的账户。 - cTokens : 要进入的 cToken 市场地址。 - 返回值: 对于每个市场,返回一个错误代码,表示是否已进入市场。成功时为 0,否则返回[错误代码]()。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 CToken[] memory cTokens = new CToken[](2); 3 cTokens[0] = CErc20(0x3FDA...); 4 cTokens[1] = CEther(0x3FDB...); 5 uint[] memory errors = troll.enterMarkets(cTokens); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const cTokens = [CErc20.at(0x3FDA...), CEther.at(0x3FDB...)]; 3 const errors = await troll.methods.enterMarkets(cTokens).send({from: ...}); ``` ## 退出市场 退出一个市场 -- 退出当前没有进入的市场,这不是错误。退出市场将不计入账户流动性计算。 **Comptroller** ``` 1 function exitMarket(address cToken) returns (uint) ``` - msg.sender : 应退出特定市场的账户。 - cTokens : 要退出的市场 cToken 地址。 - RETURN : 成功时为 0,否则返回[错误代码]()。 **Solidity** ``` 1Comptroller troll = Comptroller(0xABCD...); 2uint error = troll.exitMarket(CToken(0x3FDA...)); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const errors = await troll.methods.exitMarket(CEther.at(0x3FDB...)).send({from: ...}); ``` ## Get Assets In 获取一个账户目前进入的市场列表。要在市场上提供抵押品或借款,必须先进入市场。已进入的市场计入账户流动性计算中。 **Comptroller** ``` 1 function getAssetsIn(address account) view returns (address[] memory) ``` - account : 应查询其进入市场清单的账户; - RETURN : 目前进入的每个市场的地址。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 address[] memory markets = troll.getAssetsIn(0xMyAccount); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const markets = await troll.methods.getAssetsIn(cTokens).call(); ``` ## 抵押系数 一个 cToken 的抵押系数(Collateral factors)可以在 0-90% 之间,代表账户通过铸造 cToken 获得的流动性(借款限额)的比例增加。 一般来说,大额资产或流动性较强的资产抵押系数较高,而小额资产或流动性较差的资产抵押系数较低。如果一项资产的抵押系数为 0%,则不能作为抵押品(或在清算时被扣押),但仍可借入。 随着市场情况的变化,可以通过 Compound 治理,提高(或降低)抵押品系数。 **Comptroller** ``` 1 function markets(address cTokenAddress) view returns (bool, uint) ``` - cTokenAddress : 检查特定的 cToken 是否上市,并获得其抵押系数。 - RETURN : 值元祖(isListed, collateralFactorMantissa);isListed 代表审计是否承认这个cToken;collateralFactorMantissa 代表(抵押系数),按 1e18 比例乘以一个供给余额来确定可以借入多少资产。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 (bool isListed, uint collateralFactorMantissa) = troll.markets(0x3FDA...); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const result = await troll.methods.markets(0x3FDA...).call(); 3 const {0: isListed, 1: collateralFactorMantissa} = result; ``` ## 获取账户流动性 在 Compound 协议中,账户流动性被定义为账户抵押品的预估以太值(供应余额乘以协议[抵押系数](),减去账户借款余额的总价值)。这些价值仅使用账户[已进入]()的市场计算。 没有正账户流动性的用户在没有提供更多的资产或者偿还未偿还的借款,使其账户流动性恢复到正值之前,没有能力提取或借入任何资产。 **Comptroller** ``` 1 function getAccountLiquidity(address account) view returns (uint, uint, uint) ``` - account : 应计算其流动性的账户; - RETURN : 数组值(error、liquidity、shortfall)。成功时错误为0,否则为[错误代码]()。非零 liquidity 表示该账户有可用的账户流动性。非零 shortfall 表示该账户目前低于其抵押品要求,需要清算。 liquidity 和 shortfall 最多只有一个不为零。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 (uint error, uint liquidity, uint shortfall) = troll.getAccountLiquidity(msg.caller); 3 require(error == 0, "join the Discord"); 4 require(shortfall == 0, "account underwater"); 5 require(liquidity > 0, "account has excess collateral"); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const result = await troll.methods.getAccountLiquidity(0xBorrower).call(); 3 const {0: error, 1: liquidity, 2: shortfall} = result; ``` ## 关闭系数 可清偿借款的账户中,可在一次清算交易中偿还的借款的百分比,范围从 0% 到 100%。如果一个用户有多个借款资产,则 closeFactor 适用于任何单一的借款资产,而不是用户未清偿借款的总价值。 **Comptroller** ``` 1 function closeFactorMantissa() view returns (uint) ``` - 返回值 : 关闭系数,按 1e18 比例计算,乘以未偿还的借款余额,确定可以结清多少借款。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 uint closeFactor = troll.closeFactorMantissa(); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const closeFactor = await troll.methods.closeFactoreMantissa().call(); ``` ## 清算奖励 给予清算人的额外抵押品,作为清算水下账户的奖励。例如,如果清算奖励是 1.1 ,那么清算人每关闭一个单位,就能额外获得借款人抵押品的 10%。 **Comptroller** ``` 1 function liquidationIncentiveMantissa() view returns (uint) ``` - 返回值 : 清算奖励,按 1e18 比例计算,再乘以清算人的平仓借款金额,以确定可以扣押多少抵押品。 **Solidity** ``` 1 Comptroller troll = Comptroller(0xABCD...); 2 uint closeFactor = troll.liquidationIncentiveMantissa(); ``` **Web3 1.0** ``` 1 const troll = Comptroller.at(0xABCD...); 2 const closeFactor = await troll.methods.liquidationIncentiveMantissa().call(); ``` ## 主要事件 | Event | Description | | --------------------------------------------- | ---------------------- | | MarketEntered(CToken cToken, address account) | 成功[进入市场]()时发生 | | MarketExited(CToken cToken, address account) | 成功[退出市场]()时发生 | ## 错误代码 | Code | Name | Description | | ---- | ----------------------------- | ------------------------------------------------------------ | | 0 | NO_ERROR | 不算错误 | | 1 | UNAUTHORIZED | The sender is not authorized to perform this action. | | 2 | COMPTROLLER_MISMATCH | Liquidation cannot be performed in markets with different comptrollers. | | 3 | INSUFFICIENT_SHORTFALL | The account does not have sufficient shortfall to perform this action. | | 4 | INSUFFICIENT_LIQUIDITY | The account does not have sufficient liquidity to perform this action. | | 5 | INVALID_CLOSE_FACTOR | The close factor is not valid. | | 6 | INVALID_COLLATERAL_FACTOR | The collateral factor is not valid. | | 7 | INVALID_LIQUIDATION_INCENTIVE | The liquidation incentive is invalid. | | 8 | MARKET_NOT_ENTERED | The market has not been entered by the account. | | 9 | MARKET_NOT_LISTED | The market is not currently listed by the comptroller. | | 10 | MARKET_ALREADY_LISTED | An admin tried to list the same market more than once. | | 11 | MATH_ERROR | A math calculation error occurred. | | 12 | NONZERO_BORROW_BALANCE | The action cannot be performed since the account carries a borrow balance. | | 13 | PRICE_ERROR | The comptroller could not obtain a required price of an asset. | | 14 | REJECTION | The comptroller rejects the action requested by the market. | | 15 | SNAPSHOT_ERROR | The comptroller could not get the account borrows and exchange rate from the market. | | 16 | TOO_MANY_ASSETS | Attempted to enter more markets than are currently supported. | | 17 | TOO_MUCH_REPAY | Attempted to repay more than is allowed by the protocol. | ## 错误信息 | Code | Name | | ---- | ------------------------------------------- | | 0 | ACCEPT_ADMIN_PENDING_ADMIN_CHECK | | 1 | ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK | | 2 | EXIT_MARKET_BALANCE_OWED | | 3 | EXIT_MARKET_REJECTION | | 4 | SET_CLOSE_FACTOR_OWNER_CHECK | | 5 | SET_CLOSE_FACTOR_VALIDATION | | 6 | SET_COLLATERAL_FACTOR_OWNER_CHECK | | 7 | SET_COLLATERAL_FACTOR_NO_EXISTS | | 8 | SET_COLLATERAL_FACTOR_VALIDATION | | 9 | SET_COLLATERAL_FACTOR_WITHOUT_PRICE | | 10 | SET_IMPLEMENTATION_OWNER_CHECK | | 11 | SET_LIQUIDATION_INCENTIVE_OWNER_CHECK | | 12 | SET_LIQUIDATION_INCENTIVE_VALIDATION | | 13 | SET_MAX_ASSETS_OWNER_CHECK | | 14 | SET_PENDING_ADMIN_OWNER_CHECK | | 15 | SET_PENDING_IMPLEMENTATION_OWNER_CHECK | | 16 | SET_PRICE_ORACLE_OWNER_CHECK | | 17 | SUPPORT_MARKET_EXISTS | | 18 | SUPPORT_MARKET_OWNER_CHECK |
介绍
Comptroller 是 Compound 协议的风险管理层;它决定了用户需要维持多少抵押品,以及是否可以(和多少)清算用户。每次用户与 cToken 交互时,Comptroller 都会被要求批准或拒绝交易。
Comptroller 将用户余额映射到价格(通过价格预言机),再映射到风险权重(称为[抵押系数]() )来进行判断。用户通过调用“[进入市场]()”和“[退出市场]()”,明确列出他们希望在风险评分中包括哪些资产。
架构
Comptroller 作为一个可升级的代理实现。Unitroller 将所有逻辑都代理给 Comptroller 实现,但存储值是在 Unitroller 上设置的。要调用 Comptroller 方法,请使用 Unitroller 地址上的 Comptroller ABI。
进入市场
进入一个市场的清单 -- 重复进入同一个市场,不是错误。要想在一个市场中提供抵押品或借贷,必须先进入市场。
Comptroller
1 function enterMarkets(address[] calldata cTokens) returns (uint[] memory)
- msg.sender : 应进入特定市场的账户。
- cTokens : 要进入的 cToken 市场地址。
- 返回值: 对于每个市场,返回一个错误代码,表示是否已进入市场。成功时为 0,否则返回[错误代码]()。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 CToken[] memory cTokens = new CToken[](2);
3 cTokens[0] = CErc20(0x3FDA...);
4 cTokens[1] = CEther(0x3FDB...);
5 uint[] memory errors = troll.enterMarkets(cTokens);
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const cTokens = [CErc20.at(0x3FDA...), CEther.at(0x3FDB...)];
3 const errors = await troll.methods.enterMarkets(cTokens).send({from: ...});
退出市场
退出一个市场 -- 退出当前没有进入的市场,这不是错误。退出市场将不计入账户流动性计算。
Comptroller
1 function exitMarket(address cToken) returns (uint)
- msg.sender : 应退出特定市场的账户。
- cTokens : 要退出的市场 cToken 地址。
- RETURN : 成功时为 0,否则返回[错误代码]()。
Solidity
1Comptroller troll = Comptroller(0xABCD...);
2uint error = troll.exitMarket(CToken(0x3FDA...));
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const errors = await troll.methods.exitMarket(CEther.at(0x3FDB...)).send({from: ...});
Get Assets In
获取一个账户目前进入的市场列表。要在市场上提供抵押品或借款,必须先进入市场。已进入的市场计入账户流动性计算中。
Comptroller
1 function getAssetsIn(address account) view returns (address[] memory)
- account : 应查询其进入市场清单的账户;
- RETURN : 目前进入的每个市场的地址。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 address[] memory markets = troll.getAssetsIn(0xMyAccount);
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const markets = await troll.methods.getAssetsIn(cTokens).call();
抵押系数
一个 cToken 的抵押系数(Collateral factors)可以在 0-90% 之间,代表账户通过铸造 cToken 获得的流动性(借款限额)的比例增加。
一般来说,大额资产或流动性较强的资产抵押系数较高,而小额资产或流动性较差的资产抵押系数较低。如果一项资产的抵押系数为 0%,则不能作为抵押品(或在清算时被扣押),但仍可借入。
随着市场情况的变化,可以通过 Compound 治理,提高(或降低)抵押品系数。
Comptroller
1 function markets(address cTokenAddress) view returns (bool, uint)
- cTokenAddress : 检查特定的 cToken 是否上市,并获得其抵押系数。
- RETURN : 值元祖(isListed, collateralFactorMantissa);isListed 代表审计是否承认这个cToken;collateralFactorMantissa 代表(抵押系数),按 1e18 比例乘以一个供给余额来确定可以借入多少资产。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 (bool isListed, uint collateralFactorMantissa) = troll.markets(0x3FDA...);
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const result = await troll.methods.markets(0x3FDA...).call();
3 const {0: isListed, 1: collateralFactorMantissa} = result;
获取账户流动性
在 Compound 协议中,账户流动性被定义为账户抵押品的预估以太值(供应余额乘以协议[抵押系数](),减去账户借款余额的总价值)。这些价值仅使用账户[已进入]()的市场计算。
没有正账户流动性的用户在没有提供更多的资产或者偿还未偿还的借款,使其账户流动性恢复到正值之前,没有能力提取或借入任何资产。
Comptroller
1 function getAccountLiquidity(address account) view returns (uint, uint, uint)
- account : 应计算其流动性的账户;
-
RETURN : 数组值(error、liquidity、shortfall)。成功时错误为0,否则为[错误代码]()。非零
liquidity 表示该账户有可用的账户流动性。非零 shortfall 表示该账户目前低于其抵押品要求,需要清算。 liquidity 和 shortfall 最多只有一个不为零。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 (uint error, uint liquidity, uint shortfall) = troll.getAccountLiquidity(msg.caller);
3 require(error == 0, "join the Discord");
4 require(shortfall == 0, "account underwater");
5 require(liquidity > 0, "account has excess collateral");
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const result = await troll.methods.getAccountLiquidity(0xBorrower).call();
3 const {0: error, 1: liquidity, 2: shortfall} = result;
关闭系数
可清偿借款的账户中,可在一次清算交易中偿还的借款的百分比,范围从 0% 到 100%。如果一个用户有多个借款资产,则 closeFactor 适用于任何单一的借款资产,而不是用户未清偿借款的总价值。
Comptroller
1 function closeFactorMantissa() view returns (uint)
- 返回值 : 关闭系数,按 1e18 比例计算,乘以未偿还的借款余额,确定可以结清多少借款。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 uint closeFactor = troll.closeFactorMantissa();
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const closeFactor = await troll.methods.closeFactoreMantissa().call();
清算奖励
给予清算人的额外抵押品,作为清算水下账户的奖励。例如,如果清算奖励是 1.1 ,那么清算人每关闭一个单位,就能额外获得借款人抵押品的 10%。
Comptroller
1 function liquidationIncentiveMantissa() view returns (uint)
- 返回值 : 清算奖励,按 1e18 比例计算,再乘以清算人的平仓借款金额,以确定可以扣押多少抵押品。
Solidity
1 Comptroller troll = Comptroller(0xABCD...);
2 uint closeFactor = troll.liquidationIncentiveMantissa();
Web3 1.0
1 const troll = Comptroller.at(0xABCD...);
2 const closeFactor = await troll.methods.liquidationIncentiveMantissa().call();
主要事件
Event | Description |
---|---|
MarketEntered(CToken cToken, address account) | 成功[进入市场]()时发生 |
MarketExited(CToken cToken, address account) | 成功[退出市场]()时发生 |
错误代码
Code | Name | Description |
---|---|---|
0 | NO_ERROR | 不算错误 |
1 | UNAUTHORIZED | The sender is not authorized to perform this action. |
2 | COMPTROLLER_MISMATCH | Liquidation cannot be performed in markets with different comptrollers. |
3 | INSUFFICIENT_SHORTFALL | The account does not have sufficient shortfall to perform this action. |
4 | INSUFFICIENT_LIQUIDITY | The account does not have sufficient liquidity to perform this action. |
5 | INVALID_CLOSE_FACTOR | The close factor is not valid. |
6 | INVALID_COLLATERAL_FACTOR | The collateral factor is not valid. |
7 | INVALID_LIQUIDATION_INCENTIVE | The liquidation incentive is invalid. |
8 | MARKET_NOT_ENTERED | The market has not been entered by the account. |
9 | MARKET_NOT_LISTED | The market is not currently listed by the comptroller. |
10 | MARKET_ALREADY_LISTED | An admin tried to list the same market more than once. |
11 | MATH_ERROR | A math calculation error occurred. |
12 | NONZERO_BORROW_BALANCE | The action cannot be performed since the account carries a borrow balance. |
13 | PRICE_ERROR | The comptroller could not obtain a required price of an asset. |
14 | REJECTION | The comptroller rejects the action requested by the market. |
15 | SNAPSHOT_ERROR | The comptroller could not get the account borrows and exchange rate from the market. |
16 | TOO_MANY_ASSETS | Attempted to enter more markets than are currently supported. |
17 | TOO_MUCH_REPAY | Attempted to repay more than is allowed by the protocol. |
错误信息
Code | Name |
---|---|
0 | ACCEPT_ADMIN_PENDING_ADMIN_CHECK |
1 | ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK |
2 | EXIT_MARKET_BALANCE_OWED |
3 | EXIT_MARKET_REJECTION |
4 | SET_CLOSE_FACTOR_OWNER_CHECK |
5 | SET_CLOSE_FACTOR_VALIDATION |
6 | SET_COLLATERAL_FACTOR_OWNER_CHECK |
7 | SET_COLLATERAL_FACTOR_NO_EXISTS |
8 | SET_COLLATERAL_FACTOR_VALIDATION |
9 | SET_COLLATERAL_FACTOR_WITHOUT_PRICE |
10 | SET_IMPLEMENTATION_OWNER_CHECK |
11 | SET_LIQUIDATION_INCENTIVE_OWNER_CHECK |
12 | SET_LIQUIDATION_INCENTIVE_VALIDATION |
13 | SET_MAX_ASSETS_OWNER_CHECK |
14 | SET_PENDING_ADMIN_OWNER_CHECK |
15 | SET_PENDING_IMPLEMENTATION_OWNER_CHECK |
16 | SET_PRICE_ORACLE_OWNER_CHECK |
17 | SUPPORT_MARKET_EXISTS |
18 | SUPPORT_MARKET_OWNER_CHECK |
区块链技术网。
- 发表于 2021-02-13 13:26
- 阅读 ( 128 )
- 学分 ( 0 )
- 分类:DeFi
- 专栏:Compound 研究
评论