Governance
This crate includes primitives for on-chain governance.
Timelock
In a governance system, TimelockControllerComponent is in charge of introducing a delay between a proposal and its execution.
ITimelock
use openzeppelin_governance::timelock::interface::ITimelock;
Interface of a timelock contract.
is_operation(id: felt252) → bool external
Returns whether id corresponds to a registered operation.
This includes the OperationStates: Waiting, Ready, and Done.
is_operation_pending(id: felt252) → bool external
Returns whether the id OperationState is pending or not.
Note that a pending operation may be either Waiting or Ready.
is_operation_ready(id: felt252) → bool external
Returns whether the id OperationState is Ready or not.
is_operation_done(id: felt252) → bool external
Returns whether the id OperationState is Done or not.
get_timestamp(id: felt252) → u64 external
Returns the timestamp at which id becomes Ready.
0 means the OperationState is Unset and 1 means the OperationState
is Done.
|
get_min_delay() → u64 external
Returns the minimum delay in seconds for an operation to become valid.
This value can be changed by executing an operation that calls update_delay.
hash_operation(call: Call, predecessor: felt252, salt: felt252) external
Returns the identifier of an operation containing a single transaction.
hash_operation_batch(calls: Span<Call>, predecessor: felt252, salt: felt252) external
Returns the identifier of an operation containing a batch of transactions.
schedule(call: Call, predecessor: felt252, salt: felt252, delay: u64) external
Schedule an operation containing a single transaction.
Requirements:
-
the caller must have the
PROPOSER_ROLErole.
Emits CallScheduled event.
If salt is not zero, emits CallSalt event.
schedule_batch(calls: Span<Call>, predecessor: felt252, salt: felt252, delay: u64) external
Schedule an operation containing a batch of transactions.
Requirements:
-
The caller must have the
PROPOSER_ROLErole.
Emits one CallScheduled event for each transaction in the batch.
If salt is not zero, emits CallSalt event.
cancel(id: felt252) external
Cancel an operation.
Requirements:
-
The caller must have the
CANCELLER_ROLErole. -
idmust be an operation.
Emits a CallCancelled event.
execute(call: Call, predecessor: felt252, salt: felt252) external
Execute a (Ready) operation containing a single Call.
Requirements:
-
Caller must have
EXECUTOR_ROLE. -
idmust be in Ready OperationState. -
predecessormust either be0or in Done OperationState.
Emits a CallExecuted event.
This function can reenter, but it doesn’t pose a risk because _after_call(self: @ContractState, id: felt252) internal
checks that the proposal is pending, thus any modifications to the operation during
reentrancy should be caught.
|
execute_batch(calls: Span<Call>, predecessor: felt252, salt: felt252) external
Execute a (Ready) operation containing a batch of Calls.
Requirements:
-
Caller must have
EXECUTOR_ROLE. -
idmust be in Ready OperationState. -
predecessormust either be0or in Done OperationState.
Emits a CallExecuted event for each Call.
This function can reenter, but it doesn’t pose a risk because _after_call
checks that the proposal is pending, thus any modifications to the operation during
reentrancy should be caught.
|
update_delay(new_delay: u64) external
Changes the minimum timelock duration for future operations.
Requirements:
-
The caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the serialized call to this function.
Emits a MinDelayChanged event.
CallScheduled(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64) event
Emitted when call is scheduled as part of operation id.
CallExecuted(id: felt252, index: felt252, call: Call) event
Emitted when call is performed as part of operation id.
TimelockControllerComponent
use openzeppelin_governance::timelock::TimelockControllerComponent;
Component that implements ITimelock and enables the implementing contract to act as a timelock controller.
is_operation(self: @ContractState, id: felt252) → bool external
Returns whether id corresponds to a registered operation.
This includes the OperationStates: Waiting, Ready, and Done.
is_operation_pending(self: @ContractState, id: felt252) → bool external
Returns whether the id OperationState is pending or not.
Note that a pending operation may be either Waiting or Ready.
is_operation_ready(self: @ContractState, id: felt252) → bool external
Returns whether the id OperationState is Ready or not.
is_operation_done(self: @ContractState, id: felt252) → bool external
Returns whether the id OperationState is Done or not.
get_timestamp(self: @ContractState, id: felt252) → u64 external
Returns the timestamp at which id becomes Ready.
0 means the OperationState is Unset and 1 means the OperationState
is Done.
|
get_operation_state(self: @ContractState, id: felt252) → OperationState external
Returns the OperationState for id.
get_min_delay(self: @ContractState) → u64 external
Returns the minimum delay in seconds for an operation to become valid.
This value can be changed by executing an operation that calls update_delay.
hash_operation(self: @ContractState, call: Call, predecessor: felt252, salt: felt252) external
Returns the identifier of an operation containing a single transaction.
hash_operation_batch(self: @ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252) external
Returns the identifier of an operation containing a batch of transactions.
schedule(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252, delay: u64) external
Schedule an operation containing a single transaction.
Requirements:
-
the caller must have the
PROPOSER_ROLErole.
Emits CallScheduled event.
If salt is not zero, emits CallSalt event.
schedule_batch(ref self: ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252, delay: u64) external
Schedule an operation containing a batch of transactions.
Requirements:
-
The caller must have the
PROPOSER_ROLErole.
Emits one CallScheduled event for each transaction in the batch.
If salt is not zero, emits CallSalt event.
cancel(ref self: ContractState, id: felt252) external
Cancel an operation.
Requirements:
-
The caller must have the
CANCELLER_ROLErole. -
idmust be an operation.
Emits a CallCancelled event.
execute(ref self: ContractState, call: Call, predecessor: felt252, salt: felt252) external
Execute a (Ready) operation containing a single Call.
Requirements:
-
Caller must have
EXECUTOR_ROLE. -
idmust be in Ready OperationState. -
predecessormust either be0or in Done OperationState.
Emits a CallExecuted event.
This function can reenter, but it doesn’t pose a risk because _after_call(self: @ContractState, id: felt252) internal
checks that the proposal is pending, thus any modifications to the operation during
reentrancy should be caught.
|
execute_batch(ref self: ContractState, calls: Span<Call>, predecessor: felt252, salt: felt252) external
Execute a (Ready) operation containing a batch of Calls.
Requirements:
-
Caller must have
EXECUTOR_ROLE. -
idmust be in Ready OperationState. -
predecessormust either be0or in Done OperationState.
Emits a CallExecuted event for each Call.
This function can reenter, but it doesn’t pose a risk because _after_call
checks that the proposal is pending, thus any modifications to the operation during
reentrancy should be caught.
|
update_delay(ref self: ContractState, new_delay: u64) external
Changes the minimum timelock duration for future operations.
Requirements:
-
The caller must be the timelock itself. This can only be achieved by scheduling and later executing an operation where the timelock is the target and the data is the serialized call to this function.
Emits a MinDelayChanged event.
initializer(ref self: ContractState, min_delay: u64, proposers: Span<ContractAddress>, executors: Span<ContractState>, admin: ContractAddress) internal
Initializes the contract by registering support for SRC5 and AccessControl.
This function also configures the contract with the following parameters:
-
min_delay: initial minimum delay in seconds for operations. -
proposers: accounts to be granted proposer and canceller roles. -
executors: accounts to be granted executor role. -
admin: optional account to be granted admin role; disable with zero address.
| The optional admin can aid with initial configuration of roles after deployment without being subject to delay, but this role should be subsequently renounced in favor of administration through timelocked proposals. |
Emits two IAccessControl::RoleGranted events for each account in proposers with PROPOSER_ROLE and
CANCELLER_ROLE roles.
Emits a IAccessControl::RoleGranted event for each account in executors with EXECUTOR_ROLE role.
May emit a IAccessControl::RoleGranted event for admin with DEFAULT_ADMIN_ROLE role (if admin is
not zero).
Emits MinDelayChanged event.
assert_only_role(self: @ContractState, role: felt252) internal
Validates that the caller has the given role.
Otherwise it panics.
assert_only_role_or_open_role(self: @ContractState, role: felt252) internal
Validates that the caller has the given role.
If role is granted to the zero address, then this is considered an open role which allows anyone to be the caller.
assert_only_self(self: @ContractState) internal
Validates that the caller is the timelock contract itself. Otherwise it panics.
_before_call(self: @ContractState, id: felt252, predecessor: felt252) internal
Private function that checks before execution of an operation’s calls.
Requirements:
-
idmust be in theReadyOperationState. -
predecessormust either be zero or be in theDoneOperationState.
_after_call(self: @ContractState, id: felt252) internal
Private function that checks after execution of an operation’s calls
and sets the OperationState of id to Done.
Requirements:
-
idmust be in the Ready OperationState.
_schedule(ref self: ContractState, id: felt252, delay: u64) internal
Private function that schedules an operation that is to become valid after a given delay.
_execute(ref self: ContractState, call: Call) internal
Private function that executes an operation’s calls.
CallScheduled(id: felt252, index: felt252, call: Call, predecessor: felt252, delay: u64) event
Emitted when call is scheduled as part of operation id.
CallExecuted(id: felt252, index: felt252, call: Call) event
Emitted when call is performed as part of operation id.
Votes
The VotesComponent provides a flexible system for tracking and delegating voting power. This system allows users to delegate their voting power to other addresses, enabling more active participation in governance.
IVotes
use openzeppelin_governance::votes::interface::IVotes;
Common interface for Votes-enabled contracts.
get_votes(account: ContractAddress) → u256 external
Returns the current amount of votes that account has.
get_past_votes(account: ContractAddress, timepoint: u64) → u256 external
Returns the amount of votes that account had at a specific moment in the past.
get_past_total_supply(timepoint: u64) → u256 external
Returns the total supply of votes available at a specific moment in the past.
| This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote. |
VotesComponent
use openzeppelin_governance::votes::VotesComponent;
Component that implements the IVotes interface and provides a flexible system for tracking and delegating voting power.
By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.
When using this module, your contract must implement the VotingUnitsTrait. For convenience, this is done automatically for ERC20 and ERC721 tokens.
|
get_voting_units(self: @ComponentState<TContractState>, account: ContractAddress) → u256 internal
Returns the number of voting units for a given account.
This implementation is specific to ERC20 tokens, where the balance of tokens directly represents the number of voting units.
| This implementation will work out of the box if the ERC20 component is implemented in the final contract. |
| This implementation assumes tokens map to voting units 1:1. Any deviation from this formula when transferring voting units (e.g. by using hooks) may compromise the internal vote accounting. |
get_voting_units(self: @ComponentState<TContractState>, account: ContractAddress) → u256 internal
Returns the number of voting units for a given account.
This implementation is specific to ERC721 tokens, where each token represents one voting unit. The function returns the balance of ERC721 tokens for the specified account.
| This implementation will work out of the box if the ERC721 component is implemented in the final contract. |
| This implementation assumes tokens map to voting units 1:1. Any deviation from this formula when transferring voting units (e.g. by using hooks) may compromise the internal vote accounting. |
get_votes(self: @ComponentState<TContractState>, account: ContractAddress) → u256 external
Returns the current amount of votes that account has.
get_past_votes(self: @ComponentState<TContractState>, account: ContractAddress, timepoint: u64) → u256 external
Returns the amount of votes that account had at a specific moment in the past.
Requirements:
-
timepointmust be in the past.
get_past_total_supply(self: @ComponentState<TContractState>, timepoint: u64) → u256 external
Returns the total supply of votes available at a specific moment in the past.
| This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. Votes that have not been delegated are still part of total supply, even though they would not participate in a vote. |
Requirements:
-
timepointmust be in the past.
delegates(self: @ComponentState<TContractState>, account: ContractAddress) → ContractAddress external
Returns the delegate that account has chosen.
delegate(ref self: ComponentState<TContractState>, delegatee: ContractAddress) external
Delegates votes from the sender to delegatee.
Emits a DelegateChanged event.
May emit one or two DelegateVotesChanged events.
delegate_by_sig(ref self: ComponentState<TContractState>, delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span<felt252>) external
Delegates votes from delegator to delegatee through a SNIP12 message signature validation.
Requirements:
-
expirymust not be in the past. -
noncemust match the account’s current nonce. -
delegatormust implementSRC6::is_valid_signature. -
signatureshould be valid for the message hash.
Emits a DelegateChanged event.
May emit one or two DelegateVotesChanged events.
get_total_supply(self: @ComponentState<TContractState>) → u256 internal
Returns the current total supply of votes.
move_delegate_votes(ref self: ComponentState<TContractState>, from: ContractAddress, to: ContractAddress, amount: u256) internal
Moves delegated votes from one delegate to another.
May emit one or two DelegateVotesChanged events.
transfer_voting_units(ref self: ComponentState<TContractState>, from: ContractAddress, to: ContractAddress, amount: u256) internal
Transfers, mints, or burns voting units.
To register a mint, from should be zero. To register a burn, to
should be zero. Total supply of voting units will be adjusted with mints and burns.
| If voting units are based on an underlying transferable asset (like a token), you must call this function every time the asset is transferred to keep the internal voting power accounting in sync. For ERC20 and ERC721 tokens, this is typically handled using hooks. |
May emit one or two DelegateVotesChanged events.
num_checkpoints(self: @ComponentState<TContractState>, account: ContractAddress) → u64 internal
Returns the number of checkpoints for account.
checkpoints(self: @ComponentState<TContractState>, account: ContractAddress, pos: u64) → Checkpoint internal
Returns the pos-th checkpoint for account.
_delegate(ref self: ComponentState<TContractState>, account: ContractAddress, delegatee: ContractAddress) internal
Delegates all of account's voting units to delegatee.
Emits a DelegateChanged event.
May emit one or two DelegateVotesChanged events.
VotingUnitsTrait
pub trait VotingUnitsTrait<TState> {
fn get_voting_units(self: @TState, account: ContractAddress) -> u256;
}
A trait that must be implemented when integrating VotesComponent into a contract. It offers a mechanism to retrieve the number of voting units for a given account at the current time.
get_voting_units(self: @TState, account: ContractAddress) → u256 external
Returns the number of voting units for a given account. For ERC20, this is typically the token balance. For ERC721, this is typically the number of tokens owned.
|
While any formula can be used as a measure of voting units, the internal vote accounting of the contract may be
compromised if voting units are transferred in any external flow by following a different formula. For example, when implementing the hook for ERC20, the number of voting units transferred should match the formula given by the get_voting_units implementation.
|