Compound 治理

Governance开发者文档

介绍

Compound 协议由 COMP Token 持有者管理和升级,使用三个不同的组件; COMP Token、治理模块(Governor Alpha)和 Timelock。这些合约一起,允许社区通过 cToken 或 Comproller 的管理功能提出、投票和实时更改。提案可以包括调整利率模型,到增加对新资产的支持等改变。

任何授权超过 10 万 COMP Token 的地址都可以提出治理活动,这些活动都是可执行的代码。提案产生后,社区可以在 3 天的投票期内提交投票。如果投票获得多数、且至少 40 万票以上,就会在 Timlock 中排队,2 天后可以实施。

image.png

COMP

COMP 是一个 代币,允许所有者将投票权委托给任何地址,包括自己的地址。所有者的代币余额会自动调整被委托人的投票权。

委托(Delegate)

将发送者的投票数委托给被委托人。用户每次可以委托给一个地址,被委托人的投票数相当于用户账号的 COMP 代币余额。投票将从当前区块开始进行委托,直到发送者再次委托或者转移其 COMP。

COMP

1 function delegate(address delegatee)
  • delegatee : 发送者希望委托投票的地址;
  • msg.sender : 试图委托投票的 COMP 代币持有者的地址;
  • 返回值 : 无返回值,错误时恢复。

Solidity

1 Comp comp = Comp(0x123...); // contract address
2 comp.delegate(delegateeAddress);

Web3 1.2.6

1 const tx = await comp.methods.delegate(delegateeAddress).send({ from: sender });

签名委托(Delegate By Signature)

Delegate 投票从签名者到被委托人。这种方法与 Delegate 的目的相同,但它可以离线签名参与Compound 治理投票授权。有关如何创建离线签名的更多细节,请查看 。

COMP

1 function delegateBySig(address delegateeAddress,uint256 nonce,uint256 expiry,uint256 v,uint256 r,uint256 s);
  • delegatee : 发送者希望委托投票的地址;
  • nonce : 合约状态要求与签名相匹配。这一点可以从合同的公共 nonce 映射中检索;
  • expiry : 签名过期时间。以 unix epoch (uint) 后的秒数表示的区块时间戳;
  • v : 签名恢复字节;
  • r : ECDSA 签名对的一部分;
  • s : ECDSA 签名对的一部分;
  • 返回值 : 无,错误时恢复。

Solidity

1 Comp comp = Comp(0x123...); // contract address
2 comp.delegateBySig(delegateeAddress, nonce, expiry, v, r, s);

Web3 1.2.6

1 const tx = await comp.methods.delegateBySig(delegateeAddress, nonce, expiry, v, r, s).send({});

获取当前投票数

获取一个账户当前区块的票数余额。

COMP

1 function getCurrentVotes(address account) returns (uint96)
  • account : 检索票数的账户地址;
  • RETURN : 票数(整型)。

Solidity

1 Comp comp = Comp(0x123...); // contract address
2 uint votes = comp.getCurrentVotes(0xabc...);

Web3 1.2.6

1 const account = '0x123...'; // contract address
2 const votes = await comp.methods.getCurrentVotes(account).call();

获取先前投票数

获取一个账户在特定区块上的投票数。传入的区块高度必须是最终确定的区块,否则函数将revert。

COMP

1 function getPriorVotes(address account, uint blockNumber) returns (uint96)
  • account : 检索先前的投票数的账户地址;
  • blockNumber : 取回之前的票数的区块高度;
  • 返回值 : 先前投票数;

Solidity

1 Comp comp = Comp(0x123...); // contract address
2 uint priorVotes = comp.getPriorVotes(account, blockNumber);

Web3 1.2.6

1 const priorVotes = await comp.methods.getPriorVotes(account, blockNumber).call();

Governor Alpha

Governor Alpha 是协议的治理模块;它允许超过 10 万 COMP 代币的地址提出修改建议。在提案开始时,手握投票权(通过调用 getpriorvotes 方法)的地址可以在 3 天的投票期内提交投票。如果提取被投了多数,且至少有 40 万票,则会在 Timelock 中排队,2 两天后实施。

Govern Alpha 合约包含一个守卫者地址,由 Compound 团队控制,可以取消提案,或在紧急情况下禁用治理模块。在最初的沙盒期后,守护者可以放弃权利,标志着 COMP 代币持有者开始完全控制。

法定投票数(Quorum Votes)

成功支持一项提案的最低票数要求。

Governor Alpha

1 function quorumVotes() public pure returns (uint)
  • 返回值 : 成功支持一项提案的最低票数。

Solidity

1GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint quorum = gov.quorumVotes();

Web3 1.2.6

1 const quorum = await gov.methods.quorumVotes().call();

提案门槛(Proposal Threshold)

账户创建一个提案所需的最低票数;

Governor Alpha

1 function proposalThreshold() returns (uint)
  • 返回值ETURN : 账户创建一个提案所需的最低票数。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint threshold = gov.proposalThreshold();

Web3 1.2.6

1 const threshold = await gov.methods.proposalThreshold().call();

提案最大操作量(Proposal Max Operations)

提案中可以包含的最大操作数量。操作是指提案成功并执行时将进行的函数调用。

Governor Alpha

1 function proposalMaxOperations() returns (uint)
  • 返回值 : 提案中可以包含的最大操作数量。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint operations = gov.proposalMaxOperations();

Web3 1.2.6

1 const operations = await gov.methods.proposalMaxOperations().call();

投票延迟(Voting Delay)

在对一个提案投票前需要等到的以太坊区块数。当创建一个提案时,该值会被添加到当前区块高度上。

Governor Alpha

1function votingDelay() returns (uint)
  • 返回值:在对一个提案投票前需要等到的以太坊区块数。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint blocks = gov.votingDelay();

Web3 1.2.6

1 const blocks = await gov.methods.votingDelay().call();

投票期(Voting Period)

以以太坊区块为单位,对提案进行投票的持续时间。

Governor Alpha

1 function votingPeriod() returns (uint)
  • RETURN : 对提案进行投票的持续时间。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint blocks = gov.votingPeriod();

Web3 1.2.6

1 const blocks = await gov.methods.votingPeriod().call();

提案(Propose)

创建一个提案来改变协议。比如:一个提案能在 Comproller 上设置 cToken 的利率模型或者风险参数。

提案将委托投票人进行投票表决。如果在投票期结束前有足够的支持,提案将被自动颁布。已颁布的提案将在 Compound Timelock 合约中排队并执行。

发送者在紧邻的前一个区块中持有的 COMP 代币必须超过当前的提案阈值(proposalThreshold)。如果阈值是 10 万 COMP 代币,则发送者必须被委托超过所有 COMP 的 1% 才能创建一个提案。提案最多有 10 个操作(基于 proposalMaxOperations() )。

如果提案者当前有待处理或活动中的提案,则他们不能创建另一个提案。不可能在同一个区块中排队两个相同的操作(由于 Timelock 中的限制)。因此一个提案中的操作必须是唯一的,共享一个相同操作的唯一提案必须在不同的区块中排队。

Governor Alpha

1 function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) returns (uint)
  • targets : 在提案执行过程中,将被调用的目标地址的有序列表。这个数组的长度必须和这个方法中所有其他数组参数的长度相同;
  • values : 在提案执行过程中要传递给调用的值(即msg.value)的有序列表。这个数组的长度必须和这个方法中所有其他数组参数的长度相同;
  • signatures : 提案执行过程中要传递的方法签名的有序列表。这个数组的长度必须和这个方法中所有其他数组参数的长度相同;
  • calldatas : 在提案执行过程中要传递给每个方法调用的数据的有序列表。这个数组必须和这个方法中所有其他数组参数的长度相同;
  • description : 对该提案的可读性说明及其将作出的修改;
  • 返回值 : 新创建的提案 ID。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint proposalId = gov.propose(targets, values, signatures, calldatas, description);

Web3 1.2.6

1const tx = gov.methods.propose(targets, values, signatures, calldatas, description).send({ from: sender });

队列(Queue)

提案通过后,任何地址可以调用 queue 方法将提案转移到 Timelock 队列中。提案只有在成功通过后,才能被排队。

Governor Alpha

1 function queue(uint proposalId)
  • proposalId : 已通过的提案 ID;
  • 返回值 : 无,错误时将 revert。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 gov.queue(proposalId);

Web3 1.2.6

1 const tx = gov.methods.queue(proposalId).send({ from: sender });

执行(Execute)

在 Timelock 延迟期之后,任何账户都可以调用 execu 方法将提案中的更改应用到目标合约中。这将调用提案中描述的每一个操作。

这个功能是可支付(payable)的,所以 Timelock 合约可以调用提案中选择的可支付功能。例如,A 提案可以 像cETH 一样在市场上添加准备金,设置 cToken 的利率模型,或者在 Comptroller上设置风险参数。

Governor Alpha

1function execute(uint proposalId) payable returns (uint)
  • proposalId : 要执行的成功提案 ID;
  • 返回值 : 无,错误时将 revert。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 gov.execute(proposalId).value(999).gas(999)();

Web3 1.2.6

1 const tx = gov.methods.execute(proposalId).send({ from: sender, value: 1 });

取消(Cancel)

取消尚未执行的提案。除非提案人没有维持创建提案所需的委托量,否则监护人是唯一可以执行取消的人。如果提案人的委托人数没有超过提案的阈值,任何人都可以取消该提案。

Governor Alpha

1 function cancel(uint proposalId)
  • proposalId : 要取消的提案 ID。提案不能重复取消。
  • RETURN : 无,错误时 revert。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 gov.cancel(proposalId);

Web3 1.2.6

1 const tx = gov.methods.cancel(proposalId).send({ from: sender });

获取操作(Get Actions)

获取所选提案的操作列表。传递一个提案 ID,获取该提案的目标对象、值、签名和调用数据。

Governor Alpha

1 function getActions(uint proposalId) returns (uint proposalId) public view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas)
  • proposalId : 拟获取操作的提案 ID。
  • RETURN : 如果提案 ID 非法,则 revert 。否则成功时返回以下 4 个 参考信息:
    1. 提案调用的合约地址数组;
    2. 提案中使用的值 - 无符号整数数组;
    3. 提案签名的字符串数组;
    4. 提案的 calldata 字节数组。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 uint proposalId = 123;
3 (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) = gov.getActions(proposalId);

Web3 1.2.6

1 const {0: targets, 1: values, 2: signatures, 3: calldatas} = gov.methods.getActions(proposalId).call();

获取回执(Get Receipt)

获得指定投票者的提案选票。

Governor Alpha

1 function getReceipt(uint proposalId, address voter) returns (Receipt memory)
  • proposalId : 提案ID,以获取投票者的选票收据;
  • voter : 提案投票者的账户地址;
  • RETURN : 错误时 revert。成功时返回投票者地址的选票收据结构数据。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 Receipt ballot = gov.getReceipt(proposalId, voterAddress);

Web3 1.2.6

1 const proposalId = 11;
2 const voterAddress = '0x123...';
3 const result = await gov.methods.getReceipt(proposalId, voterAddress).call();
4 const { hasVoted, support, votes } = result;

获取提案状态(State)

获取指定提案的提案状态。返回值 ProposalState 是一个 Governor Alpha 合约中定义的枚举类型。

Governor Alpha

1 function state(uint proposalId) returns (ProposalState)
  • proposalId : 提案ID,以获得其状态;
  • 返回值 : 枚举类型 ProposalState。类型有:Pending(等待中)、Active(活动中)、

    Canceled(已取消)、Defeated(已败北)、 Succeeded(已成功)、Queued(已排队)、Expired(已过期)和Executed(已执行)。

Solidity

1 overnorAlpha gov = GovernorAlpha(0x123...); // contract address
2 GovernorAlpha.ProposalState state = gov.state(123);

Web3 1.2.6

1 const proposalStates = ['Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'];
2 const proposalId = 123;
3 result = await gov.methods.state(proposalId).call();
4 const proposalState = proposalStates[result];

投票(Cast Vote)

对某项提案进行投票。该账户的表决权重取决于该账户在提案开始生效时的表决权重。

Governor Alpha

1 function castVote(uint proposalId, bool support)
  • proposalId : 提案ID,以进行投票;
  • support : 布尔值,赞同提案为 true ,反对为 false;
  • RETURN : 无返回值,错误时 revert。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 gov.castVote(proposalId, true);

Web3 1.2.6

1 const tx = gov.methods.castVote(proposalId, false).send({ from: sender });

通过签名投票(Cast Vote By Signature)

对某项提案进行投票。该账户的投票权重由该账户在该提案状态生效时的投票权重决定。此方法的目的与 "cast vote "相同,但它可以让脱机签名参与 Compound 治理投票。有关如何创建离线签名的详细信息,请查看 EIP-712。

Governor Alpha

1 function castVoteBySig(uint proposalId, bool support, uint8 v, bytes32 r, bytes32 s)
  • proposalId : 提案ID,以进行投票;
  • support : 布尔值,赞同提案为 true ,反对为 false;
  • v : 签名恢复字节;
  • r : ECDSA 签名对的一部分;
  • s : ECDSA 签名对的一部分;
  • 返回值 : 无,错误时恢复。

Solidity

1 GovernorAlpha gov = GovernorAlpha(0x123...); // contract address
2 gov.castVoteBySig(proposalId, true, v, r, s);

Web3 1.2.6

1 const tx = await gov.methods.castVoteBySig(proposalId, false, v, r, s).send({});

时间锁(Timelock)

每个 cToken 合约和 Comptroller 合约都允许 Timelock 地址修改。Timelock 合约可以修改系统参数、逻辑和合约,以 "延迟时间、选择退出 " 的升级模式进行修改。

Timelock 有一个 2 天的最小延迟时间硬性规定,这是治理行动的最小通知时间。每项拟采取的治理行动,都会在公告后至少 2 天内公布。重大升级,如变更风险系统等,可能会有 14 天的延迟时间。

时间锁由治理模块控制;待定和已完成的治理行动可以在上监控。

暂停守护者(Pause Guardian)

Comptroller 合约指定了一个能够禁用协议功能的暂停守护者地址。暂停守护者只有在出现不可预见的漏洞时才会使用,暂停守护者只有一种能力:禁用一组选定的功能。Mint、Borrow、Borrow、Transfer 和 Liquidate。暂停守护者不能解除一个动作,也不能阻止用户调用赎回、偿还借款以平仓和退出协议。

目前,Compound 团队控制了暂停守护者的地址。

本文参与2022世界杯预选赛赛程直播社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2021-03-04 13:47
  • 阅读 ( 561 )
  • 学分 ( 5 )
  • 分类:DeFi
  • 专栏:Compound 研究

0 条评论

请先 登录 后评论
七哥
七哥

区块链创业者

25 篇文章, 4297 学分