文章详细介绍了ERC20 Votes的功能和实现方式,重点解释了ERC5805和ERC6372标准的功能及其在ERC20 Votes中的应用。文章还对比了ERC20 Votes与ERC20 Snapshot的区别,并讨论了何时使用哪种标准。
ERC20 投票
需要假设你已了解 ERC20 Snapshot 的知识,请参阅我们关于 ERC20 Snapshot 的文章以获取主题介绍。ERC20 投票并不实际处理投票表决,它仍然是一个常规的 ERC20 代币,具有快照和委托投票能力。投票通常由治理合约处理。委托意味着一个地址可以将其投票权借给另一个地址,而无需将其代币转移到该地址。
与 ERC20 Snapshot 不同,它并不保留代币余额的快照,而是保留地址的投票权快照。这有几个动机:
ERC20 投票继承自 ERC20、ERC6372 和 ERC5805。这意味着它具有 ERC20 代币所有功能以及下文描述的附加属性。
getVotes(address delegate)
这个函数接受一个账户的地址,并返回它拥有的总投票权。如果其他地址已将他们的投票权委托给它,这可能大于 balanceOf(delegate)。
delegate(address delegatee)
这个函数允许 msg.sender
将他们的投票权委托给 delegatee,且 delegatee 将代表 msg.sender
投票。请注意,代币不会转移给 delegatee,仅投票权会转移。可以通过再次调用 delegate,使用不同的 delegatee 或 address(0)
,在任何时候更改或撤销委托。委托是全有或全无。没有选项可以委托部分投票权。重要的是要注意,地址必须先委托给自己才能计算它的投票。这一奇怪设计是出于Gas效率的原因。
delegates(address account)
这个函数返回 account
参数所委托的投票权的账户。
delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
函数 delegateBySig 允许用户通过无Gas费的交易委托投票权,并让另一个账户支付Gas费用并执行交易。过期会设置委托有效的时间,v、r 和 s 是椭圆曲线数字签名的组成部分。这个签名需要以 EIP 712 格式进行。内部,合约会按地址递增 nonce,如下所述。
nonces(address account)
签名需要 nonce 来防止重放攻击,因此该函数暴露了内部 nonce 跟踪。这使得签名方可以知道下一个应该签署的值。
getPastVotes(account, timepoint)
正如我们在 ERC20 Snapshot 文章 中讨论的那样,除非账户余额被快照,否则可能出现双重投票攻击。这是投票合约会查看过去快照的地方。与 ERC20 快照不同,快照并不是由于一个地址调用快照函数而触发。快照是当以下任何事件发生时,按账户触发的:
每当发生这些事件时,包含投票权和时间戳的结构会附加到存储该用户投票权历史的数组中。与 ERC20 Snapshot 一样,ERC20 投票将在时间戳上进行二分查找,以查找时间点之后的最早检查点。将在该时间点返回投票权。这意味着,与 ERC20 快照不同,没有“全局”快照 ID。如果你想查询过去的某个时间点,你可以选择一个时间戳或区块号,并将其作为“时间点”提供给函数。
ERC5805 有两个事件,它们的名称正如字面意思:DelegateChange
和 DelegateVotesChagned
。
在本文中,我们解释了 ERC20 投票,但这并不意味着 ERC5805 必须是一种可替代代币。它可以是 NFT,甚至是以其他方式管理的投票记录,例如一个中心化实体将投票分配给地址,但想要保持投票权分配的不可变历史。
我们假设合约正在使用 block.timestamp
来记录检查点的方式。然而,一些合约可能使用 block.number
或这些全局变量的某种单调递增函数。ERC6372 是一个标准,允许合约查询它所使用的“时钟”的类型。它有两个函数:
clock()
这个函数返回一个 uint48,可能是区块号或区块时间戳或这些的某种函数。选择 uint48 是因为它有足够的位数来表示所有合理的时间表示,而区块号在未来比人类记录的历史更远。
CLOCK_MODE()
是的,蛇形命名法的全大写函数在 Solidity 中非常不寻常,但这就是 EIP 所指定的内容。这个函数返回一个字符串,告诉读者时钟使用的单位。
mode=blocknumber&from=default
。这意味着它仅使用 block.number
变量。如果它起始于其他区块,必须指定链 ID 以及起始的区块号。例如,Avalanche 的链 ID 为 43114,因此如果它起始于第 100 个区块,CLOCK_MODE()
的响应将是 mode=blocknumber&from=43114:100
。EIP 6372 没有事件。有关更多详细信息,请参见 EIP,该文档实际上是相当易读的。请注意,这个 EIP 尚未最终确定。
使用 ERC20 快照还是投票的选择主要取决于是否需要委托投票,或者更抽象地说,某些 ERC20 代币所赋予的权利。
请查看我们的高级 Solidity 编程训练营 以及我们其他 区块链训练营 产品。最初发布于 2023 年 2 月 23 日
- 原文链接: rareskills.io/post/erc20...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!