本文档介绍了用于链上治理的 Governor 合约,它是一个模块化的系统,允许部署类似于 Compound 的 Governor Alpha & Bravo 的链上投票协议。该系统具有高度的可定制性,通过选择不同的模块(如投票模块、计数模块、时间锁扩展等)和实现特定的虚拟函数,可以满足各种治理需求。
此文档在 https://docs.openzeppelin.com/contracts/api/governance 上查看效果更佳 |
此目录包含链上治理的基本要素。
Governor 合约的这个模块化系统允许部署类似于 Compound 的 Governor Alpha & Bravo 以及更高级的链上投票协议,因为它能够轻松自定义协议的多个方面。
为了获得指导体验,请使用 Contracts Wizard 设置你的 Governor 合约。<br>有关书面演练,请查看我们的 如何设置链上治理 指南。 |
Governor
: 包含所有逻辑和基本要素的核心合约。它是抽象的,需要选择下面每个模块中的一个,或者自定义的模块。投票模块决定投票权力的来源,有时也决定法定人数。
GovernorVotes
:从 IVotes
合约中提取投票权重。
GovernorVotesQuorumFraction
:与 GovernorVotes
结合使用,将法定人数设置为总 token 供应量的一部分。
GovernorVotesSuperQuorumFraction
:将 GovernorSuperQuorum
与 GovernorVotesQuorumFraction
结合使用,将超级法定人数设置为总 token 供应量的一部分。
计数模块决定有效的投票选项。
GovernorCountingSimple
:简单的投票机制,有 3 个投票选项:反对、赞成和弃权。
GovernorCountingFractional
:一个更模块化的投票系统,允许用户仅使用其部分投票权进行投票,并在 3 个不同选项(反对、赞成和弃权)之间任意分配该权重。
GovernorCountingOverridable
:GovernorCountingSimple
的扩展版本,允许被委托人在投票进行时覆盖其委托人。必须与 VotesExtended
结合使用。
时间锁扩展为治理决策的执行增加了一个延迟。工作流程被扩展为在执行之前需要一个 queue
步骤。使用这些模块,提案由外部时间锁合约执行,因此时间锁必须持有被治理的资产。
GovernorTimelockAccess
:与 AccessManager
的实例连接。这允许管理器强制执行的限制(和延迟)被 Governor 考虑,并集成到 AccessManager 的 "schedule + execute" 工作流程中。
GovernorTimelockControl
:与 TimelockController
的实例连接。除了 Governor 本身之外,还允许多个提议者和执行者。
GovernorTimelockCompound
:与 Compound 的 Timelock
合约的实例连接。
其他扩展可以以多种方式自定义行为或界面。
GovernorStorage
:将提案详细信息存储在链上,并提供提案的可枚举性。这对于某些 L2 链可能很有用,因为与 calldata 相比,存储成本较低。
GovernorSettings
:以可以通过治理提案更新的方式管理某些设置(投票延迟、投票期持续时间和提案阈值),而无需升级。
GovernorPreventLateQuorum
:确保在达到法定人数后有一个最短的投票期,作为针对大型投票者的安全保护。
GovernorProposalGuardian
:添加一个提案 guardian,可以在提案生命周期的任何阶段取消提案——如果未设置 guardian,则此权限将传递给提案人。
GovernorSuperQuorum
:Governor
的扩展,具有超级法定人数。符合超级法定人数(并且大多数票数为赞成票)的提案将在提案截止日期之前进入 Succeeded
状态。
除了模块和扩展之外,核心合约还需要实现一些虚拟函数以满足你的特定规范:
votingDelay()
:自提案提交到投票权固定且投票开始的延迟(以 ERC-6372 时钟为单位)。这可以用于在发布提案后强制延迟,以便用户购买 token 或委托其投票。
votingPeriod()
:自提案开始到投票结束的延迟(以 ERC-6372 时钟为单位)。
quorum(uint256 timepoint)
:提案成功所需的法定人数。此函数包含一个 timepoint
参数(参见 ERC-6372),因此法定人数可以随着时间的推移而调整,例如,跟随 token 的 totalSupply
。
Governor 合约的函数不包含访问控制。如果你想限制访问,你应该通过重载特定函数来添加这些检查。其中,Governor._cancel 默认是内部的,如果需要此功能,你将必须自己公开它(使用正确的访问控制机制)。 |
IGovernor
import "@openzeppelin/contracts/governance/IGovernor.sol";
Governor
核心的接口。
事件参数缺少 indexed 关键字,以与 GovernorBravo 事件兼容。<br>加粗动事件参数会影响事件的解码方式,可能会破坏现有的索引器。 |
函数
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IERC6372
IERC165
事件
错误
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
name() → string
externalgovernor 实例的名称(用于构建 EIP-712 域分隔符)。
version() → string
externalgovernor 实例的版本(用于构建 EIP-712 域分隔符)。默认值:"1"
COUNTING_MODE() → string
externalcastVote
的可能 support
值的描述,以及这些选票的计算方式,旨在
供 UI 使用,以显示正确的投票选项并解释结果。该字符串是一个 URL 编码的键值对序列,每个键值对描述一个方面,例如 support=bravo&quorum=for,abstain
。
有 2 个标准键:support
和 quorum
。
support=bravo
指的是投票选项 0 = 反对,1 = 赞成,2 = 弃权,如 GovernorBravo
中所示。
quorum=bravo
意味着只有赞成票才计入法定人数。
quorum=for,abstain
意味着赞成票和弃权票都计入法定人数。
如果计数模块使用编码的 params
,它应该将其包含在 params
键下,并使用描述该行为的唯一名称。例如:
params=fractional
可能指的是在赞成/反对/弃权之间按比例分配选票的方案。
params=erc721
可能指的是将特定的 NFT 委托进行投票的方案。
该字符串可以被标准的<br>加粗URLSearchParams <br>加粗JavaScript 类解码。 |
hashProposal(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
external哈希函数,用于从提案详细信息中(重新)构建提案 ID。
对于所有链下和外部调用,请使用 getProposalId 。 |
getProposalId(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
external用于从提案详细信息中获取提案 ID 的函数。
state(uint256 proposalId) → enum IGovernor.ProposalState
external提案的当前状态,遵循 Compound 的惯例
proposalThreshold() → uint256
external投票者成为提案者所需的票数。
proposalSnapshot(uint256 proposalId) → uint256
external用于检索用户的选票和法定人数的时间点。如果使用区块号(如 Compound 的 Comp),则快照在此区块结束时执行。因此,对此提案的投票从下一个区块的开始开始。
proposalDeadline(uint256 proposalId) → uint256
external投票结束的时间点。如果使用区块号,则投票在此区块结束时结束,因此可以在此区块期间投票。
proposalProposer(uint256 proposalId) → address
external创建提案的帐户。
proposalEta(uint256 proposalId) → uint256
external排队的提案变为可执行的时间("ETA")。与 proposalSnapshot
和
proposalDeadline
不同,这不使用 governor 时钟,而是依赖于执行者的时钟,该时钟可能不同。在大多数情况下,这将是一个时间戳。
proposalNeedsQueuing(uint256 proposalId) → bool
external提案在执行之前是否需要排队。
votingDelay() → uint256
external提案创建和投票开始之间的延迟。此持续时间以哪个单位表示取决于此合约使用的时钟(参见 ERC-6372)。
可以增加此延迟,以便用户在提案开始投票之前有时间购买投票权或委托它。
虽然此接口返回一个 uint256,但时间点以 uint48 存储,遵循 ERC-6372 时钟类型。<br>加粗果后续要参与计算,该值应适合 uint48(添加到当前时钟时)。请参见 IERC6372.clock 。 |
votingPeriod() → uint256
external投票开始和投票结束延迟。此持续时间以哪个单位表示取决于此合约使用的时钟 (参见 ERC-6372)。
votingDelay 可以延迟投票的开始。与投票延迟相比,设置投票<br>加粗需要考虑持续时间。 |
此值在提交提案时存储,以便对该值的可能更改不影响<br>加粗已提交的提案。用于保存它的类型是 uint32。因此,虽然此<br>加粗接口返回一个 uint256,但它返回的值应该适合 uint32。 |
quorum(uint256 timepoint) → uint256
external提案成功所需的最低投票数。
timepoint 参数对应于用于计算选票的快照。这允许根据诸如Token在该时间点的 totalSupply 之类的值缩放<br>加粗totalSupply(请参见 ERC20Votes )。 |
getVotes(address account, uint256 timepoint) → uint256
externalaccount
在特定 timepoint
的投票权。
注意:这可以通过多种方式实现,例如通过从一个(或多个)ERC20Votes
Token中读取委托的余额。
getVotesWithParams(address account, uint256 timepoint, bytes params) → uint256
externalaccount
在特定 timepoint
的投票权,给定附加的编码参数。
hasVoted(uint256 proposalId, address account) → bool
external返回 account
是否已在 proposalId
上投票。
propose(address[] targets, uint256[] values, bytes[] calldatas, string description) → uint256 proposalId
external创建一个新提案。在 IGovernor.votingDelay
指定的延迟后开始投票,并持续
IGovernor.votingPeriod
指定的持续时间。
发出一个 ProposalCreated
事件。
在提案创建和执行之间,Governor 和 targets 的状态可能会更改。<br>加粗可能是由于第三方对目标合约的操作或其他 governor 提案造成的。<br>加粗例如,此合约的余额可能会更新,或者其访问控制权限可能会被修改,<br>加粗可能会危及提案成功执行的能力(例如,governor 没有足够的<br>加粗价值来支付具有多个转账的提案)。 |
queue(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256 proposalId
external排队一个提案。一些 governor 要求在执行之前执行此步骤。如果排队不是必需的,则此函数可能会还原。 排队提案要求达到法定人数、投票成功并且达到截止日期。
发出一个 ProposalQueued
事件。
execute(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256 proposalId
external执行一个成功的提案。这要求达到法定人数、投票成功并且达到截止日期。根据 governor 的不同,可能还需要对提案进行排队并且经过一些延迟。
发出一个 ProposalExecuted
事件。
一些模块可以修改执行的要求,例如通过添加额外的时间锁。 |
cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256 proposalId
external取消一个提案。提案可以由提案人取消,但只能在其处于 Pending 状态时取消,即在投票开始之前。
发出一个 ProposalCanceled
事件。
castVote(uint256 proposalId, uint8 support) → uint256 balance
external投票
发出一个 VoteCast
事件。
castVoteWithReason(uint256 proposalId, uint8 support, string reason) → uint256 balance
external带理由的投票
发出一个 VoteCast
事件。
castVoteWithReasonAndParams(uint256 proposalId, uint8 support, string reason, bytes params) → uint256 balance
external使用理由和附加的编码参数进行投票
发出一个 VoteCast
或 VoteCastWithParams
根据 params 的长度发出事件。
castVoteBySig(uint256 proposalId, uint8 support, address voter, bytes signature) → uint256 balance
external使用投票者的签名进行投票,包括 ERC-1271 签名支持。
发出一个 VoteCast
事件。
castVoteWithReasonAndParamsBySig(uint256 proposalId, uint8 support, address voter, string reason, bytes params, bytes signature) → uint256 balance
external使用投票者的签名,包括 ERC-1271 签名支持,对带有理由和附加编码参数的投票进行投票。
发出一个 VoteCast
或 VoteCastWithParams
根据 params 的长度发出事件。
ProposalCreated(uint256 proposalId, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 voteStart, uint256 voteEnd, string description)
event在创建提案时发出。
ProposalQueued(uint256 proposalId, uint256 etaSeconds)
event在提案排队时发出。
ProposalExecuted(uint256 proposalId)
event在提案执行时发出。
ProposalCanceled(uint256 proposalId)
event在提案取消时发出。
VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason)
event在没有参数的情况下投出选票时发出。
注意:support
值应被视为存储桶。他们的解释取决于所使用的投票模块。
VoteCastWithParams(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason, bytes params)
event在有参数的情况下投出选票时发出。
注意:support
值应被视为存储桶。他们的解释取决于所使用的投票模块。
params
是附加的编码参数。它们的解释还取决于所使用的投票模块。
GovernorInvalidProposalLength(uint256 targets, uint256 calldatas, uint256 values)
error空提案或提案调用的参数长度不匹配。
GovernorAlreadyCastVote(address voter)
error选票已被投出。
GovernorDisabledDeposit()
error在此合约中禁用 token 存款。
GovernorOnlyExecutor(address account)
erroraccount
不是治理执行者。
GovernorNonexistentProposal(uint256 proposalId)
errorproposalId
不存在。
GovernorUnexpectedProposalState(uint256 proposalId, enum IGovernor.ProposalState current, bytes32 expectedStates)
error提案的当前状态不是执行操作所需的。
expectedStates
是一个位图,其中为每个 ProposalState 枚举位置启用位
从右到左计数。
如果 expectedState 是 bytes32(0) ,则预计提案不处于任何状态(即不存在)。<br>加粗这是一个预计要取消设置的提案已经被初始化(重复提案)的情况。 |
请参见 Governor._encodeStateBitmap
。
GovernorInvalidVotingPeriod(uint256 votingPeriod)
error设置的投票期不是有效期限。
GovernorInsufficientProposerVotes(address proposer, uint256 votes, uint256 threshold)
errorproposer
没有创建提案所需的选票。
GovernorRestrictedProposer(address proposer)
error不允许 proposer
创建提案。
GovernorInvalidVoteType()
error使用的投票类型对于相应的计数模块无效。
GovernorInvalidVoteParams()
error计数模块不支持提供的参数缓冲区。
GovernorQueueNotImplemented()
error未为此 governor 实现队列操作。应直接调用 Execute。
GovernorNotQueuedProposal(uint256 proposalId)
error提案尚未排队。
GovernorAlreadyQueuedProposal(uint256 proposalId)
error提案已排队。
GovernorInvalidSignature(address voter)
error对于预期的 voter
,提供的签名无效。
如果 voter
是一个合约,则使用 IERC1271.isValidSignature
时签名无效。
GovernorUnableToCancel(uint256 proposalId, address account)
error给定的 account
无法取消具有给定 proposalId
的提案。
Governor
import "@openzeppelin/contracts/governance/Governor.sol";
治理系统的核心,旨在通过各种模块进行扩展。
此合约是抽象的,需要通过各种模块实现多个函数:
计数模块必须实现 _quorumReached
, _voteSucceeded
和 [_countVote
](https://- proposalProposer(proposalId)
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
onlyGovernance()
modifier限制一个函数,使其只能通过治理提案执行。例如,GovernorSettings
中的治理参数设置器使用此修饰符进行保护。
治理执行地址可能与 Governor 自身的地址不同,例如它可以是一个时间锁。这可以通过重写 _executor
来由模块进行自定义。执行者只能在 governor 的 execute
函数执行期间调用这些函数,而不能在任何其他情况下调用。因此,例如,额外的时间锁提议者无法在不经过治理协议的情况下更改治理参数(自 v4.6 起)。
constructor(string name_)
internalreceive()
external接收 ETH 的函数,该 ETH 将由 governor 处理(如果执行者是第三方合约,则禁用)
supportsInterface(bytes4 interfaceId) → bool
publicname() → string
public参见 IGovernor.name
。
version() → string
publichashProposal(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
public提案 id 通过哈希 ABI 编码的 targets
数组、values
数组、calldatas
数组和 descriptionHash(bytes32 本身是描述字符串的 keccak256 哈希)来生成。此提案 id 可以从提案数据中生成,提案数据是 ProposalCreated
事件的一部分。它甚至可以在提案提交之前提前计算出来。
请注意,chainId 和 governor 地址不是提案 id 计算的一部分。因此,如果相同的提案(具有相同的操作和相同的描述)在多个网络上的多个 governor 上提交,则将具有相同的 id。这也意味着为了(在同一 governor 上)执行相同的操作两次,提议者将必须更改描述,以避免提案 id 冲突。
getProposalId(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
publicstate(uint256 proposalId) → enum IGovernor.ProposalState
public参见 IGovernor.state
。
proposalThreshold() → uint256
public参见 IGovernor.proposalThreshold
。
proposalSnapshot(uint256 proposalId) → uint256
public参见 IGovernor.proposalSnapshot
。
proposalDeadline(uint256 proposalId) → uint256
public参见 IGovernor.proposalDeadline
。
proposalProposer(uint256 proposalId) → address
public参见 IGovernor.proposalProposer
。
proposalEta(uint256 proposalId) → uint256
publicproposalNeedsQueuing(uint256) → bool
public参见 IGovernor.proposalNeedsQueuing
。
_checkGovernance()
internal如果 msg.sender
不是执行者,则还原。如果执行者不是此合约本身,则如果 msg.data
未被列入白名单作为 execute
操作的结果,则该函数将还原。参见 onlyGovernance
。
_quorumReached(uint256 proposalId) → bool
internal已投出的票数是否超过了阈值限制。
_voteSucceeded(uint256 proposalId) → bool
internal提案是否成功。
_getVotes(address account, uint256 timepoint, bytes params) → uint256
internal获取 account
在特定 timepoint
的投票权重,用于 params
描述的投票。
_countVote(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes params) → uint256
internal为 proposalId
注册由 account
投票,具有给定的 support
、投票 weight
和投票 params
。
注意:支持是通用的,并且可以代表各种事物,具体取决于所使用的投票系统。
_tallyUpdated(uint256 proposalId)
internal每次更新提案的计票时都应调用的Hook。
注意:此函数必须成功运行。还原将导致治理崩溃
_defaultParams() → bytes
internalcastVote 方法使用的默认附加编码参数,不包括这些参数
注意:应由特定实现重写以使用适当的值,附加参数的含义,在该实现的上下文中
propose(address[] targets, uint256[] values, bytes[] calldatas, string description) → uint256
public参见 IGovernor.propose
。此函数具有选择加入的前端运行保护,如 _isValidDescriptionForProposer
中所述。
_propose(address[] targets, uint256[] values, bytes[] calldatas, string description, address proposer) → uint256 proposalId
internal内部提议机制。可以重写以在提案创建时添加更多逻辑。
发出一个 IGovernor.ProposalCreated
事件。
queue(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
public参见 IGovernor.queue
。
_queueOperations(uint256, address[], uint256[], bytes[], bytes32) → uint48
internal内部排队机制。可以重写(无需超级调用)以修改执行排队的方式(例如添加 vault/timelock)。
默认情况下,此项为空,必须重写才能实现排队。
此函数返回一个时间戳,该时间戳描述了预期的执行 ETA。如果返回值是 0(这是默认值),则核心将认为排队未成功,并且公共 queue
函数将还原。
直接调用此函数将不会检查提案的当前状态,也不会发出 ProposalQueued 事件。应使用 queue 对提案进行排队。 |
execute(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
public_executeOperations(uint256, address[] targets, uint256[] values, bytes[] calldatas, bytes32)
internal内部执行机制。可以重写(无需超级调用)以修改执行方式(例如添加 vault/timelock)。
直接调用此函数将不会检查提案的当前状态,也不会将执行标志设置为 true 或发出 ProposalExecuted 事件。应使用 execute 执行提案。 |
cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
public参见 IGovernor.cancel
。
_cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
internal具有最小限制的内部取消机制。除了 Canceled、Expired 或 Executed 之外,提案可以在任何状态下取消。取消后,提案无法重新提交。
发出一个 IGovernor.ProposalCanceled
事件。
getVotes(address account, uint256 timepoint) → uint256
publicgetVotesWithParams(address account, uint256 timepoint, bytes params) → uint256
public参见 IGovernor.getVotesWithParams
。
castVote(uint256 proposalId, uint8 support) → uint256
publiccastVoteWithReason(uint256 proposalId, uint8 support, string reason) → uint256
public参见 IGovernor.castVoteWithReason
。
castVoteWithReasonAndParams(uint256 proposalId, uint8 support, string reason, bytes params) → uint256
public参见 IGovernor.castVoteWithReasonAndParams
。
castVoteBySig(uint256 proposalId, uint8 support, address voter, bytes signature) → uint256
publiccastVoteWithReasonAndParamsBySig(uint256 proposalId, uint8 support, address voter, string reason, bytes params, bytes signature) → uint256
public参见 IGovernor.castVoteWithReasonAndParamsBySig
。
_castVote(uint256 proposalId, address account, uint8 support, string reason) → uint256
internal内部投票机制:检查投票是否待处理,是否尚未投票,使用 IGovernor.getVotes
检索投票权重,并调用 _countVote
内部函数。使用_defaultParams()。
发出一个 IGovernor.VoteCast
事件。
_castVote(uint256 proposalId, address account, uint8 support, string reason, bytes params) → uint256
internal内部投票机制:检查投票是否待处理,是否尚未投票,使用 IGovernor.getVotes
检索投票权重,并调用 _countVote
内部函数。
发出一个 IGovernor.VoteCast
事件。
relay(address target, uint256 value, bytes data)
external将事务或函数调用中继到任意目标。如果治理执行者是 governor 本身以外的某个合约,例如使用时间锁时,可以在治理提案中调用此函数,以恢复错误发送到 governor 合约的Token或 Ether。请注意,如果执行者只是 governor 本身,则使用 relay
是多余的。
_executor() → address
internalgovernor 通过其执行操作的地址。将被通过另一个合约(例如时间锁)执行操作的模块重载。
onERC721Received(address, address, uint256, bytes) → bytes4
public参见 IERC721Receiver.onERC721Received
。如果治理执行者不是 governor 本身(例如,与时间锁一起使用),则禁用接收Token。
onERC1155Received(address, address, uint256, uint256, bytes) → bytes4
public参见 IERC1155Receiver.onERC1155Received
。如果治理执行者不是 governor 本身(例如,与时间锁一起使用),则禁用接收Token。
onERC1155BatchReceived(address, address, uint256[], uint256[], bytes) → bytes4
public参见 IERC1155Receiver.onERC1155BatchReceived
。如果治理执行者不是 governor 本身(例如,与时间锁一起使用),则禁用接收Token。
_encodeStateBitmap(enum IGovernor.ProposalState proposalState) → bytes32
internal将 ProposalState
编码为 bytes32
表示形式,其中每个启用的位对应于 ProposalState
枚举中的底层位置。例如:
0x000…10000
^^\-\-\-\-\-\- …
^\-\-\-\-\- Succeeded
^\-\-\-\- Defeated
^\-\-\- Canceled
^\-\- Active
^\- Pending
_validateStateBitmap(uint256 proposalId, bytes32 allowedStates) → enum IGovernor.ProposalState
internal检查提案的当前状态是否与 allowedStates
位图描述的要求相符。此位图应使用 _encodeStateBitmap
构建。
如果不满足要求,则会还原并显示 GovernorUnexpectedProposalState
错误。
_isValidDescriptionForProposer(address proposer, string description) → bool
internal_validateCancel(uint256 proposalId, address caller) → bool
internal检查 caller
是否可以取消具有给定 proposalId
的提案。
默认实现允许提案提议者在待处理状态期间取消提案。
clock() → uint48
public用于标记检查点的时钟。可以重写以实现基于时间戳的检查点(和投票)。
CLOCK_MODE() → string
public时钟的描述
votingDelay() → uint256
public提案创建和投票- hashProposal(targets, values, calldatas, descriptionHash)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
##### `COUNTING_MODE() → string` public
##### `hasVoted(uint256 proposalId, address account) → bool` public
##### `proposalVotes(uint256 proposalId) → uint256 againstVotes, uint256 forVotes, uint256 abstainVotes` public
访问内部投票计数。
##### `_quorumReached(uint256 proposalId) → bool` internal
##### `_voteSucceeded(uint256 proposalId) → bool` internal
查看 Governor._voteSucceeded
. 在此模块中,forVotes 必须严格大于 againstVotes。
##### `_countVote(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes) → uint256` internal
查看 Governor._countVote
. 在此模块中,支持遵循来自 Governor Bravo 的 VoteType
枚举。
GovernorCountingFractional
import "@openzeppelin/contracts/governance/extensions/GovernorCountingFractional.sol";
Governor
的扩展,用于 fractional voting。
与 GovernorCountingSimple
类似,此合约是 Governor
的投票计数模块,支持 3 个选项:
反对、赞成、弃权。此外,它还包括第四个选项:Fractional,允许选民在其他 3 个选项中拆分他们的投票权。
以 Fractional 支持投出的票必须附带一个 params
参数,该参数是三个打包的 uint128
值,
分别代表委托人分配给反对、赞成和弃权的权重。对于为其他
3 个选项投出的那些票,params
参数必须为空。
当委托人是一个实施自己投票规则的合约时,这尤其有用。这些委托合约 可以根据多个实体委托其投票权的偏好来投 fractional 票。
一些示例用例包括:
从 DeFi 池持有的代币进行投票
从 L2 中由桥持有的代币进行投票
使用零知识证明从受保护的池中私下投票。
基于 ScopeLift 的 GovernorCountingFractional
自 v5.1 起可用。
函数
Governor
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
[GovernorUnexpectedProposalState(proposalId, current, expectedStates)
](https://docs.openzeppelin.com/contracts/5.x/api/governance#IGovernor-GovernorUnexpectedProposalState-uint256-enum-IGovernor-对一个具有小数的投票进行 分配 会消耗 委托人 在提案中剩余权重的一部分,根据 委托人 分配给每个支持选项的权重(分别是不支持、支持、弃权)。三个解码后的投票权重的总和必须小于或等于 委托人 在提案中剩余的权重(即,他们经过检查点后的总权重减去已在提案中投出的票数)。可以使用以下格式生成:
abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))
考虑一下,小数表决将所投的票数(在每个类别中)限制为 128 位。<br>根据底层 token 有多少小数位,单个投票人可能需要将其投票分成<br>多个投票操作。对于高于约 30 个小数位的精度,大型 token 持有者可能需要<br>可能需要大量调用来投出所有选票。投票人可以选择在单个操作中投出所有<br>剩余的选票,使用传统的 "bravo" 投票。 |
GovernorExceedRemainingWeight(address voter, uint256 usedVotes, uint256 remainingWeight)
error一个小数投票参数使用的投票数超过了该用户可用的投票数。
uint8 VOTE_TYPE_FRACTIONAL
internal constantGovernorCountingOverridable
import "@openzeppelin/contracts/governance/extensions/GovernorCountingOverridable.sol";
Governor
的扩展,使 委托人 能够覆盖其 受托人 的投票。此模块需要一个
继承了 VotesExtended
的 token。
函数
GovernorVotes
Governor
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
COUNTING_MODE() → string
publichasVoted(uint256 proposalId, address account) → bool
public调用 castVote (或类似函数) 会使用 委托 给投票人的投票权来投票。<br>相反,调用 castOverrideVote (或类似函数) 会使用账户本身的投票权,来自其资产<br>余额。投出 "override vote" 不算作投票,也不会通过此 getter 反映出来。 考虑<br>使用 hasVotedOverride 来检查某个账户是否已针对给定的提案 id 投出 "override vote"。 |
hasVotedOverride(uint256 proposalId, address account) → bool
public检查 account
是否已否决其 受托人 对提案的投票。
proposalVotes(uint256 proposalId) → uint256 againstVotes, uint256 forVotes, uint256 abstainVotes
public内部投票计数的访问器。
_quorumReached(uint256 proposalId) → bool
internal_voteSucceeded(uint256 proposalId) → bool
internal参见 Governor._voteSucceeded
。 在此模块中,forVotes 必须严格大于 againstVotes。
_countVote(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes) → uint256
internal参见 Governor._countVote
。 在此模块中,支持遵循 VoteType
枚举(来自 Governor Bravo)。
由 Governor._castVote 调用,后者发出 IGovernor.VoteCast (或 IGovernor.VoteCastWithParams )<br>事件。 |
_countOverride(uint256 proposalId, address account, uint8 support) → uint256
internalGovernor._countVote
的变体,用于处理投票否决。
有关 castVote 和 castOverrideVote 之间的区别,请参见 hasVoted 。 |
_castOverride(uint256 proposalId, address account, uint8 support, string reason) → uint256
internalGovernor._castVote
的变体,用于处理投票否决。返回否决的权重。
castOverrideVote(uint256 proposalId, uint8 support, string reason) → uint256
public用于投出否决票的公共函数。返回否决的权重。
castOverrideVoteBySig(uint256 proposalId, uint8 support, address voter, string reason, bytes signature) → uint256
public用于使用投票人的签名投出否决票的公共函数。返回否决的权重。
OVERRIDE_BALLOT_TYPEHASH() → bytes32
publicVoteReduced(address indexed delegate, uint256 proposalId, uint8 support, uint256 weight)
event在原始 token 持有者投出否决票后,delegate
投出的票数减少了 weight
OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason)
eventproposalId
上的 委托 投票被 weight
否决
GovernorAlreadyOverriddenVote(address account)
errorGovernorVotes
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
Governor
的扩展,用于从 ERC20Votes
token 中提取投票权重,或者自 v4.5 起从 ERC721Votes
token 中提取投票权重。
函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
[castVoteWithReasonAndParams(proposal- [
EIP712Name()`](https://docs.openzeppelin.com/contracts/5.x/api/utils#EIP712-_EIP712Name--)
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
##### constructor(contract IVotes tokenAddress) internal
##### token() → contract IERC5805 public
投票权来源的 token。
##### clock() → uint48 public
Clock (如 ERC-6372 中指定的) 设置为与 token 的 clock 匹配。如果 token 未实现 ERC-6372,则回退到区块号。
##### CLOCK_MODE() → string public
机器可读的 clock 描述,如 ERC-6372 中指定的。
##### _getVotes(address account, uint256 timepoint, bytes) → uint256 internal
GovernorVotesQuorumFraction
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
Governor
的扩展,用于从 ERC20Votes
token 中提取投票权重,并将法定人数表示为占总供应量的一部分。
Functions
GovernorVotes
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
##### constructor(uint256 quorumNumeratorValue) internal
将法定人数初始化为 token 总供应量的一部分。
该分数指定为 numerator / denominator
。默认情况下,分母为 100,因此法定人数指定为百分比:分子为 10 对应于法定人数为总供应量的 10%。分母可以通过覆盖 quorumDenominator
来自定义。
##### quorumNumerator() → uint256 public
返回当前的法定人数分子。请参阅 quorumDenominator
。
##### quorumNumerator(uint256 timepoint) → uint256 public
返回特定时间点的法定人数分子。请参阅 quorumDenominator
。
##### quorumDenominator() → uint256 public
返回法定人数分母。默认为 100,但可能会被覆盖。
##### quorum(uint256 timepoint) → uint256 public
返回时间点的法定人数,以投票数表示:supply * numerator / denominator
。
##### updateQuorumNumerator(uint256 newQuorumNumerator) external
更改法定人数分子。
发出 QuorumNumeratorUpdated
事件。
要求:
必须通过治理提案调用。
新分子必须小于或等于分母。
##### _updateQuorumNumerator(uint256 newQuorumNumerator) internal
更改法定人数分子。
发出 QuorumNumeratorUpdated
事件。
要求:
##### _optimisticUpperLookupRecent(struct Checkpoints.Trace208 ckpts, uint256 timepoint) → uint256 internal
返回特定时间点的分子。
##### QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator) event
##### GovernorInvalidQuorumFraction(uint256 quorumNumerator, uint256 quorumDenominator) error
设置的法定人数不是有效分数。
GovernorVotesSuperQuorumFraction
import "@openzeppelin/contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol";
GovernorVotesQuorumFraction
的扩展,具有表示为总供应量一部分的超级法定人数。满足超级法定人数(并且具有多数赞成票)的提案在提案截止日期之前进入“成功”状态。
Functions
GovernorSuperQuorum
GovernorVotesQuorumFraction
GovernorVotes
Governor
[_voteSucceeded(proposalId- [
_executor()`](https://docs.openzeppelin.com/contracts/5.x/api/governance#Governor-_executor--)
IGovernor
Nonces
EIP712
Events
GovernorVotesQuorumFraction
IGovernor
IERC5267
Errors
GovernorInvalidSuperQuorumFraction(superQuorumNumerator, denominator)
GovernorInvalidSuperQuorumTooSmall(superQuorumNumerator, quorumNumerator)
GovernorInvalidQuorumTooLarge(quorumNumerator, superQuorumNumerator)
GovernorVotesQuorumFraction
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
constructor(uint256 superQuorumNumeratorValue)
internal将超级仲裁初始化为 token 总供应量的一部分。
超级仲裁被指定为 token 总供应量的一部分,并且必须大于仲裁。
superQuorumNumerator() → uint256
public返回当前的超级仲裁分子。
superQuorumNumerator(uint256 timepoint) → uint256
public返回在特定 timepoint
的超级仲裁分子。
superQuorum(uint256 timepoint) → uint256
public返回 timepoint
的超级仲裁,以票数表示:supply * numerator / denominator
。
更多详细信息,请参见 GovernorSuperQuorum.superQuorum
。
updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator)
public更改超级仲裁分子。
发出一个 SuperQuorumNumeratorUpdated
事件。
要求:
必须通过治理提案调用。
新的超级仲裁分子必须小于或等于分母。
新的超级仲裁分子必须大于或等于仲裁分子。
_updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator)
internal更改超级仲裁分子。
发出一个 SuperQuorumNumeratorUpdated
事件。
要求:
新的超级仲裁分子必须小于或等于分母。
新的超级仲裁分子必须大于或等于仲裁分子。
_updateQuorumNumerator(uint256 newQuorumNumerator)
internal覆盖 GovernorVotesQuorumFraction._updateQuorumNumerator
以确保超级仲裁分子大于或等于仲裁分子。
state(uint256 proposalId) → enum IGovernor.ProposalState
publicGovernor.state
函数的重写版本,用于检查提案是否已达到超级仲裁。
如果提案达到超级仲裁,但 _voteSucceeded 返回 false,例如,假设超级仲裁设置得足够低,以至于 FOR 和 AGAINST 票都超过了它,并且 AGAINST 票超过了 FOR 票,<br>该提案将继续保持活动状态,直到 _voteSucceeded 返回 true 或达到提案截止日期。<br>这意味着,如果超级仲裁设置得很低,投票也可能在足够的 AGAINST 投票者有机会投票之前过早成功。因此,建议设置足够高的超级仲裁以避免这些<br>类型的场景。 |
SuperQuorumNumeratorUpdated(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator)
eventGovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator)
error设置的超级仲裁无效,因为它超过了仲裁分母。
GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator)
error设置的超级仲裁无效,因为它小于或等于仲裁。
GovernorInvalidQuorumTooLarge(uint256 quorumNumerator, uint256 superQuorumNumerator)
error设置的仲裁无效,因为它超过了超级仲裁。
GovernorTimelockAccess
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockAccess.sol";
该模块将 Governor
实例连接到 accessManager
实例, 允许 governor 使用普通的 queue
工作流调用被 manager 延迟限制的调用. 对于 manager 没有外部延迟的操作,会应用一个可选的基础延迟. 提案的执行将会被延迟,以满足其所有操作的需求延迟。
这个扩展允许 governor 持有和使用自己的资产和权限,不像 GovernorTimelockControl
和 GovernorTimelockCompound
,其中时间锁是一个单独的合约,必须是持有资产和
权限的合约。然而,受 manager 延迟限制的操作将通过
AccessManager.execute
函数执行.
一些操作可能会在 AccessManager
中被管理员或一组监护人取消,这取决于
正在调用的受限函数。由于提案是原子的,监护人取消提案中的单个操作将导致所有提案都无法执行。考虑单独提出可取消的操作。
默认情况下,只要相关的 AccessManager
声称目标函数受其约束,函数调用将通过其路由。然而,管理员可以配置 manager 对 governor 想要直接调用的函数(例如,token 转移)进行声明,试图拒绝 governor 访问这些函数。为了缓解这种攻击媒介,governor 能够使用 setAccessManagerIgnored
忽略 AccessManager
声明的限制。虽然减轻了永久拒绝服务,但临时 DoS 在技术上仍有可能。默认情况下,所有 governor 自己的函数(例如,setBaseDelaySeconds
)都忽略 AccessManager
。
AccessManager 不支持同时调度具有相同目标和 calldata 的多个操作。<br>参见 AccessManager.schedule 以获得解决方法。 |
函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorInvalidProposalLength(targets, calldatas, values)
](https://docs.openzeppelin.com/contracts/5.x/api/governance#IGovernor-GovernorInvalidProposalLength-uint256-uint25更改 baseDelaySeconds
的值。此操作只能通过治理提案调用。_setBaseDelaySeconds(uint32 newBaseDelay)
internal更改 baseDelaySeconds
的值。没有访问控制的内部函数。
isAccessManagerIgnored(address target, bytes4 selector) → bool
public检查来自关联的 accessManager
的限制是否对目标函数忽略。当目标函数将被直接调用,而不管该函数的 AccessManager
设置如何时,返回 true。
请参阅上面的 setAccessManagerIgnored
和安全考虑事项。
setAccessManagerIgnored(address target, bytes4[] selectors, bool ignored)
public配置是否忽略来自关联的 accessManager
的限制,针对目标函数。
请参阅上面的安全考虑事项。
_setAccessManagerIgnored(address target, bytes4 selector, bool ignored)
internalsetAccessManagerIgnored
的内部版本,没有访问限制。
proposalExecutionPlan(uint256 proposalId) → uint32 delay, bool[] indirect, bool[] withDelay
public公共访问器,用于检查执行计划,包括提案自排队后将被延迟的秒数,一个数组,指示哪些提案操作将通过关联的 accessManager
间接执行,另一个数组,指示哪些操作将在 queue
中调度。请注意,那些必须调度的操作可以被 AccessManager
守护者取消。
proposalNeedsQueuing(uint256 proposalId) → bool
public请参阅 IGovernor.proposalNeedsQueuing
。
propose(address[] targets, uint256[] values, bytes[] calldatas, string description) → uint256
public_queueOperations(uint256 proposalId, address[] targets, uint256[], bytes[] calldatas, bytes32) → uint48
internal用于对提案进行排队的机制,可能会在 AccessManager 中调度其某些操作。
执行延迟是根据在 propose 中检索的延迟信息选择的。如果自提案创建以来延迟已更新,则此值可能不正确。在这种情况下,需要重新创建提案。 |
_executeOperations(uint256 proposalId, address[] targets, uint256[] values, bytes[] calldatas, bytes32)
internal用于执行提案的机制,对于延迟的操作,可能会通过 AccessManager.execute
进行。
_cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
internal请参阅 Governor._cancel
BaseDelaySet(uint32 oldBaseDelaySeconds, uint32 newBaseDelaySeconds)
eventAccessManagerIgnoredSet(address target, bytes4 selector, bool ignored)
eventGovernorUnmetDelay(uint256 proposalId, uint256 neededTimestamp)
errorGovernorMismatchedNonce(uint256 proposalId, uint256 expectedNonce, uint256 actualNonce)
errorGovernorLockedIgnore()
errorGovernorTimelockControl
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
Governor
的扩展,它将执行过程绑定到 TimelockController
的实例。这为所有成功的提案增加了一个延迟,该延迟由 TimelockController
强制执行(除了投票持续时间之外)。Governor
需要 proposer(理想情况下是 executor 和 canceller)角色,Governor
才能正常工作。
使用此模型意味着提案将由 TimelockController
操作,而不是由 Governor
操作。因此,资产和权限必须附加到 TimelockController
。发送到 Governor
的任何资产将无法从提案访问,除非通过 Governor.relay
执行。
除了 governor 之外,将 TimelockController 设置为具有额外的 proposers 或 cancelers 非常危险,因为它授予他们以下能力:1) 以 timelock 的身份执行操作,从而可能执行预计只能通过投票才能访问的操作或访问资金,以及 2) 阻止已获得选民批准的治理提案,从而有效地执行拒绝服务攻击。 |
函数
_queueOperations(proposalId, targets, values, calldatas, descriptionHash)
_executeOperations(proposalId, targets, values, calldatas, descriptionHash)
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
constructor(contract TimelockController timelockAddress)
internal设置 timelock。
state(uint256 proposalId) → enum IGovernor.ProposalState
publicGovernor.state
函数的重写版本,它考虑了 timelock 报告的状态。
timelock() → address
public用于检查 timelock 地址的公共访问器
proposalNeedsQueuing(uint256) → bool
public请参阅 IGovernor.proposalNeedsQueuing
。
_queueOperations(uint256 proposalId, address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint48
internal用于将提案排队到 timelock 的函数。
_executeOperations(uint256 proposalId, address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash)
internalGovernor._executeOperations
函数的重写版本,它通过 timelock 运行已经排队的提案。
_cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
internalGovernor._cancel
函数的重写版本,用于取消已经排队的 timelock 提案。
_executor() → address
internalgovernor 执行操作的地址。在这种情况下,是 timelock。
updateTimelock(contract TimelockController newTimelock)
external用于更新底层 timelock 实例的公共端点。限制为 timelock 本身,因此更新必须通过治理提案提出、安排和执行。
建议不要在存在其他已排队的治理提案时更改 timelock。 |
TimelockChange(address oldTimelock, address newTimelock)
event当用于提案执行的 timelock 控制器被修改时发出。
GovernorTimelockCompound
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockCompound.sol";
Governor
的扩展,它将执行过程绑定到 Compound Timelock。这为所有成功的提案增加了一个延迟,该延迟由外部 timelock 强制执行(除了投票持续时间之外)。对于要执行的任何操作,Governor
需要是 timelock 的管理员。一个公共的、不受限制的 GovernorTimelockCompound.acceptAdmin
可用于接受 timelock 的所有权。
使用此模型意味着提案将由 TimelockController
操作,而不是由 Governor
操作。因此,资产和权限必须附加到 TimelockController
。发送到 Governor
的任何资产将无法从提案访问,除非通过 Governor.relay
执行。
函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
[queue(targets, values, calldatas, descriptionHash- [
CLOCK_MODE()`](https://docs.openzeppelin.com/contracts/5.x/api/governance#Governor-CLOCK_MODE--)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
constructor(contract ICompoundTimelock timelockAddress)
internal设置时间锁。
state(uint256 proposalId) → enum IGovernor.ProposalState
publicGovernor.state
函数的重写版本,增加了对 Expired
状态的支持。
timelock() → address
public用于检查时间锁地址的公共访问器
proposalNeedsQueuing(uint256) → bool
public参见 IGovernor.proposalNeedsQueuing
。
_queueOperations(uint256 proposalId, address[] targets, uint256[] values, bytes[] calldatas, bytes32) → uint48
internal用于将提案加入时间锁队列的函数。
_executeOperations(uint256 proposalId, address[] targets, uint256[] values, bytes[] calldatas, bytes32)
internalGovernor._executeOperations
函数的重写版本,用于通过时间锁运行已排队的提案。
_cancel(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) → uint256
internalGovernor._cancel
函数的重写版本,用于取消已排队的时间锁提案(如果已排队)。
_executor() → address
internalGovernor 执行操作的地址。 在本例中,为时间锁。
__acceptAdmin()
public接受对时间锁的管理权限。
updateTimelock(contract ICompoundTimelock newTimelock)
external用于更新底层时间锁实例的公共端点。 仅限于时间锁本身,因此更新必须通过治理提案提出、安排和执行。
出于安全原因,必须在设置新的时间锁之前将时间锁移交给另一个管理员。 两个操作(移交时间锁)并执行更新可以分批放在一个提案中。
请注意,如果时间锁管理员已在之前的操作中被移交出去,如果时间锁的管理员已被接受并且操作在治理范围之外执行,我们将拒绝通过时间锁进行的更新。
不建议在有其他已排队的治理提案时更改时间锁。 |
TimelockChange(address oldTimelock, address newTimelock)
event当用于提案执行的时间锁控制器被修改时发出。
GovernorSettings
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
Governor
的扩展,用于通过治理更新设置。
函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
constructor(uint48 initialVotingDelay, uint32 initialVotingPeriod, uint256 initialProposalThreshold)
internal初始化治理参数。
votingDelay() → uint256
publicvotingPeriod() → uint256
publicproposalThreshold() → uint256
public参见 Governor.proposalThreshold
。
setVotingDelay(uint48 newVotingDelay)
public更新投票延迟。此操作只能通过治理提案执行。
发出 VotingDelaySet
事件。
setVotingPeriod(uint32 newVotingPeriod)
public更新投票期。此操作只能通过治理提案执行。
发出 VotingPeriodSet
事件。
setProposalThreshold(uint256 newProposalThreshold)
public更新提案阈值。此操作只能通过治理提案执行。
发出 ProposalThresholdSet
事件。
_setVotingDelay(uint48 newVotingDelay)
internal投票延迟的内部设置器。
发出 VotingDelaySet
事件。
_setVotingPeriod(uint32 newVotingPeriod)
internal投票期的内部设置器。
发出 VotingPeriodSet
事件。
_setProposalThreshold(uint256 newProposalThreshold)
internal提案阈值的内部设置器。
发出 ProposalThresholdSet
事件。
VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay)
eventVotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod)
eventProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold)
eventGovernorPreventLateQuorum
import "@openzeppelin/contracts/governance/extensions/GovernorPreventLateQuorum.sol";
一个模块,确保在达到法定人数后有最短的投票期。这可以防止大型投票者通过确保始终有时间让其他投票者做出反应并尝试反对该决定,从而在最后一刻左右投票并触发法定人数。
如果投票导致达到法定人数,则可以延长提案的投票期,使其不会在至少经过指定时间(“投票延期”参数)之前结束。此参数可以通过治理提案设置。
函数
[_setLateQuorumVoteExtension(newVoteExtension)
](https://docs.openzeppelin.com/contracts/5.x/api/governance#GovernorPreventLateQuorum-_setLateQuorumVoteExtension- cancel(targets, values, calldatas, descriptionHash)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
constructor(uint48 initialVoteExtension)
internal初始化投票扩展参数:自提案达到法定人数到其投票期结束之间需要经过的时间(以区块数或秒为单位,具体取决于 governor 时钟模式)。 如果必要,投票期将延长到提案创建期间设置的时间之外。
proposalDeadline(uint256 proposalId) → uint256
public返回提案截止日期,如果提案在其投票期内较晚达到法定人数,则截止日期可能已超出提案创建时设置的截止日期。 请参阅 Governor.proposalDeadline
。
_tallyUpdated(uint256 proposalId)
internal投票统计已更新,并检测它是否导致达到法定人数,从而可能延长投票期。
可能会发出 ProposalExtended
事件。
lateQuorumVoteExtension() → uint48
public返回投票扩展参数的当前值:从提案达到法定人数到其投票期结束所需经过的区块数。
setLateQuorumVoteExtension(uint48 newVoteExtension)
public更改 lateQuorumVoteExtension
。 此操作只能由治理执行者执行,通常通过治理提案执行。
发出 LateQuorumVoteExtensionSet
事件。
_setLateQuorumVoteExtension(uint48 newVoteExtension)
internal更改 lateQuorumVoteExtension
。 这是一个内部函数,如果需要另一种访问控制机制,可以在公共函数(如 setLateQuorumVoteExtension
)中公开该函数。
发出 LateQuorumVoteExtensionSet
事件。
ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline)
event当提案截止日期因在其投票期内较晚达到法定人数而被推迟时发出。
LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension)
event当 lateQuorumVoteExtension
参数被更改时发出。
GovernorStorage
import "@openzeppelin/contracts/governance/extensions/GovernorStorage.sol";
Governor
的扩展,实现了提案详情的存储。此模块还提供了提案可枚举性的原语。
此模块的用例包括:
Governor.queue
和 Governor.execute
函数中的参数,用于 L2 链,在这些链中,与 calldata 相比,存储成本较低。函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
_propose(address[] targets, uint256[] values, bytes[] calldatas, string description,- [
_checkGovernance()`](https://docs.openzeppelin.com/contracts/5.x/api/governance#Governor-_checkGovernance--)_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
proposalGuardian() → address
publicGetter,返回 proposal guardian 的地址。
setProposalGuardian(address newProposalGuardian)
public更新 proposal guardian 的地址。这个操作只能通过治理提案来执行。
发出一个 ProposalGuardianSet
事件。
_setProposalGuardian(address newProposalGuardian)
internalproposal guardian 的内部 setter。
发出一个 ProposalGuardianSet
事件。
_validateCancel(uint256 proposalId, address caller) → bool
internal覆盖 Governor._validateCancel
以实现扩展的取消逻辑。
proposalGuardian
可以在任何时候取消任何提案。
如果没有设置 proposal guardian,IGovernor.proposalProposer
可以在任何时候取消他们的提案。
在任何情况下,Governor._validateCancel
(或另一个覆盖)中定义的权限仍然有效。
ProposalGuardianSet(address oldProposalGuardian, address newProposalGuardian)
eventGovernorSuperQuorum
import "@openzeppelin/contracts/governance/extensions/GovernorSuperQuorum.sol";
Governor
的扩展,具有超级法定人数。满足超级法定人数(并且具有多数赞成票)的提案在提案截止日期之前进入 Succeeded
状态。想要使用此扩展的计数模块必须实现proposalVotes
。
函数
Governor
_countVote(proposalId, account, support, totalWeight, params)
castVoteWithReasonAndParams(proposalId, support, reason, params)
castVoteWithReasonAndParamsBySig(proposalId, support, voter, reason, params, signature)
IGovernor
Nonces
EIP712
Events
IGovernor
IERC5267
Errors
IGovernor
GovernorUnexpectedProposalState(proposalId, current, expectedStates)
GovernorInsufficientProposerVotes(proposer, votes, threshold)
Nonces
superQuorum(uint256 timepoint) → uint256
public提案达到超级法定人数所需的最小投票- getVotes(account)
Nonces
EIP712
Events
IVotes
IERC5267
Errors
IVotes
Nonces
clock() → uint48
public用于标记检查点的时钟。可以被覆盖以实现基于时间戳的检查点(和投票),在这种情况下,CLOCK_MODE
也应该被覆盖以匹配。
CLOCK_MODE() → string
public如 ERC-6372 中规定的时钟的机器可读描述。
_validateTimepoint(uint256 timepoint) → uint48
internal验证时间点是否在过去,并将其作为 uint48 返回。
getVotes(address account) → uint256
public返回 account
当前拥有的票数。
getPastVotes(address account, uint256 timepoint) → uint256
public返回 account
在过去特定时刻拥有的票数。如果 clock()
被配置为使用区块号,这将返回相应区块结束时的值。
要求:
timepoint
必须在过去。如果使用区块号操作,则该区块必须已被挖掘。getPastTotalSupply(uint256 timepoint) → uint256
public返回过去特定时刻可用的总票数。如果 clock()
被配置为使用区块号,这将返回相应区块结束时的值。
该值是所有可用票数的总和,不一定是所有已授权票数的总和。<br>尚未授权的票数仍然是总供应量的一部分,即使它们不会参与投票。<br> |
要求:
timepoint
必须在过去。如果使用区块号操作,则该区块必须已被挖掘。_getTotalSupply() → uint256
internal返回当前的总票数。
delegates(address account) → address
public返回 account
选择的委托人。
delegate(address delegatee)
public将投票权从发送者委托给 delegatee
。
delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
public将投票权从签名者委托给 delegatee
。
_delegate(address account, address delegatee)
internal将所有 account
的投票单位委托给 delegatee
。
发出事件 IVotes.DelegateChanged
和 IVotes.DelegateVotesChanged
。
_transferVotingUnits(address from, address to, uint256 amount)
internal转移、铸造或销毁投票单位。要注册铸造,from
应该为零。要注册销毁,to
应该为零。投票单位的总供应量将通过铸造和销毁进行调整。
_moveDelegateVotes(address from, address to, uint256 amount)
internal将委托的投票权从一个委托人转移到另一个委托人。
_numCheckpoints(address account) → uint32
internal获取 account
的检查点数量。
_checkpoints(address account, uint32 pos) → struct Checkpoints.Checkpoint208
internal获取 account
的第 pos
个检查点。
_getVotingUnits(address) → uint256
internal必须返回账户持有的投票单位。
ERC6372InconsistentClock()
error时钟被错误地修改了。
ERC5805FutureLookup(uint256 timepoint, uint48 clock)
error无法查找未来的投票。
VotesExtended
import "@openzeppelin/contracts/governance/utils/VotesExtended.sol";
Votes
的扩展,增加了对委托和余额的检查点。
虽然此合约扩展了 Votes ,但 Votes 的有效使用可能与<br>VotesExtended 不兼容,除非进行额外的考虑。_transferVotingUnits 的此实现必须<br>在投票权重移动注册加粗后运行,以便它反映在 _getVotingUnits 上。 |
换句话说,VotesExtended
必须以一种在资产转移注册加粗且余额更新后调用 _transferVotingUnits
的方式集成:
contract VotingToken is Token, VotesExtended {
function transfer(address from, address to, uint256 tokenId) public override {
super.transfer(from, to, tokenId); // <- 首先执行转移 ...
_transferVotingUnits(from, to, 1); // <- ... 然后调用 _transferVotingUnits。
}
function _getVotingUnits(address account) internal view override returns (uint256) {
return balanceOf(account);
}
}
ERC20Votes
和 ERC721Votes
遵循此模式,因此可以安全地与 VotesExtended
一起使用。
Functions
Votes
Nonces
EIP712
Events
IVotes
IERC5267
Errors
Votes
IVotes
Nonces
getPastDelegate(address account, uint256 timepoint) → address
public返回在过去特定时刻 account
的委托人。如果 clock()
被配置为使用区块号,这将返回相应区块结束时的值。
要求:
timepoint
必须在过去。如果使用区块号操作,则该区块必须已被挖掘。getPastBalanceOf(address account, uint256 timepoint) → uint256
public返回在过去特定时刻 account
的 balanceOf
。如果 clock()
被配置为使用区块号,这将返回相应区块结束时的值。
要求:
timepoint
必须在过去。如果使用区块号操作,则该区块必须已被挖掘。_delegate(address account, address delegatee)
internal将所有 account
的投票单位委托给 delegatee
。
发出事件 IVotes.DelegateChanged
和 IVotes.DelegateVotesChanged
。
_transferVotingUnits(address from, address to, uint256 amount)
internal转移、铸造或销毁投票单位。要注册铸造,from
应该为零。要注册销毁,to
应该为零。投票单位的总供应量将通过铸造和销毁进行调整。
在治理系统中,TimelockController
合约负责在提案及其执行之间引入延迟。它可以与 Governor
一起使用,也可以不一起使用。
TimelockController
import "@openzeppelin/contracts/governance/TimelockController.sol";
合约模块,充当时间锁定的控制器。当设置为 Ownable
智能合约的所有者时,它会对所有 onlyOwner
维护操作强制执行时间锁。这使得受控合约的用户有时间在应用潜在危险的维护操作之前退出。
默认情况下,此合约是自我管理的,这意味着管理任务必须经过时间锁流程。提议者(resp 执行者)角色负责提议(resp 执行)操作。一个常见的用例是将此 TimelockController
定位为智能合约的所有者,并将多重签名或 DAO 作为唯一的提议者。
Modifiers
Functions
hashOperationBatch(targets, values, payloads, predecessor, salt)
scheduleBatch(targets, values, payloads, predecessor, salt, delay)
ERC1155Holder
ERC721Holder
AccessControl
Events
IAccessControl
Errors
IAccessControl
Internal Variables
onlyRoleOrOpenRole(bytes32 role)
modifier修饰符,使一个函数只能由某个角色调用。除了检查发送者的角色之外,address(0)
的角色也被考虑在内。将角色授予 address(0)
等同于为每个人启用此角色。
constructor(uint256 minDelay, address[] proposers, address[] executors, address admin)
public使用以下参数初始化合约:
minDelay
:操作的初始最小延迟(以秒为单位)
proposers
:将被授予提议者和取消者角色的帐户
executors
:将被授予执行者角色的帐户
admin
:将被授予管理员角色的可选帐户;使用零地址禁用
可选的管理员可以帮助在部署后进行角色的初始配置,而无需受到延迟的影响,但是此角色应随后被放弃,以支持<br>通过时间锁定的提案进行管理。此合约的先前版本会自动将此管理员分配给部署者,并且也应将其放弃。 |
receive()
external合约可能会接收/持有 ETH 作为维护过程的一部分。
supportsInterface(bytes4 interfaceId) → bool
publicisOperation(bytes32 id) → bool
public返回 ID 是否对应于已注册的操作。这包括等待、就绪和完成的操作。
isOperationPending(bytes32 id) → bool
public返回操作是否正在挂起。请注意,“挂起”操作也可能是“就绪”的。
isOperationReady(bytes32 id) → bool
public返回操作是否已准备好执行。请注意,“就绪”操作也正在“挂起”。
isOperationDone(bytes32 id) → bool
public返回操作是否已完成。
getTimestamp(bytes32 id) → uint256
public返回操作准备就绪的时间戳(未设置的操作为 0,完成的操作为 1)。
getOperationState(bytes32 id) → enum TimelockController.OperationState
public返回操作状态。
getMinDelay() → uint256
public返回操作变为有效所需的最小延迟(以秒为单位)。
此值可以通过执行调用 updateDelay
的操作来更改。
hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) → bytes32
public返回包含单个事务的操作的标识符。
hashOperationBatch(address[] targets, uint256[] values, bytes[] payloads, bytes32 predecessor, bytes32 salt) → bytes32
public返回包含一批事务的操作的标识符。
schedule(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt, uint256 delay)
public计划包含单个事务的操作。
如果盐不为零,则发出 CallSalt
,并发出 [CallScheduled
](https://docs.##### TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates)
错误
操作的当前状态不符合要求。
expectedStates
是一个位图,从右到左,为每个 OperationState 枚举位置启用位。
TimelockUnexecutedPredecessor(bytes32 predecessorId)
错误某个操作的前置操作尚未完成。
TimelockUnauthorizedCaller(address caller)
错误调用者账户未被授权。
uint256 _DONE_TIMESTAMP
内部常量Operation (操作): 一项事务(或一组事务),是时间锁的主题。它必须由提议者安排,并由执行者执行。时间锁强制在提议和执行之间设置最短延迟。如果操作包含多个事务(批量模式),它们将以原子方式执行。操作由其内容的哈希标识。
Operation status (操作状态):
Unset (未设置): 不属于时间锁机制的操作。
Waiting (等待中): 已安排的操作,在计时器到期之前。
Ready (就绪): 已安排的操作,在计时器到期之后。
Pending (待定): 处于等待中或就绪状态的操作。
Done (已完成): 已执行的操作。
Predecessor (前置操作): 操作之间的(可选)依赖关系。一个操作可以依赖于另一个操作(其前置操作),从而强制执行这两个操作的执行顺序。
Role (角色):
Admin (管理员): 负责授予提议者和执行者角色的地址(智能合约或 EOA)。
Proposer (提议者): 负责安排(和取消)操作的地址(智能合约或 EOA)。
Executor (执行者): 负责在时间锁到期后执行操作的地址(智能合约或 EOA)。可以将此角色授予零地址,以允许任何人执行操作。
由 TimelockController
执行的操作可以包含一个或多个后续调用。根据是否需要以原子方式执行多个调用,可以使用简单操作或批量操作。
两种操作都包含:
Target (目标),时间锁应操作的智能合约的地址。
Value (值),以 wei 为单位,应与事务一起发送。大多数时候,这将是 0。以太币可以在执行事务之前存入,也可以在执行事务时一同传递。
Data (数据),包含编码的函数选择器和调用的参数。这可以使用多种工具生成。例如,可以使用 web3js 将授予 ACCOUNT
对角色 ROLE
的维护操作编码如下:
const data = timelock.contract.methods.grantRole(ROLE, ACCOUNT).encodeABI()
Predecessor (前置操作),指定操作之间的依赖关系。此依赖关系是可选的。如果操作没有任何依赖关系,请使用 bytes32(0)
。
Salt (盐),用于消除两个其他方面相同的操作的歧义。这可以是任何随机值。
在批量操作的情况下,target
、value
和 data
被指定为数组,这些数组的长度必须相同。
时间锁定的操作由唯一的 ID(它们的哈希)标识,并遵循特定的生命周期:
Unset
→ Pending
→ Pending
+ Ready
→ Done
通过调用 schedule
(或 scheduleBatch
),提议者将操作从 Unset
状态移动到 Pending
状态。这将启动一个计时器,该计时器必须长于最短延迟。计时器在通过 getTimestamp
方法访问的时间戳到期。
计时器到期后,操作将自动进入 Ready
状态。此时,可以执行该操作。
通过调用 execute
(或 executeBatch
),执行者触发操作的底层事务,并将其移动到 Done
状态。如果操作具有前置操作,则该前置操作必须处于 Done
状态,此转换才能成功。
cancel
允许提议者取消任何 Pending
操作。这会将操作重置为 Unset
状态。因此,提议者可以重新安排已取消的操作。在这种情况下,重新安排操作时,计时器将重新启动。
可以使用以下函数查询操作状态:
管理员负责管理提议者和执行者。为了使时间锁实现自治,此角色应仅授予时间锁本身。部署后,除了时间锁本身之外,还可以将管理员角色授予任何地址。在进一步配置和测试后,此可选管理员应放弃其角色,以便所有进一步的维护操作都必须通过时间锁过程。
提议者负责安排(和取消)操作。这是一个关键角色,应授予治理实体。这可以是 EOA、多重签名或 DAO。
Proposer fight (提议者之争): 拥有多个提议者,虽然可以在某个提议者不可用时提供冗余,但可能很危险。由于提议者对所有操作都有发言权,因此他们可以取消他们不同意的操作,包括将他们从提议者中删除的操作。 |
此角色由 PROPOSER_ROLE 值标识:0xb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1
执行者负责在时间锁到期后执行提议者安排的操作。逻辑上讲,作为提议者的多重签名或 DAO 也应该是执行者,以保证已安排的操作最终会被执行。但是,拥有额外的执行者可以降低成本(执行事务不需要提议它的多重签名或 DAO 的验证),同时确保负责执行的人员无法触发未经提议者安排的操作。或者,可以允许任何地址在时间锁到期后通过将执行者角色授予零地址来执行提议。
此角色由 EXECUTOR_ROLE 值标识:0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63
一个没有至少一个提议者和一个执行者的活动合约将被锁定。在部署者放弃其对时间锁合约本身的行政权利之前,请确保这些角色由可靠的实体填充。有关角色管理的更多信息,请参见 AccessControl 文档。 |
- 原文链接: docs.openzeppelin.com/co...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!