治理
这个 crate 包括链上治理的原语。
Governor
这个模块化的 Governor 组件系统允许部署易于定制的链上投票协议。
有关如何实现 Governor 的演练,请查看 Governor 页面。 |
IGovernor
use openzeppelin_governance::governor::interface::IGovernor;
governor 合约的接口。
0x1100a1f8546595b5bd75a6cd8fcc5b015370655e66f275963321c5cd0357ac9
name() → felt252
external
governor 实例的名称(用于构建 SNIP-12 域分隔符)。
version() → felt252
external
governor 实例的版本(用于构建 SNIP-12 域分隔符)。
COUNTING_MODE() → ByteArray
external
对 cast_vote
的可能 support
值的描述,以及这些投票的计数方式,旨在被 UI 消费,
以显示正确的投票选项并解释结果。该字符串是一个 URL 编码的键值对序列,
每个键值对描述一个方面,例如 support=bravo&quorum=for,abstain
。
有两个标准键:support
和 quorum
。
-
support=bravo
指的是投票选项 0 = 反对,1 = 赞成,2 = 弃权,如在GovernorBravo
中。 -
quorum=bravo
意味着只有赞成票会计入法定人数。 -
quorum=for,abstain
意味着赞成票和弃权票都会计入法定人数。
如果计数模块使用了编码的 params
,则应在 params
下包含此信息
键,并使用描述行为的唯一名称。例如:
-
params=fractional
可能指的是一种方案,其中投票以分数形式在 赞成/反对/弃权之间分配。 -
params=erc721
可能指的是一种方案,其中特定的 NFT 被委托进行投票。
该字符串可以被标准的 URLSearchParams
JavaScript 类解码。
|
hash_proposal(calls: Span<Call>, description_hash: felt252) → felt252
external
用于从提案细节(重新)构建提案 id 的哈希函数。
proposal_snapshot(proposal_id: felt252) → u64
external
用于检索用户投票和法定人数的时间点。如果使用区块号,则快照在此区块结束时执行。 因此,对此提案的投票从下一个区块的开始开始。
proposal_deadline(proposal_id: felt252) → u64
external
投票结束的时间点。如果使用区块号,则投票在此区块结束时结束,因此 可以在此区块期间进行投票。
proposal_eta(proposal_id: felt252) → u64
external
排队的提案变得可执行的时间("ETA")。与 proposal_snapshot
和 proposal_deadline
不同,
这不使用 governor 时钟,而是依赖于执行者的时钟,该时钟可能不同。在大多数情况下,这将是一个时间戳。
voting_delay() → u64
external
提案创建时间和投票开始时间之间的延迟。此持续时间使用的单位取决于 此合约使用的时钟(参见 ERC-6372)。
可以增加此值,以便在提案开始投票之前,用户有时间购买投票权或委托投票权。
voting_period() → u64
external
投票开始时间和结束时间之间的延迟。此持续时间使用的单位取决于 此合约使用的时钟(参见 ERC-6372)。
voting_delay 可能会延迟投票的开始。在设置投票持续时间时,必须考虑这一点
与投票延迟相比。
|
此值在提交提案时存储,以便对该值的可能更改 不会影响已提交的提案。 |
quorum(timepoint: u64) → u256
external
提案成功所需的最低票数。
timepoint 参数对应于用于计算投票的快照。这允许
法定人数根据该时间点的值(例如令牌的总供应量)进行调整。
|
get_votes(account: ContractAddress, timepoint: u64) → u256
external
返回 account
在特定 timepoint
的投票权。
这可以通过多种方式实现,例如通过从一个(或多个)ERC20Votes 令牌读取委托余额。
|
get_votes_with_params(account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256
external
返回 account
在特定 timepoint
的投票权(给定额外的编码参数)。
propose(calls: Span<Call>, description: ByteArray) → felt252
external
创建一个新提案。投票在 voting_delay
指定的延迟后开始,持续时间为 voting_period
指定的时间。
Governor 和目标的状态可能在提案创建和执行之间发生变化。 这可能是目标合约上第三方操作或其 governor 提案的结果。 例如,此合约的余额可能会更新,或者其访问控制权限可能会被 修改,可能会损害提案成功执行的能力(例如,governor 没有足够的价值来覆盖具有多个转移的提案)。 |
返回提案的 id。
queue(calls: Span<Call>, description_hash: felt252) → felt252
external
对提案进行排队。某些 governor 要求在执行之前执行此步骤。 如果排队不是必需的,则此函数可能会回退。
对提案进行排需要达到法定人数,投票才能成功,并且必须达到 截止日期。
返回提案的 id。
execute(calls: span<Call>, description_hash: felt252) → felt252
external
执行成功的提案。这需要达到法定人数,投票才能 成功,并且必须达到截止日期。根据 governor 的不同,也可能需要 提案已排队并且经过了一些延迟。
有些模块可以修改执行的要求,例如通过添加
额外的时间锁(参见 timelock_controller )。
|
返回提案的 id。
cancel(calls: Span<Call>, description_hash: felt252) → felt252
external
取消提案。提案可以由提案人取消,但只能在 Pending 状态下取消,即在投票开始之前取消。
返回提案的 id。
cast_vote_with_reason(proposal_id: felt252, support: u8, reason: ByteArray) → u256
external
对提案进行投票,并提供 reason
。
返回投票的权重。
cast_vote_with_reason_and_params(proposal_id: felt252, support: u8, reason: ByteArray, params: Span<felt252>) → u256
external
对提案进行投票,并提供理由和其他编码参数。
返回投票的权重。
cast_vote_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span<felt252>) → u256
external
使用选民的签名对提案进行投票。
返回投票的权重。
cast_vote_with_reason_and_params_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, reason: ByteArray, params: Span<felt252>, signature: Span<felt252>) → u256
external
使用 voter
的签名对提案进行投票,并提供理由和其他编码参数。
返回投票的权重。
relay(call: Call)
external
将交易或函数调用传递到任意目标。
如果 governance 执行器是 governor 本身以外的某个合约,例如 当使用时间锁时,可以在 governance 提案中调用此函数以恢复 错误地发送到 governor 合约的令牌。
如果执行器只是 governor 本身,则使用 relay 是多余的。
|
ProposalCreated(proposal_id: felt252, proposer: ContractAddress, calls: Span<Call>, signatures: Span<Span<felt252>>, vote_start: u64, vote_end: u64, description: ByteArray)
event
在创建提案时发出。
GovernorComponent
use openzeppelin_governance::governor::GovernorComponent;
治理系统的核心。
下面介绍的扩展 trait 使 GovernorComponent 成为一个模块化和可配置的系统。可嵌入的 和内部实现取决于这些 trait。它们可以在合约本地实现,也可以通过提供的库 组件扩展。 |
实施 SRC5Component 是本组件需要实现的要求。 |
voting_delay(self: @ContractState) → u64
extension
必须返回提案创建时间和投票开始时间之间的延迟(以时间点数表示)。可以 增加此值,以便在提案开始投票之前,用户有时间购买投票权或委托投票权。
counting_mode(self: @ContractState) → ByteArray
extension
必须返回对 cast_vote
的可能 support
值以及计算这些投票的方式的描述,
旨在被 UI 消耗,以显示正确的投票选项并解释结果。
有关更多详细信息,请参见 COUNTING_MODE。
count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span<felt252>) → u256
extension
必须使用给定的 support
、投票 weight
和投票 params
为 account
注册 proposal_id
的投票。
支持是通用的,可以根据使用的投票系统表示各种内容。 |
has_voted(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool
extension
必须返回帐户是否已对提案进行投票。
clock(self: @ContractState) → u64
extension
返回由 governor 的操作模式确定的当前时间点,旨在用于时间敏感的逻辑- Pending
:提案尚不存在。
- Active
:提案处于活跃状态。
- Canceled
:提案已被取消。
- Defeated
:提案未通过。
- Succeeded
:提案已通过。
- Queued
:提案已进入队列。
- Executed
:提案已执行。
executor(self: @ContractState) → ContractAddress
internal
必须返回 governor 执行操作的地址。 应该用于指定模块是否通过另一个合约(例如时间锁)执行操作。
必须是 governor 本身,或者是将 governor 作为唯一提议者、取消者和执行者的 TimelockController 的实例。 |
当 executor 不是 governor 本身(即时间锁)时,它可以调用受 assert_only_governance 保护的函数,并且还可能代表 governor 执行交易。因此,此模块被设计为与作为唯一潜在外部 executor 的 TimelockController 一起工作。
|
execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)
internal
执行机制。 可用于修改操作的执行方式(例如添加 vault/timelock)。
queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)
internal
排队机制。 可用于修改排队执行的方式 (例如添加 vault/timelock)。
要求:
-
必须返回一个时间戳,描述预期的执行 ETA。 如果返回的 值为 0,则核心将认为排队未成功,并且公共
queue
函数将回退。
cancel_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)
internal
取消机制。 可用于修改取消执行的方式 (例如添加 vault/timelock)。
name() → felt252
external
Governor 实例的名称(用于构建 SNIP-12 域分隔符)。
version() → felt252
external
Governor 实例的版本(用于构建 SNIP-12 域分隔符)。
COUNTING_MODE() → ByteArray
external
对 cast_vote
的可能的 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 被委托进行投票。
该字符串可以被标准的 URLSearchParams
JavaScript 类解码。
|
hash_proposal(calls: Span<Call>, description_hash: felt252) → felt252
external
用于从提案详细信息中(重新)构建提案 id 的散列函数。
proposal_snapshot(proposal_id: felt252) → u64
external
用于检索用户投票和法定人数的时间点。 如果使用区块号,则快照将在 此区块的末尾执行。 因此,对此提案的投票从下一个区块的开始开始。
proposal_deadline(proposal_id: felt252) → u64
external
投票结束的时间点。 如果使用区块号,则投票在此区块的末尾结束,因此 可以在此区块期间进行投票。
proposal_eta(proposal_id: felt252) → u64
external
排队的提案变为可执行的时间(“ETA”)。 与 proposal_snapshot
和
proposal_deadline
不同,这不使用 governor 时钟,而是依赖于
executor 的时钟,该时钟可能不同。 在大多数情况下,这将是一个时间戳。
voting_delay() → u64
external
提案创建时间和投票开始时间之间的延迟。 此持续时间使用的单位 取决于此合约使用的时钟(参见 ERC-6372)。
可以增加此值,以便在提案投票开始之前,用户有时间购买投票权或委托投票权。
voting_period() → u64
external
投票开始和投票结束之间的延迟。 此持续时间使用的单位取决于 此合约使用的时钟(参见 ERC-6372)。
voting_delay 可以延迟投票的开始。 在设置投票持续时间时,必须
考虑投票延迟。
|
此值在提交提案时存储,以便对 该值的可能更改不会影响已提交的提案。 |
quorum(timepoint: u64) → u256
external
提案成功所需的最小票数。
timepoint 参数对应于用于计算投票的快照。 这
允许法定人数根据时间点(例如令牌的总供应量)进行缩放。
|
get_votes(account: ContractAddress, timepoint: u64) → u256
external
返回 account
在特定 timepoint
的投票权。
这可以通过多种方式实现,例如通过从一个(或多个)ERC20Votes 令牌中读取委托的
余额。
|
get_votes_with_params(account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256
external
返回具有附加编码参数的帐户在特定时间点的投票权。
propose(calls: Span<Call>, description: ByteArray) → felt252
external
创建一个新提案。 投票在 voting_delay
指定的延迟后开始,并
持续 voting_period
指定的持续时间。 返回提案的 id。
此函数具有选择加入抢跑保护,如
is_valid_description_for_proposer
中所述。
在提案创建之间, Governor 和目标的状态可能会发生变化 及其执行。 这可能是目标 合约上的第三方行为或其他 governor 提案的结果。 例如,此合约的余额 可能会更新,或者其访问控制权限可能会被修改,这可能会损害 提案成功执行的能力(例如,governor 没有足够的价值 来支付具有多个转移的提案)。 |
要求:
-
提议者必须有权提交提案。
-
如果
proposal_threshold
大于零,则提议者必须有足够的票数来提交提案。 -
提案不得已存在。
发出 ProposalCreated 事件。
queue(calls: Span<Call>, description_hash: felt252) → felt252
external
将提案排队。 一些 governor 要求在执行可以 发生之前执行此步骤。 如果不需要排队,则此函数可能会回退。 对提案进行排队需要达到法定人数,投票成功,并且 达到截止时间。
返回提案的 id。
要求:
-
提案必须处于
Succeeded
状态。 -
队列操作必须返回非零 ETA。
发出 ProposalQueued 事件。
execute(calls: span<Call>, description_hash: felt252) → felt252
external
执行成功的提案。 这需要达到法定人数,投票成功,并且 达到截止时间。 根据 governor 的不同,可能还需要 对提案进行排队并经过一些延迟。
一些模块可以修改执行的要求,例如添加
额外的时间锁(参见 timelock_controller )。
|
返回提案的 id。
要求:
-
提案必须处于
Succeeded
或Queued
状态。
发出 ProposalExecuted 事件。
cancel(calls: Span<Call>, description_hash: felt252) → felt252
external
取消提案。 提案可以由提议者取消,但只能在其 Pending 状态下,即在投票开始之前。
返回提案的 id。
要求:
-
提案必须处于
Pending
状态。 -
调用者必须是提案的提议者。
发出 ProposalCanceled 事件。
cast_vote_with_reason(proposal_id: felt252, support: u8, reason: ByteArray) → u256
external
使用 reason
进行投票。
要求:
-
提案必须处于活动状态。
发出 VoteCast 事件。
cast_vote_with_reason_and_params(proposal_id: felt252, support: u8, reason: ByteArray, params: Span<felt252>) → u256
external
使用 reason
和附加的序列化 params
进行投票。
要求:
-
提案必须处于活动状态。
发出以下事件之一:
-
如果未提供任何参数,则发出 VoteCast 事件。
-
否则,发出 VoteCastWithParams 事件。
cast_vote_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span<felt252>) → u256
external
使用 voter
的签名进行投票。
要求:
-
提案必须处于活动状态。
-
签名消息中的 nonce 必须与帐户的当前 nonce 匹配。
-
voter
必须实现SRC6::is_valid_signature
。 -
signature
对于消息散列必须有效。
发出 VoteCast 事件。
cast_vote_with_reason_and_params_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, reason: ByteArray, params: Span<felt252>, signature: Span<felt252>) → u256
external
使用 voter
的签名,使用 reason
和附加的序列化 params
进行投票。
要求:
-
提案必须处于活动状态。
-
签名消息中的 nonce 必须与帐户的当前 nonce 匹配。
-
voter
必须实现SRC6::is_valid_signature
。 -
signature
对于消息散列必须有效。
发出以下事件之一:
-
如果未提供任何参数,则发出 VoteCast 事件。
-
否则,发出 VoteCastWithParams 事件。
relay(call: Call)
external
将交易或函数调用中继到任意目标。
在 governance 执行器是 governor 本身以外的某个合约的情况下,例如 在使用时间锁时,可以在 governance 提案中调用此函数以恢复 错误发送到 governor 合约的令牌。
如果 executor 只是 governor 本身,则使用 relay 是多余的。
|
is_valid_description_for_proposer(self: @ContractState, proposer: ContractAddress, description: ByteArray) → bool
internal
检查提议者是否有权提交具有给定描述的提案。
如果提案描述以 #proposer=0x???
结尾,其中 0x???
是
以十六进制字符串(不区分大小写)编写的地址,则此提案的提交将
仅授权给所述地址。
这用于抢跑保护。 通过在他们 提案的末尾添加此模式,可以确保没有其他地址可以提交相同的提案。 攻击者 将不得不删除或更改该部分,这将导致不同的 提案 id。
在 Starknet 中,Sequencer 确保交易的顺序,但抢跑 仍然可以通过节点实现,并且未来可能会通过 sequencer 去中心化实现。 |
如果描述与此模式不匹配,则不受限制,任何人都可以提交 它。 这包括:
-
如果
0x???
部分不是有效的十六进制字符串。 -
如果
0x???
部分是有效的十六进制字符串,但不包含正好 64 个十六进制数字。 -
如果它以预期的后缀结尾,后跟换行符或其他空格。
-
如果它以一些其他类似的后缀结尾,例如
#other=abc
。 -
如果它不以任何此类后缀结尾。
_hash_proposal(self: @ContractState, calls: Span<Call>, description_hash: felt252) → felt252
internal
从给定参数计算的提案 id。
提案 id 计算为 Pedersen 哈希值:
-
被提议的调用数组
-
描述哈希
_proposal_snapshot(self: @ContractState, proposal_id: felt252) → u64
internal
用于检索用户投票和法定人数的时间点。 如果使用区块号,则快照 在此区块的末尾执行。 因此,对此提案的投票从 下一个区块的开始开始。
_proposal_deadline(self: @ContractState, proposal_id: felt252) → u64
internal
投票结束的时间点。 如果使用区块号,则投票在此 区块的末尾结束,因此可以在此区块期间进行投票。
_proposal_eta(self: @ContractState, proposal_id: felt252) → u64
internal
排队的提案变为可执行的时间(“ETA”)。 与 proposal_snapshot
和 proposal_deadline
不同,这不使用 governor 时钟,而是依赖于
executor 的时钟,该时钟可能不同。 在大多数情况下,这将是一个时间戳。
assert_only_governance(self: @ContractState)
internal
断言调用者是 governance 执行器。
当 executor 不是 governor 本身(即时间锁)时,它可以调用 受此修饰符限制的函数,并且还可能代表 governor 执行 交易。 因此,此模块被设计为与 TimelockController 作为唯一的潜在外部 executor 一起工作。 时间锁 必须将 governor 作为唯一的提议者、取消者和执行者。 |
validate_state(self: @ContractState, proposal_id: felt252, state: ProposalState)
internal
验证提案是否处于预期状态。 否则会发生 panic。
_get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256
internal
GovernorVotesTrait::get_votes
的内部包装器。
_proposal_threshold(self: @ContractState) → u256
internal
GovernorProposeTrait::proposal_threshold
的内部包装器。
_state(self: @ContractState, proposal_id: felt252) → ProposalState
internal
返回给定 id 的提案的状态。
要求:
-
提案必须存在。
_propose(ref self: ContractState, calls: Span<Call>, description_hash: felt252) → felt252
internal
内部提议机制。 返回提案 id。
要求:
-
提案不得已存在。
发出 ProposalCreated 事件。
_cancel(ref self: ContractState, proposal_id: felt252)
internal
具有最小限制的内部取消机制。
提案可以在除 Canceled 或 Executed 之外的任何状态下取消。
取消后,无法重新提交提案。 |
_count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, weight: u256, params: Span<felt252>)
internal
GovernorCountingTrait::count_vote
的内部包装器。
_cast_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, reason: ByteArray, params: Span<felt252>) → u256
internal
内部投票机制。
检查投票是否待定以及是否尚未进行投票。
此函数使用 get_votes
检索投票权重,然后调用
_count_vote
内部函数。
发出以下事件之一:
-
如果未提供任何参数,则发出 VoteCast 事件。
-
否则,发出 VoteCastWithParams 事件。
ProposalCreated(proposal_id: felt252, proposer: ContractAddress, calls: Span<Call>, signatures: Span<Span<felt252>>, vote_start: u64, vote_end: u64, description: ByteArray)
event
创建提案时发出。
Governor 扩展
Governor 组件可以(并且必须)通过实现 扩展 traits 来扩展,以添加所需的功能。 这可以通过直接在您的合约上实现这些 traits 来实现,或者通过使用库提供的一组现成的扩展来实现, 这些扩展如下所示。
GovernorCoreExecutionComponent
use openzeppelin_governance::governor::extensions::GovernorCoreExecutionComponent;
GovernorComponent 的扩展,提供直接通过 Governor 本身的执行机制。 对于时间锁定的执行机制,请参见 GovernorTimelockExecutionComponent。
state(self: @ContractState, proposal_id: felt252) → ProposalState
internal
返回给定 id 的提案状态。
要求:
-
提案必须存在。
executor(self: @ContractState) → ContractAddress
internal
返回 executor 地址。
在这种情况下,它返回 governor 合约地址,因为执行是直接通过它执行的。
execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252)
internal
直接通过 governor 合约执行提案的操作。
queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252) → u64
internal
在此实现中,不需要排队,因此它返回 0。
GovernorCountingSimpleComponent
use openzeppelin_governance::governor::extensions::GovernorCountingSimpleComponent;
GovernorComponent 的扩展,用于具有三个选项的简单投票计数。
counting_mode(self: @ContractState) → ByteArray
internal
返回 "support=bravo&quorum=for,abstain"
。
-
support=bravo
表示支持遵循 Governor Bravo 格式,其中投票者可以投票赞成、反对或弃权 -
quorum=for,abstain
表示赞成票和弃权票都计入法定人数
count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span<felt252>) → u256
internal
记录提案的投票。
支持值遵循 VoteType
枚举(0=反对、1=赞成、2=弃权)。
返回被计数的权重。
has_voted(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool
internal
返回一个帐户是否已对提案投票。
GovernorSettingsComponent
use openzeppelin_governance::governor::extensions::GovernorSettingsComponent;
GovernorComponent 的扩展,用于可以通过 governance 更新的设置。
==== 扩展 traits 函数
==== voting_delay(self: @ContractState) → u64
internal
返回一个提案被创建到投票开始之间的延迟。
==== voting_period(self: @ContractState) → u64
internal
返回投票可以进行的时间段。
==== proposal_threshold(self: @ContractState) → u256
internal
返回一个账户创建提案所需的最小投票数。
==== 可嵌入函数
==== set_voting_delay(ref self: ContractState, new_voting_delay: u64)
external
设置投票延迟。
要求:
-
调用者必须是 governance executor。
如果新的投票延迟与旧的相同,则此函数不会发出事件。 |
可能会发出一个 VotingDelayUpdated 事件。
==== set_voting_period(ref self: ContractState, new_voting_period: u64)
external
设置投票周期。
如果新的投票周期与旧的周期相同,则此函数不会发出事件 旧的投票周期。 |
要求:
-
调用者必须是 governance executor。
-
new_voting_period
必须大于 0。
可能会发出一个 VotingPeriodUpdated 事件。
==== set_proposal_threshold(ref self: ContractState, new_proposal_threshold: u256)
external
设置提案阈值。
如果新的提案阈值与该阈值相同,则此函数不会发出事件 旧的阈值。 |
要求:
-
调用者必须是 governance executor。
可能会发出一个 ProposalThresholdUpdated 事件。
==== 内部函数
==== initializer(ref self: ContractState, initial_voting_delay: u64, initial_voting_period: u64, initial_proposal_threshold: u256)
internal
通过设置默认值来初始化组件。
要求:
-
new_voting_period
必须大于 0。
==== assert_only_governance(ref self: ContractState)
internal
断言调用者是 governance executor。
==== _set_voting_delay(ref self: ContractState, new_voting_delay: u64)
internal
用于更新投票延迟的内部函数。
如果新的投票延迟与该延迟相同,则此函数不会发出事件 旧的那个。 |
可能会发出一个 VotingDelayUpdated 事件。
==== _set_voting_period(ref self: ContractState, new_voting_period: u64)
internal
用于更新投票周期的内部函数。
要求:
-
new_voting_period
必须大于 0。
如果新的投票周期与旧的周期相同,则此函数不会发出事件。 |
可能会发出一个 VotingPeriodUpdated 事件。
==== _set_proposal_threshold(ref self: ContractState, new_proposal_threshold: u256)
internal
用于更新提案阈值的内部函数。
如果新的提案阈值与旧的阈值相同,则此函数不会发出事件。 |
可能会发出一个 ProposalThresholdUpdated 事件。
==== 事件
==== VotingDelayUpdated(old_voting_delay: u64, new_voting_delay: u64)
event
当投票延迟更新时发出。
==== VotingPeriodUpdated(old_voting_period: u64, new_voting_period: u64)
event
当投票周期更新时发出。
==== ProposalThresholdUpdated(old_proposal_threshold: u256, new_proposal_threshold: u256)
event
当提案阈值更新时发出。
use openzeppelin_governance::governor::extensions::GovernorVotesComponent;
GovernorComponent 的扩展,用于从具有 IVotes 的 token 中提取投票权重 扩展。
==== 扩展 traits 函数
==== clock(self: @ContractState) → u64
internal
返回由 governor 的操作模式确定的当前时间点,旨在用于对时间敏感的逻辑。 参见 ERC-6372#clock。
要求:
-
此函数必须始终是非递减的。
==== CLOCK_MODE(self: @ContractState) → ByteArray
internal
返回对 governor 正在运行的时钟的描述。 参见 ERC-6372#CLOCK_MODE。
要求:
-
输出的格式必须像 URL 查询字符串,可以在标准 JavaScript 中解码。
==== get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256
internal
使用 votes token 返回 account
在特定 timepoint
的投票权。
==== 可嵌入函数
==== token(self: @ContractState) → ContractAddress
external
返回投票权来源的 votes token。
==== 内部函数
==== initializer(ref self: ContractState, votes_token: ContractAddress)
internal
通过设置 votes token 来初始化组件。
要求:
-
votes_token
不能为零。
use openzeppelin_governance::governor::extensions::GovernorVotesQuorumFractionComponent;
GovernorComponent 的扩展,用于从具有 IVotes 扩展的 token 中提取投票权重,以及以总供应量的一部分表示的法定人数。
==== 扩展 traits 函数
==== quorum(self: @ContractState, timepoint: u64) → u256
internal
它被计算为过去给定 timepoint
的 votes token 总供应量的百分比。
==== clock(self: @ContractState) → u64
internal
返回由 governor 的操作模式确定的当前时间点,旨在用于对时间敏感的逻辑。 参见 ERC-6372#clock。
要求:
-
此函数必须始终是非递减的。
==== CLOCK_MODE(self: @ContractState) → ByteArray
internal
返回对 governor 正在运行的时钟的描述。 参见 ERC-6372#CLOCK_MODE。
要求:
-
输出的格式必须像 URL 查询字符串,可以在标准 JavaScript 中解码。
==== get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256
internal
使用 votes token 返回 account
在特定 timepoint
的投票权。
==== 可嵌入函数
==== token(self: @ContractState) → ContractAddress
external
返回用于提取投票权的 votes token 的地址。
==== current_quorum_numerator(self: @ContractState) → u256
external
返回当前的 quorum numerator 值。
==== quorum_numerator(self: @ContractState, timepoint: u64) → u256
external
返回过去特定 timepoint
的 quorum numerator 值。
==== quorum_denominator(self: @ContractState) → u256
external
返回 quorum denominator 值。
==== 内部函数
==== initializer(self: @ComponentState<TContractState>, votes_token: ContractAddress, quorum_numerator: u256)
internal
通过设置 votes token 和初始 quorum numerator 值来初始化组件。
要求:
-
votes_token
不能为零。 -
quorum_numerator
必须小于quorum_denominator
。
发出一个 QuorumNumeratorUpdated 事件。
==== update_quorum_numerator(self: @ComponentState<TContractState>, new_quorum_numerator: u256)
internal
更新 quorum numerator。
如果新的 quorum numerator 与旧的相同,则此函数不会发出事件。 |
要求:
-
new_quorum_numerator
必须小于quorum_denominator
。
可能会发出一个 QuorumNumeratorUpdated 事件。
==== 事件
==== QuorumNumeratorUpdated(old_quorum_numerator: u256, new_quorum_numerator: u256)
event
当 quorum numerator 更新时发出。
use openzeppelin_governance::governor::extensions::GovernorTimelockExecutionComponent;
GovernorComponent 的扩展,它将执行过程绑定到实现 TimelockControllerComponent 的合约实例。这增加了由 timelock 强制执行的延迟, 对于所有成功的提案(除了投票持续时间)。
Governor 需要 PROPOSER、EXECUTOR 和 CANCELLER 角色 才能正常工作。 |
使用此模型意味着提案将由 timelock 操作,而不是由 governor 操作。因此,资产和权限必须附加到 timelock。发送给 governor 的任何资产都无法从提案访问,除非通过 Governor::relay
执行。
将 timelock 设置为除了 governor 之外还有其他提议者或取消者是非常危险的,因为它授予了他们以下能力:1) 以 timelock 的身份执行操作,因此可能会执行操作或访问预计只能通过投票访问的资金,以及 2) 阻止已获得选民批准的治理提案,从而有效地执行拒绝服务攻击。 |
==== 扩展 traits 函数
==== state(self: @ContractState, proposal_id: felt252) → ProposalState
internal
返回给定 id 的提案状态。
要求:
-
提案必须存在。
==== executor(self: @ContractState) → ContractAddress
internal
返回 executor 地址。
在此模块中,executor 是 timelock controller。
==== execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252)
internal
通过 timelock 运行已排队的提案。
==== queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252) → u64
internal
将提案排队到 timelock。
返回已排队提案执行的 eta。
==== proposal_needs_queuing(self: @ContractState, proposal_id: felt252) → bool
internal
在此实现中,它始终返回 true。
==== cancel_operations(ref self: ContractState, proposal_id: felt252, description_hash: felt252)
internal
如果已经排队,则取消 timelock 的提案。
==== 可嵌入函数
==== timelock(self: @ContractState) → ContractAddress
external
返回 timelock controller 地址。
==== get_timelock_id(self: @ContractState) → felt252
external
返回给定提案 id 的 timelock 提案 id。
==== update_timelock(ref self: ContractState, new_timelock: ContractAddress)
external
更新关联的 timelock。
要求:
-
调用者必须是 governance。
发出一个 TimelockUpdated 事件。
==== 内部函数
==== initializer(ref self: ContractState, timelock: ContractAddress)
internal
初始化 timelock controller。
要求:
-
timelock 不能为零地址。
==== assert_only_governance(self: @ContractState)
internal
确保调用者是 executor(在本例中为 timelock controller)。
==== timelock_salt(self: @ContractState, description_hash: felt252) → felt252
internal
将 TimelockController
操作 salt 计算为 governor 地址和 description_hash
的 XOR。
它使用 governor 地址本身进行计算,以避免跨 governor 实例使用相同的 timelock 发生冲突。
==== get_timelock_dispatcher(self: @ContractState) → ITimelockDispatcher
internal
返回用于与 timelock controller 交互的 dispatcher。
==== _update_timelock(ref self: ContractState, new_timelock: ContractAddress)
internal
用于更新 timelock controller 地址的内部函数。
发出一个 TimelockUpdated 事件。
==== 事件
==== TimelockUpdated(old_timelock: ContractAddress, new_timelock: ContractAddress)
event
当 timelock controller 更新时发出。
== Multisig
Multisig 模块通过要求多个签名者批准和执行交易来增强安全性并实现去中心化。功能包括可配置的法定人数、签名者管理和自我管理,确保关键操作的集体决策和透明度。
use openzeppelin_governance::multisig::interface::IMultisig;
Multisig 合约的接口。
==== 函数
==== get_quorum() → u32
external
返回当前的法定人数值。法定人数是批准交易所需的最小确认数。
==== is_signer(signer: ContractAddress) → bool
external
返回给定的 signer
是否已在注册。只有注册的签名者才能提交、确认或执行交易。
==== get_signers() → Span<ContractAddress>
external
返回所有当前签名者的列表。
==== is_confirmed(id: TransactionID) → bool
external
返回是否已确认具有给定 id
的交易。
==== is_confirmed_by(id: TransactionID, signer: ContractAddress) → bool
external
返回具有给定 id
的交易是否已由指定的 signer
确认。
==== is_executed(id: TransactionID) → bool
external
返回是否已执行具有给定 id
的交易。
==== get_submitted_block(id: TransactionID) → u64
external
返回提交具有给定 id
的交易时所在的区块号。
==== get_transaction_state(id: TransactionID) → TransactionState
external
返回具有给定 id
的交易的当前状态。
==== get_transaction_confirmations(id: TransactionID) → u32
external
返回来自已注册的签名者、对具有指定 id
的交易的确认数。
==== hash_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252) → TransactionID
external
返回包含单个调用的交易的计算标识符。
==== `hash_transaction_batch++(calls: Span<Call>, salt: felt如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== replace_signer(signer_to_remove: ContractAddress, signer_to_add: ContractAddress)
external
用新的签名者替换现有的签名者。
要求:
-
调用者必须是合约本身。
-
signer_to_remove
必须是现有的签名者。 -
signer_to_add
不能是现有的签名者。
为被移除的签名者发出 SignerRemoved 事件。
为新的签名者发出 SignerAdded 事件。
==== change_quorum(new_quorum: u32)
external
如果 new_quorum
与当前仲裁人数不同,则将仲裁人数更新为 new_quorum
。
要求:
-
调用者必须是合约本身。
-
new_quorum
必须为非零值。 -
new_quorum
必须小于或等于签名者的总数。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== submit_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252) → TransactionID
external
提交一个新的交易以供确认。
要求:
-
调用者必须是已注册的签名者。
-
这笔交易之前不能被提交过。
发出 TransactionSubmitted 事件。
如果 salt
不为零,则发出 CallSalt 事件。
==== submit_transaction_batch(calls: Span<Call>, salt: felt252) → TransactionID
external
提交一个新的批量交易以供确认。
要求:
-
调用者必须是已注册的签名者。
-
这笔交易之前不能被提交过。
发出 TransactionSubmitted 事件。
如果 salt
不为零,则发出 CallSalt 事件。
==== confirm_transaction(id: TransactionID)
external
确认具有给定 id
的交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须存在且未被执行。
-
调用者之前不能确认过该交易。
发出 TransactionConfirmed 事件。
==== revoke_confirmation(id: TransactionID)
external
撤销先前对具有给定 id
的交易的确认。
要求:
-
交易必须存在且未被执行。
-
调用者之前必须确认过该交易。
发出 ConfirmationRevoked 事件。
==== execute_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)
external
执行已确认的交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须被确认且尚未执行。
发出 TransactionExecuted 事件。
==== execute_transaction_batch(calls: Span<Call>, salt: felt252)
external
执行已确认的批量交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须被确认且尚未执行。
发出 TransactionExecuted 事件。
==== 事件
==== SignerAdded(signer: ContractAddress)
event
当添加新的 signer
时发出。
==== SignerRemoved(signer: ContractAddress)
event
当 signer
被移除时发出。
==== QuorumUpdated(old_quorum: u32, new_quorum: u32)
event
当 quorum
值更新时发出。
==== TransactionSubmitted(id: TransactionID, signer: ContractAddress)
event
当新的交易由 signer
提交时发出。
==== TransactionConfirmed(id: TransactionID, signer: ContractAddress)
event
当交易被 signer
确认时发出。
==== ConfirmationRevoked(id: TransactionID, signer: ContractAddress)
event
当 signer
撤销其确认时发出。
==== TransactionExecuted(id: TransactionID)
event
当交易被执行时发出。
==== CallSalt(id: felt252, salt: felt252)
event
当提交带有非零 salt 的新交易时发出。
=== MultisigComponent
use openzeppelin_governance::multisig::MultisigComponent;
实现了 IMultisig 并为多重签名钱包提供功能的组件, 包括交易管理、仲裁处理和签名者操作。
==== 可嵌入的函数
==== get_quorum(self: @ContractState) → u32
external
返回当前的仲裁人数值。
==== is_signer(self: @ContractState, signer: ContractAddress) → bool
external
检查给定的 signer
是否已注册。
==== get_signers(self: @ContractState) → Span<ContractAddress>
external
返回所有当前签名者的列表。
==== is_confirmed(self: @ContractState, id: TransactionID) → bool
external
返回具有给定 id
的交易是否已确认。 已确认的交易已收到所需的确认数量(仲裁人数)。
==== is_confirmed_by(self: @ContractState, id: TransactionID, signer: ContractAddress) → bool
external
返回具有给定 id
的交易是否已由指定的 signer
确认。
==== is_executed(self: @ContractState, id: TransactionID) → bool
external
返回具有给定 id
的交易是否已执行。
==== get_submitted_block(self: @ContractState, id: TransactionID) → u64
external
返回提交具有给定 id
的交易时的区块号。
==== get_transaction_state(self: @ContractState, id: TransactionID) → TransactionState
external
返回具有给定 id
的交易的当前状态。
可能的状态为:
-
NotFound
:交易不存在。 -
Pending
:交易存在但尚未达到所需的确认数。 -
Confirmed
:交易已达到所需的确认数但尚未执行。 -
Executed
:交易已执行。
==== get_transaction_confirmations(self: @ContractState, id: TransactionID) → u32
external
返回来自已注册签名者的、用于指定 id
的交易的确认数。
==== hash_transaction(self: @ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)
external
返回包含单个调用的交易的计算标识符。
==== hash_transaction_batch(self: @ContractState, calls: Span<Call>, salt: felt252)
external
返回包含一批调用的交易的计算标识符。
==== add_signers(ref self: ContractState, new_quorum: u32, signers_to_add: Span<ContractAddress>)
external
添加新的签名者并更新仲裁人数。
要求:
-
调用者必须是合约本身。
-
new_quorum
必须小于或等于添加后签名者的总数。
为每个添加的签名者发出 SignerAdded 事件。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== remove_signers(ref self: ContractState, new_quorum: u32, signers_to_remove: Span<ContractAddress>)
external
移除签名者并更新仲裁人数。
要求:
-
调用者必须是合约本身。
-
new_quorum
必须小于或等于移除后签名者的总数。
为每个移除的签名者发出 SignerRemoved 事件。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== replace_signer(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)
external
用新的签名者替换现有的签名者。
要求:
-
调用者必须是合约本身。
-
signer_to_remove
必须是现有的签名者。 -
signer_to_add
不能是现有的签名者。
为被移除的签名者发出 SignerRemoved 事件。
为新的签名者发出 SignerAdded 事件。
==== change_quorum(ref self: ContractState, new_quorum: u32)
external
将仲裁人数值更新为 new_quorum
。
要求:
-
调用者必须是合约本身。
-
new_quorum
必须为非零值。 -
new_quorum
必须小于或等于签名者的总数。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== submit_transaction(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)
external
提交一个新的交易以供确认。
要求:
-
调用者必须是已注册的签名者。
-
这笔交易之前不能被提交过。
发出 TransactionSubmitted 事件。
如果 salt
不为零,则发出 CallSalt 事件。
==== submit_transaction_batch(ref self: ContractState, calls: Span<Call>, salt: felt252)
external
提交一个新的批量交易以供确认。
要求:
-
调用者必须是已注册的签名者。
-
这笔交易之前不能被提交过。
发出 TransactionSubmitted 事件。
如果 salt
不为零,则发出 CallSalt 事件。
==== confirm_transaction(ref self: ContractState, id: TransactionID)
external
确认具有给定 id
的交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须存在且未被执行。
-
调用者之前不能确认过该交易。
发出 TransactionConfirmed 事件。
==== revoke_confirmation(ref self: ContractState, id: TransactionID)
external
撤销先前对具有给定 id
的交易的确认。
要求:
-
交易必须存在且未被执行。
-
调用者之前必须确认过该交易。
发出 ConfirmationRevoked 事件。
==== execute_transaction(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)
external
执行已确认的交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须被确认且尚未执行。
发出 TransactionExecuted 事件。
==== execute_transaction_batch(ref self: ContractState, calls: Span<Call>, salt: felt252)
external
执行已确认的批量交易。
要求:
-
调用者必须是已注册的签名者。
-
交易必须被确认且尚未执行。
发出 TransactionExecuted 事件。
==== 内部函数
==== initializer(ref self: ContractState, quorum: u32, signers: Span<ContractAddress>)
internal
使用初始 quorum
和 signers
初始化 Multisig 组件。
必须在合约初始化期间调用此函数以设置初始状态。
要求:
-
quorum
必须为非零值,且小于或等于signers
的数量。
为每个添加的签名者发出 SignerAdded 事件。
发出 QuorumUpdated 事件。
==== resolve_tx_state(self: @ContractState, id: TransactionID) → TransactionState
internal
解析并返回具有给定 id
的交易的当前状态。
可能的状态为:
-
NotFound
:交易不存在。 -
Pending
:交易存在但尚未达到所需的确认数。 -
Confirmed
:交易已达到所需的确认数但尚未执行。 -
Executed
:交易已执行。
==== assert_one_of_signers(self: @ContractState, caller: ContractAddress)
internal
断言 caller
是已注册的签名者之一。
要求:
-
caller
必须是已注册的签名者。
==== assert_tx_exists(self: @ContractState, id: TransactionID)
internal
断言具有给定 id
的交易存在。
要求:
-
具有给定
id
的交易必须已提交。
==== assert_only_self(self: @ContractState)
internal
断言调用者是合约本身。
要求:
-
调用者必须是合约自身的地址。
==== _add_signers(ref self: ContractState, new_quorum: u32, signers_to_add: Span<ContractAddress>)
internal
添加新的签名者并更新仲裁人数。
要求:
-
每个签名者地址都不能为零。
-
new_quorum
必须为非零值,且小于或等于添加后签名者的总数。
为每个新添加的签名者发出 SignerAdded 事件。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== _remove_signers(ref self: ContractState, new_quorum: u32, signers_to_remove: Span<ContractAddress>)
internal
移除现有的签名者并更新仲裁人数。
要求:
-
new_quorum
必须为非零值,且小于或等于移除后签名者的总数。
为每个移除的签名者发出 SignerRemoved 事件。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== _replace_signer(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)
internal
用新的签名者替换现有的签名者。
要求:
-
signer_to_remove
必须是现有的签名者。 -
signer_to_add
不能是现有的签名者。 -
signer_to_add
必须是非零地址。
为被移除的签名者发出 SignerRemoved 事件。
为新的签名者发出 SignerAdded 事件。
==== _change_quorum(ref self: ContractState, new_quorum: u32)
internal
如果 new_quorum
与当前仲裁人数不同,则将仲裁人数值更新为 new_quorum
。
要求:
-
new_quorum
必须为非零值。 -
new_quorum
必须小于或等于签名者的总数。
如果仲裁人数发生变化,则发出 QuorumUpdated 事件。
==== 事件
==== SignerAdded(signer: ContractAddress)
event
当添加新的 signer
时发出。
==== SignerRemoved(signer: ContractAddress)
event
当 signer
被移除时发出。
==== QuorumUpdated(old_quorum: u32, new_quorum: u32)
event
当 quorum
值更新时发出。
==== TransactionSubmitted(id: TransactionID, signer: ContractAddress)
event
当新的交易由 signer
提交时发出。
==== TransactionConfirmed(id: TransactionID, signer: ContractAddress)
event
当交易被 signer
确认时发出。
==== ConfirmationRevoked(id: TransactionID, signer: ContractAddress)
event
当 signer
撤销其确认时发出。
==== TransactionExecuted(id: TransactionID)
event
当交易被执行时发出。
==== CallSalt(id: felt252, salt: felt252)
event
当提交带有非零 salt 的新交易时发出。
== 时间锁
在治理系统中,TimelockControllerComponent
负责在提案和执行之间引入延迟。
use openzeppelin_governance::timelock::interface::ITimelock;
时间锁合约的接口。
==== 函数
==== is_operation(id: felt252) → bool
external
返回 id
是否对应于已注册的操作。
这包括 OperationStates: Waiting
,Ready
和 Done
。
==== is_operation_pending(id: felt252) → bool
external
返回 id
OperationState 是否为待处理。
请注意,待处理的操作可能是 Waiting
或 Ready
。
==== is_operation_ready(id: felt252) → bool
external
返回 id
OperationState 是否为 Ready
。
==== is_operation_done(id: felt252) → bool
external
返回 id
OperationState 是否为 Done
。
==== get_timestamp(id: felt252) → u64
external
返回 id
变为 Ready
的时间戳。
注意:0
表示 OperationState 为 Unset
,1
表示 OperationState 为 Done
。
==== get_operation_state(id: felt252) → OperationState- 调用者必须具有 `PROPOSER_ROLE
角色。
触发 CallScheduled 事件。
如果 salt
非零,则触发 CallSalt 事件。
==== schedule_batch(calls: Span<Call>, predecessor: felt252, salt: felt252, delay: u64)
external
安排一个包含一批事务的操作。
要求:
-
调用者必须具有
PROPOSER_ROLE
角色。
为批处理中的每个事务触发一个 CallScheduled 事件。
如果 salt
非零,则触发 CallSalt 事件。
==== cancel(id: felt252)
external
取消一个操作。已取消的操作将返回到 Unset
OperationState。
要求:
-
调用者必须具有
CANCELLER_ROLE
角色。 -
id
必须是待处理的操作。
触发一个 CallCancelled 事件。
==== execute(call: Call, predecessor: felt252, salt: felt252)
external
执行一个(准备就绪)操作,其中包含单个 Call。
要求:
-
调用者必须具有
EXECUTOR_ROLE
。 -
id
必须处于 Ready OperationState。 -
predecessor
必须是0
或处于 Done OperationState。
触发一个 CallExecuted 事件。
此函数可以重入,但它不会带来风险,因为 [TimelockControllerComponent-_after_call] 检查提案是否待处理,因此在重入期间对操作的任何修改都应被捕获。 |
==== execute_batch(calls: Span<Call>, predecessor: felt252, salt: felt252)
external
执行一个(准备就绪)操作,其中包含一批 Calls。
要求:
-
调用者必须具有
EXECUTOR_ROLE
。 -
id
必须处于 Ready OperationState。 -
predecessor
必须是0
或处于 Done OperationState。
为每个 Call 触发一个 CallExecuted 事件。
此函数可以重入,但它不会带来风险,因为 _after_call
检查提案是否待处理,因此在重入期间对操作的任何修改都应被捕获。
|
==== update_delay(new_delay: u64)
external
更改未来操作的最小时间锁持续时间。
要求:
-
调用者必须是时间锁本身。这只能通过调度来实现 并在稍后执行一个操作,其中时间锁是目标,数据 是对该函数的序列化调用。
触发一个 MinDelayChanged 事件。
==== 事件
==== CallScheduled(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64)
event
当 call
作为操作 id
的一部分被调度时触发。
==== CallExecuted(id: felt252, index: felt252, call: Call)
event
当 call
作为操作 id
的一部分执行时触发。
==== CallSalt(id: felt252, salt: felt252)
event
当使用非零 salt 调度新提案时触发。
==== CallCancelled(id: felt252)
event
当操作 id
被取消时触发。
==== MinDelayChanged(old_duration: u64, new_duration: u64)
event
当修改未来操作的最小延迟时触发。
use openzeppelin_governance::timelock::TimelockControllerComponent;
实现 ITimelock 并使实现合约充当时间锁控制器的组件。
==== 可嵌入的函数
==== is_operation(self: @ContractState, id: felt252) → bool
external
返回 id
是否对应于已注册的操作。
这包括 OperationStates:Waiting
、Ready
和 Done
。
==== is_operation_pending(self: @ContractState, id: felt252) → bool
external
返回 id
OperationState 是否待处理。
请注意,待处理的操作可以是 Waiting
或 Ready
。
==== is_operation_ready(self: @ContractState, id: felt252) → bool
external
返回 id
OperationState 是否为 Ready
。
==== is_operation_done(self: @ContractState, id: felt252) → bool
external
返回 id
OperationState 是否为 Done
。
==== get_timestamp(self: @ContractState, id: felt252) → u64
external
返回 id
变为 Ready
的时间戳。
0 表示 OperationState 为 Unset ,1 表示 OperationState
为 Done 。
|
==== get_operation_state(self: @ContractState, id: felt252) → OperationState
external
返回具有给定 id
的操作的当前状态。
可能的状态有:
-
Unset
: 操作尚未安排或已取消。 -
Waiting
: 操作已安排,并且正在等待安排的延迟。 -
Ready
: 计时器已过期,该操作符合执行条件。 -
Done
: 操作已执行。
==== get_min_delay(self: @ContractState) → u64
external
返回操作变为有效的最小延迟(以秒为单位)。
可以通过执行调用 update_delay
的操作来更改此值。
==== hash_operation(self: @ContractState, call: Call, predecessor: felt252, salt: felt252)
external
返回包含单个事务的操作的标识符。
==== hash_operation_batch(self: @ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252)
external
返回包含一批事务的操作的标识符。
==== schedule(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252, delay: u64)
external
安排一个包含单个事务的操作。
要求:
-
调用者必须具有
PROPOSER_ROLE
角色。 -
提案不得已存在。
-
delay
必须大于或等于最小延迟。
触发 CallScheduled 事件。
如果 salt
非零,则触发 CallSalt 事件。
==== schedule_batch(ref self: ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252, delay: u64)
external
安排一个包含一批事务的操作。
要求:
-
调用者必须具有
PROPOSER_ROLE
角色。 -
提案不得已存在。
-
delay
必须大于或等于最小延迟。
为批处理中的每个事务触发一个 CallScheduled 事件。
如果 salt
非零,则触发 CallSalt 事件。
==== cancel(ref self: ContractState, id: felt252)
external
取消一个操作。已取消的操作将返回到 Unset
OperationState。
要求:
-
调用者必须具有
CANCELLER_ROLE
角色。 -
id
必须是待处理的操作。
触发一个 CallCancelled 事件。
==== execute(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252)
external
执行一个(准备就绪)操作,其中包含单个 Call。
要求:
-
调用者必须具有
EXECUTOR_ROLE
。 -
id
必须处于 Ready OperationState。 -
predecessor
必须是0
或处于 Done OperationState。
触发一个 CallExecuted 事件。
此函数可以重入,但它不会带来风险,因为 [TimelockControllerComponent-_after_call] 检查提案是否待处理,因此在重入期间对操作的任何修改都应被捕获。 |
==== execute_batch(ref self: ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252)
external
执行一个(准备就绪)操作,其中包含一批 Calls。
要求:
-
调用者必须具有
EXECUTOR_ROLE
。 -
id
必须处于 Ready OperationState。 -
predecessor
必须是0
或处于 Done OperationState。
为每个 Call 触发一个 CallExecuted 事件。
此函数可以重入,但它不会带来风险,因为 _after_call
检查提案是否待处理,因此在重入期间对操作的任何修改都应被捕获。
|
==== update_delay(ref self: ContractState, new_delay: u64)
external
更改未来操作的最小时间锁持续时间。
要求:
-
调用者必须是时间锁本身。这只能通过调度来实现 并在稍后执行一个操作,其中时间锁是目标,数据 是对该函数的序列化调用。
触发一个 MinDelayChanged 事件。
==== 内部函数
==== initializer(ref self: ContractState, min_delay: u64, proposers: Span<ContractAddress>, executors: Span<ContractState>, admin: ContractAddress)
internal
通过注册对 SRC5 和 AccessControl 的支持来初始化合约。
此函数还使用以下参数配置合约:
-
min_delay
:操作的初始最小延迟(以秒为单位)。 -
proposers
:要授予提案者和取消者角色的帐户。 -
executors
:要授予执行者角色的帐户。 -
admin
:可选帐户,用于授予管理员角色;使用零地址禁用。
可选的管理员可以帮助在部署后进行角色的初始配置,而无需延迟,但应随后放弃此角色,以支持 通过时间锁提案进行管理。 |
为 proposers
中的每个帐户触发两个 IAccessControl::RoleGranted 事件,其中包含 PROPOSER_ROLE
和
CANCELLER_ROLE
角色。
为 executors
中的每个帐户触发一个 IAccessControl::RoleGranted 事件,其中包含 EXECUTOR_ROLE
角色。
可能会为 admin
触发一个带有 DEFAULT_ADMIN_ROLE
角色的 IAccessControl::RoleGranted 事件(如果 admin
是
非零)。
触发 MinDelayChanged 事件。
==== assert_only_role(self: @ContractState, role: felt252)
internal
验证调用者是否具有给定的 role
。
否则会panic。
==== assert_only_role_or_open_role(self: @ContractState, role: felt252)
internal
验证调用者是否具有给定的 role
。
如果 role
被授予零地址,则这被认为是开放角色,允许任何人成为调用者。
==== assert_only_self(self: @ContractState)
internal
验证调用者是否是时间锁合约本身。 否则会panic。
==== _before_call(self: @ContractState, id: felt252, predecessor: felt252)
internal
在执行操作的调用之前检查的私有函数。
要求:
-
id
必须处于Ready
OperationState。 -
predecessor
必须为零或处于Done
OperationState。
==== _after_call(self: @ContractState, id: felt252)
internal
在执行操作的调用之后检查的私有函数
并将 id
的 OperationState 设置为 Done
。
要求:
-
id
必须处于 Ready OperationState。
==== _schedule(ref self: ContractState, id: felt252, delay: u64)
internal
在给定的 delay
之后安排将变为有效的操作的私有函数。
==== _execute(ref self: ContractState, call: Call)
internal
执行操作调用的私有函数。
==== 事件
==== CallScheduled(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64)
event
当 call
作为操作 id
的一部分被调度时触发。
==== CallExecuted(id: felt252, index: felt252, call: Call)
event
当 call
作为操作 id
的一部分执行时触发。
==== CallSalt(id: felt252, salt: felt252)
event
当使用非零 salt 调度新提案时触发。
==== CallCancelled(id: felt252)
event
当操作 id
被取消时触发。
==== MinDelayChanged(old_duration: u64, new_duration: u64)
event
当修改未来操作的最小延迟时触发。
== 投票
VotesComponent
提供了一个灵活的系统来跟踪和委托投票权。该系统允许用户将其投票权委托给其他地址,从而实现更积极地参与治理。
use openzeppelin_governance::votes::interface::IVotes;
启用投票的合约的通用接口。
==== 函数
==== get_votes(account: ContractAddress) → u256
external
返回 account
当前拥有的票数。
==== get_past_votes(account: ContractAddress, timepoint: u64) → u256
external
返回 account
在过去的特定时刻拥有的票数。
==== get_past_total_supply(timepoint: u64) → u256
external
返回过去特定时刻可用的投票总数。
此值是所有可用投票的总和,不一定是所有已委派投票的总和。 尚未委派的投票仍然是总供应的一部分,即使它们不会参与投票。 |
==== delegates(account: ContractAddress) → ContractAddress
external
返回 account
选择的代理。
==== delegate(delegatee: ContractAddress)
external
将投票从发送者委托给 delegatee
。
==== delegate_by_sig(delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span<felt252>)
external
通过 SNIP-12 消息签名验证将投票从 delegator
委托给 delegatee
。
==== clock() → u64
external
返回由合约的运行模式确定的当前时间点,旨在用于时间敏感的逻辑。 请参阅 ERC-6372#clock。
要求:
-
此函数必须始终是非递减的。
==== CLOCK_MODE() → u64
external
返回对合约运行的时钟的描述。 请参阅 ERC-6372#CLOCK_MODE。
要求:
-
输出的格式必须类似于 URL 查询字符串,可以在标准 JavaScript 中解码。
use openzeppelin_governance::votes::VotesComponent;
实现 IVotes 接口并提供灵活的系统来跟踪和委托投票权的组件。
默认情况下,令牌余额不考虑投票权。这使得转移更便宜。缺点是它要求用户委托给自己才能激活检查点并跟踪他们的投票权。
使用此模块时,您的合约必须实现 VotingUnitsTrait。为方便起见,ERC20 和 ERC721 令牌会自动执行此操作。
|
==== ERC20VotesImpl
==== get_voting_units(self: @ContractState, account: ContractAddress) → u256
internal
返回给定帐户的投票单位数。
此实现特定于 ERC20 令牌,其中余额 令牌直接表示投票单位的数量。
如果 ERC20 组件在最终合约中实现,则此实现将开箱即用。 |
此实现假定令牌以 1:1 的比例映射到投票单位。 当转移投票单位时(例如,通过使用钩子)对该公式的任何偏离 可能会危及内部投票核算。 |
==== ERC721VotesImpl
==== get_voting_units(self: @ContractState, account: ContractAddress) → u256
internal
返回给定帐户的投票单位数。
此实现特定于 ERC721 令牌,其中每个令牌 表示一个投票单位。该函数返回以下余额 指定帐户的 ERC721 令牌。
如果 ERC721 组件在最终合约中实现,则此实现将开箱即用。 |
此实现假定令牌以 1:1 的比例映射到投票单位。 当转移投票单位时(例如,通过使用钩子)对该公式的任何偏离 可能会危及内部投票核算。 |
==== 可嵌入的函数
==== `get_votes++(self: @ContractState[.contract-item]
==== delegate_by_sig(ref self: ContractState, delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span<felt252>)
external
通过 SNIP-12 消息签名验证,将来自 delegator
的投票委托给 delegatee
。
要求:
-
expiry
不能是过去的时间。 -
nonce
必须与帐户的当前 nonce 匹配。 -
delegator
必须实现SRC6::is_valid_signature
。 -
signature
应该对消息哈希有效。
发出 DelegateChanged 事件。
可能会发出一个或两个 DelegateVotesChanged 事件。
==== clock(self: @ContractState) → u64
external
返回由合约的运行模式确定的当前时间点,旨在用于时间敏感的逻辑。 参见 ERC-6372#clock。
要求:
-
此函数必须始终是非递减的。
==== CLOCK_MODE(self: @ContractState) → u64
external
返回对合约运行时间的描述。 参见 ERC-6372#CLOCK_MODE。
要求:
-
输出的格式必须类似于 URL 查询字符串,可以在标准 JavaScript 中解码。
==== 内部函数
==== get_total_supply(self: @ContractState) → u256
internal
返回当前投票总供应量。
==== move_delegate_votes(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)
internal
将委托的投票从一个委托人转移到另一个委托人。
可能会发出一个或两个 DelegateVotesChanged 事件。
==== transfer_voting_units(ref self: ContractState, from: ContractAddress, to: ContractAddress, amount: u256)
internal
转移、铸造或销毁投票单位。
要注册铸币,from
应该为零。要注册销毁,to
应该为零。投票单位的总供应量将通过铸币和销毁进行调整。
如果投票单位基于底层可转让资产(如 token),则每次转移资产时都必须调用此函数,以使内部投票权核算保持同步。对于 ERC20 和 ERC721 token,这通常使用钩子来处理。 |
可能会发出一个或两个 DelegateVotesChanged 事件。
==== num_checkpoints(self: @ContractState, account: ContractAddress) → u64
internal
返回 account
的检查点数量。
==== checkpoints(self: @ContractState, account: ContractAddress, pos: u64) → Checkpoint
internal
返回 account
的第 pos
个检查点。
==== _delegate(ref self: ContractState, account: ContractAddress, delegatee: ContractAddress)
internal
将 account
的所有投票单位委托给 delegatee
。
发出 DelegateChanged 事件。
可能会发出一个或两个 DelegateVotesChanged 事件。
==== 事件
==== DelegateChanged(delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress)
event
当帐户更改其委托人时发出。
==== DelegateVotesChanged(delegate: ContractAddress, previous_votes: u256, new_votes: u256)
event
当 token 转移或委托更改导致委托人的投票数量发生变化时发出。
pub trait VotingUnitsTrait<TState> {
fn get_voting_units(self: @TState, account: ContractAddress) -> u256;
}
一个 trait,当将 VotesComponent 集成到合约中时必须实现。它提供了一种机制来检索给定帐户在当前时间的投票单位数量。
==== 函数
==== get_voting_units(self: @TState, account: ContractAddress) → u256
external
返回给定帐户的投票单位数量。对于 ERC20,这通常是 token 余额。对于 ERC721,这通常是拥有的 token 数量。
虽然任何公式都可以用作投票单位的衡量标准,但如果投票单位通过遵循不同公式的任何外部流程进行转移,则合约的内部投票核算可能会受到影响。 例如,在实现 ERC20 的钩子时,转移的投票单位数量应与 get_voting_units 实现给出的公式相匹配。
|