API Reference

Governance

This crate includes primitives for on-chain governance.

Interfaces

Starting from version 3.x.x, the interfaces are no longer part of the openzeppelin_access package. The references documented here are contained in the openzeppelin_interfaces package version 2.1.0-alpha.0.

use openzeppelin_interfaces::governor::IGovernor;

Interface of a governor contract.

SRC5 ID

0x1100a1f8546595b5bd75a6cd8fcc5b015370655e66f275963321c5cd0357ac9

Functions

Events

Functions

name() → felt252

external

#

Name of the governor instance (used in building the SNIP-12 domain separator).

version() → felt252

external

#

Version of the governor instance (used in building SNIP-12 domain separator).

COUNTING_MODE() → ByteArray

external

#

A description of the possible support values for cast_vote and the way these votes are counted, meant to be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of key-value pairs that each describe one aspect, for example support=bravo&quorum=for,abstain.

There are 2 standard keys: support and quorum.

  • support=bravo refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in GovernorBravo.
  • quorum=bravo means that only For votes are counted towards quorum.
  • quorum=for,abstain means that both For and Abstain votes are counted towards quorum.

If a counting module makes use of encoded params, it should include this under a params key with a unique name that describes the behavior. For example:

  • params=fractional might refer to a scheme where votes are divided fractionally between for/against/abstain.
  • params=erc721 might refer to a scheme where specific NFTs are delegated to vote.

The string can be decoded by the standard URLSearchParams JavaScript class.

hash_proposal(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Hashing function used to (re)build the proposal id from the proposal details.

state(proposal_id: felt252) → ProposalState

external

#

Returns the state of a proposal, given its id.

proposal_threshold() → u256

external

#

The number of votes required in order for a voter to become a proposer.

proposal_snapshot(proposal_id: felt252) → u64

external

#

Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the following block.

proposal_deadline(proposal_id: felt252) → u64

external

#

Timepoint at which votes close. If using block number, votes close at the end of this block, so it is possible to cast a vote during this block.

proposal_proposer(proposal_id: felt252) → ContractAddress

external

#

The account that created a proposal.

proposal_eta(proposal_id: felt252) → u64

external

#

The time when a queued proposal becomes executable ("ETA"). Unlike proposal_snapshot and proposal_deadline, this doesn't use the governor clock, and instead relies on the executor's clock which may be different. In most cases this will be a timestamp.

proposal_needs_queuing(proposal_id: felt252) → bool

external

#

Whether a proposal needs to be queued before execution. This indicates if the proposal needs to go through a timelock.

voting_delay() → u64

external

#

Delay between when a proposal is created and when the vote starts. The unit this duration is expressed in depends on the clock (see ERC-6372) this contract uses.

This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.

voting_period() → u64

external

#

Delay between when a vote starts and when it ends. The unit this duration is expressed in depends on the clock (see ERC-6372) this contract uses.

The voting_delay can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.

This value is stored when the proposal is submitted so that possible changes to the value do not affect proposals that have already been submitted.

quorum(timepoint: u64) → u256

external

#

Minimum number of votes required for a proposal to be successful.

The timepoint parameter corresponds to the snapshot used for counting vote. This allows the quorum to scale depending on values such as the total supply of a token at this timepoint.

get_votes(account: ContractAddress, timepoint: u64) → u256

external

#

Returns the voting power of an account at a specific timepoint.

This can be implemented in a number of ways, for example by reading the delegated balance from one (or multiple) ERC20Votes tokens.

get_votes_with_params(account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

external

#

Returns the voting power of an account at a specific timepoint, given additional encoded parameters.

has_voted(proposal_id: felt252, account: ContractAddress) → bool

external

#

Returns whether an account has cast a vote on a proposal.

propose(calls: Span<Call>, description: ByteArray) → felt252

external

#

Creates a new proposal. Vote starts after a delay specified by voting_delay and lasts for a duration specified by voting_period.

The state of the Governor and targets may change between the proposal creation and its execution. This may be the result of third party actions on the targeted contracts, or other governor proposals. For example, the balance of this contract could be updated or its access control permissions may be modified, possibly compromising the proposal's ability to execute successfully (e.g. the governor doesn't have enough value to cover a proposal with multiple transfers).

Returns the id of the proposal.

queue(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Queue a proposal. Some governors require this step to be performed before execution can happen. If queuing is not necessary, this function may revert.

Queuing a proposal requires the quorum to be reached, the vote to be successful, and the deadline to be reached.

Returns the id of the proposal.

execute(calls: span<Call>, description_hash: felt252) → felt252

external

#

Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the deadline to be reached. Depending on the governor it might also be required that the proposal was queued and that some delay passed.

Some modules can modify the requirements for execution, for example by adding an additional timelock (See timelock_controller).

Returns the id of the proposal.

cancel(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e. before the vote starts.

Returns the id of the proposal.

cast_vote(proposal_id: felt252, support: u8) → u256

external

#

Cast a vote on a proposal.

Returns the weight of the vote.

cast_vote_with_reason(proposal_id: felt252, support: u8, reason: ByteArray) → u256

external

#

Cast a vote on a proposal with a reason.

Returns the weight of the vote.

cast_vote_with_reason_and_params(proposal_id: felt252, support: u8, reason: ByteArray, params: Span<felt252>) → u256

external

#

Cast a vote on a proposal with a reason and additional encoded parameters.

Returns the weight of the vote.

cast_vote_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span<felt252>) → u256

external

#

Cast a vote on a proposal using the voter's signature.

Returns the weight of the vote.

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

#

Cast a vote on a proposal with a reason and additional encoded parameters using the voter's signature.

Returns the weight of the vote.

nonces(voter: ContractAddress) → felt252

external

#

Returns the next unused nonce for an address.

relay(call: Call)

external

#

Relays a transaction or function call to an arbitrary target.

In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens that were sent to the governor contract by mistake.

If the executor is simply the governor itself, use of relay is redundant.

Events

ProposalCreated(proposal_id: felt252, proposer: ContractAddress, calls: Span<Call>, signatures: Span<Span<felt252>>, vote_start: u64, vote_end: u64, description: ByteArray)

event

#

Emitted when a proposal is created.

ProposalQueued(proposal_id: felt252, eta_seconds: u64)

event

#

Emitted when a proposal is queued.

ProposalExecuted(proposal_id: felt252)

event

#

Emitted when a proposal is executed.

ProposalCanceled(proposal_id: felt252)

event

#

Emitted when a proposal is canceled.

VoteCast(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray)

event

#

Emitted when a vote is cast.

VoteCastWithParams(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray, params: Span<felt252>)

event

#

Emitted when a vote is cast with params.

use openzeppelin_interfaces::multisig::IMultisig;

Interface of a multisig contract.

Functions

Events

Functions

get_quorum() → u32

external

#

Returns the current quorum value. The quorum is the minimum number of confirmations required to approve a transaction.

is_signer(signer: ContractAddress) → bool

external

#

Returns whether the given signer is registered. Only registered signers can submit, confirm, or execute transactions.

get_signers() → Span<ContractAddress>

external

#

Returns the list of all current signers.

is_confirmed(id: TransactionID) → bool

external

#

Returns whether the transaction with the given id has been confirmed.

is_confirmed_by(id: TransactionID, signer: ContractAddress) → bool

external

#

Returns whether the transaction with the given id has been confirmed by the specified signer.

is_executed(id: TransactionID) → bool

external

#

Returns whether the transaction with the given id has been executed.

get_submitted_block(id: TransactionID) → u64

external

#

Returns the block number when the transaction with the given id was submitted.

get_transaction_state(id: TransactionID) → TransactionState

external

#

Returns the current state of the transaction with the given id.

get_transaction_confirmations(id: TransactionID) → u32

external

#

Returns the number of confirmations from registered signers for the transaction with the specified id.

hash_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252) → TransactionID

external

#

Returns the computed identifier of a transaction containing a single call.

hash_transaction_batch(calls: Span<Call>, salt: felt252) → TransactionID

external

#

Returns the computed identifier of a transaction containing a batch of calls.

add_signers(new_quorum: u32, signers_to_add: Span<ContractAddress>)

external

#

Adds new signers and updates the quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be less than or equal to the total number of signers after addition.

Emits a SignerAdded event for each signer added.

Emits a QuorumUpdated event if the quorum changes.

remove_signers(new_quorum: u32, signers_to_remove: Span<ContractAddress>)

external

#

Removes signers and updates the quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be less than or equal to the total number of signers after removal.

Emits a SignerRemoved event for each signer removed.

Emits a QuorumUpdated event if the quorum changes.

replace_signer(signer_to_remove: ContractAddress, signer_to_add: ContractAddress)

external

#

Replaces an existing signer with a new signer.

Requirements:

  • The caller must be the contract itself.
  • signer_to_remove must be an existing signer.
  • signer_to_add must not be an existing signer.

Emits a SignerRemoved event for the removed signer.

Emits a SignerAdded event for the new signer.

change_quorum(new_quorum: u32)

external

#

Updates the quorum value to new_quorum if it differs from the current quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be non-zero.
  • new_quorum must be less than or equal to the total number of signers.

Emits a QuorumUpdated event if the quorum changes.

submit_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252) → TransactionID

external

#

Submits a new transaction for confirmation.

Requirements:

  • The caller must be a registered signer.
  • The transaction must not have been submitted before.

Emits a TransactionSubmitted event.

Emits a CallSalt event if salt is not zero.

submit_transaction_batch(calls: Span<Call>, salt: felt252) → TransactionID

external

#

Submits a new batch transaction for confirmation.

Requirements:

  • The caller must be a registered signer.
  • The transaction must not have been submitted before.

Emits a TransactionSubmitted event.

Emits a CallSalt event if salt is not zero.

confirm_transaction(id: TransactionID)

external

#

Confirms a transaction with the given id.

Requirements:

  • The caller must be a registered signer.
  • The transaction must exist and not be executed.
  • The caller must not have already confirmed the transaction.

Emits a TransactionConfirmed event.

revoke_confirmation(id: TransactionID)

external

#

Revokes a previous confirmation for a transaction with the given id.

Requirements:

  • The transaction must exist and not be executed.
  • The caller must have previously confirmed the transaction.

Emits a ConfirmationRevoked event.

execute_transaction(to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)

external

#

Executes a confirmed transaction.

Requirements:

  • The caller must be a registered signer.
  • The transaction must be confirmed and not yet executed.

Emits a TransactionExecuted event.

execute_transaction_batch(calls: Span<Call>, salt: felt252)

external

#

Executes a confirmed batch transaction.

Requirements:

  • The caller must be a registered signer.
  • The transaction must be confirmed and not yet executed.

Emits a TransactionExecuted event.

Events

SignerAdded(signer: ContractAddress)

event

#

Emitted when a new signer is added.

SignerRemoved(signer: ContractAddress)

event

#

Emitted when a signer is removed.

QuorumUpdated(old_quorum: u32, new_quorum: u32)

event

#

Emitted when the quorum value is updated.

TransactionSubmitted(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a new transaction is submitted by a signer.

TransactionConfirmed(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a transaction is confirmed by a signer.

ConfirmationRevoked(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a signer revokes his confirmation.

TransactionExecuted(id: TransactionID)

event

#

Emitted when a transaction is executed.

CallSalt(id: felt252, salt: felt252)

event

#

Emitted when a new transaction is submitted with non-zero salt.

use openzeppelin_interfaces::timelock::ITimelock;

Interface of a timelock contract.

Functions

Events

Functions

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_operation_state(id: felt252) → OperationState

external

#

Returns the current state of the operation with the given id.

The possible states are:

  • Unset: the operation has not been scheduled or has been canceled.
  • Waiting: the operation has been scheduled and is pending the scheduled delay.
  • Ready: the timer has expired, and the operation is eligible for execution.
  • Done: the operation has been executed.

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_ROLE role.

Emits CallScheduled event. Emits CallSalt event if salt is not zero.

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_ROLE role.

Emits one CallScheduled event for each transaction in the batch. Emits CallSalt event if salt is not zero.

cancel(id: felt252)

external

#

Cancels an operation. A canceled operation returns to Unset OperationState.

Requirements:

  • The caller must have the CANCELLER_ROLE role.
  • id must be a pending 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.
  • id must be in Ready OperationState.
  • predecessor must either be 0 or 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.
  • id must be in Ready OperationState.
  • predecessor must either be 0 or 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.

Events

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.

CallSalt(id: felt252, salt: felt252)

event

#

Emitted when a new proposal is scheduled with non-zero salt.

CallCancelled(id: felt252)

event

#

Emitted when operation id is cancelled.

MinDelayChanged(old_duration: u64, new_duration: u64)

event

#

Emitted when the minimum delay for future operations is modified.

use openzeppelin_interfaces::votes::IVotes;

Common interface for Votes-enabled contracts.

Functions

Functions

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.

delegates(account: ContractAddress) → ContractAddress

external

#

Returns the delegate that account has chosen.

delegate(delegatee: ContractAddress)

external

#

Delegates votes from the sender to delegatee.

delegate_by_sig(delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span<felt252>)

external

#

Delegates votes from delegator to delegatee through a SNIP-12 message signature validation.

clock() → u64

external

#

Returns the current timepoint determined by the contract's operational mode, intended for use in time-sensitive logic. See ERC-6372#clock.

Requirements:

  • This function MUST always be non-decreasing.

CLOCK_MODE() → u64

external

#

Returns a description of the clock the contract is operating in. See ERC-6372#CLOCK_MODE.

Requirements:

  • The output MUST be formatted like a URL query string, decodable in standard JavaScript.

Governor

This modular system of Governor components allows the deployment of easily customizable on-chain voting protocols.

For a walkthrough of how to implement a Governor, check the Governor page.

use openzeppelin_governance::governor::GovernorComponent;

Core of the governance system.

The extension traits presented below are what make the GovernorComponent a modular and configurable system. The embeddable and internal implementations depends on these trait. They can be implemented locally in the contract, or through the provided library component extensions.

Implementing SRC5Component is a requirement for this component to be implemented.

Extensions traits

GovernorSettingsTrait

GovernorQuorumTrait

GovernorCountingTrait

GovernorVotesTrait

GovernorExecutionTrait

Embeddable Implementations

GovernorImpl

Internal Implementations

InternalImpl

InternalExtendedImpl

Events

Extensions traits functions

voting_delay(self: @ContractState) → u64

extension

#

Must return the delay, in number of timepoints, between when the proposal is created and when the vote starts. This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.

voting_period(self: @ContractState) → u64

extension

#

Must return the delay, in number of timepoints, between the vote start and vote end.

proposal_threshold(self: @ContractState) → u256

extension

#

Must return the minimum number of votes that an account must have to create a proposal.

quorum(self: @ContractState, timepoint: u64) → u256

extension

#

Must return the minimum number of votes required for a proposal to succeed.

counting_mode(self: @ContractState) → ByteArray

extension

#

Must return a description of the possible support values for cast_vote and the way these votes are counted, meant to be consumed by UIs to show correct vote options and interpret the results. See COUNTING_MODE for more details.

count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span<felt252>) → u256

extension

#

Must register a vote for proposal_id by account with a given support, voting weight and voting params.

Support is generic and can represent various things depending on the voting system used.

has_voted(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool

extension

#

Must return whether an account has cast a vote on a proposal.

quorum_reached(self: @ContractState, proposal_id: felt252) → bool

extension

#

Must return whether the minimum quorum has been reached for a proposal.

vote_succeeded(self: @ContractState, proposal_id: felt252) → bool

extension

#

Must return whether a proposal has succeeded or not.

clock(self: @ContractState) → u64

extension

#

Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. See ERC-6372#clock.

Requirements:

  • This function MUST always be non-decreasing.

CLOCK_MODE(self: @ContractState) → ByteArray

extension

#

Returns a description of the clock the governor is operating in. See ERC-6372#CLOCK_MODE.

Requirements:

  • The output MUST be formatted like a URL query string, decodable in standard JavaScript.

get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

extension

#

Must return the voting power of an account at a specific timepoint with the given parameters.

state(self: @ContractState, proposal_id: felt252) → ProposalState

extension

#

Must return the state of a proposal at the current time.

The state can be either:

  • Pending: The proposal does not exist yet.
  • Active: The proposal is active.
  • Canceled: The proposal has been canceled.
  • Defeated: The proposal has been defeated.
  • Succeeded: The proposal has succeeded.
  • Queued: The proposal has been queued.
  • Executed: The proposal has been executed.

executor(self: @ContractState) → ContractAddress

internal

#

Must return the address through which the governor executes action. Should be used to specify whether the module execute actions through another contract such as a timelock.

MUST be the governor itself, or an instance of TimelockController with the governor as the only proposer, canceller, and executor.

When the executor is not the governor itself (i.e. a timelock), it can call functions that are restricted with the assert_only_governance guard, and also potentially execute transactions on behalf of the governor. Because of this, this module is designed to work with the TimelockController as the unique potential external executor.

execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)

internal

#

Execution mechanism. Can be used to modify the way operations are executed (for example adding a vault/timelock).

queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)

internal

#

Queuing mechanism. Can be used to modify the way queuing is performed (for example adding a vault/timelock).

Requirements:

  • Must return a timestamp that describes the expected ETA for execution. If the returned value is 0, the core will consider queueing did not succeed, and the public queue function will revert.

proposal_needs_queuing(self: @ContractState) → bool

internal

#

Must return whether proposals need to be queued before execution. This usually indicates if the proposal needs to go through a timelock.

cancel_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>)

internal

#

Cancel mechanism. Can be used to modify the way canceling is performed (for example adding a vault/timelock).

Embeddable functions

name() → felt252

external

#

Name of the governor instance (used in building the SNIP-12 domain separator).

version() → felt252

external

#

Version of the governor instance (used in building SNIP-12 domain separator).

COUNTING_MODE() → ByteArray

external

#

A description of the possible support values for cast_vote and the way these votes are counted, meant to be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of key-value pairs that each describe one aspect, for example support=bravo&quorum=for,abstain.

There are 2 standard keys: support and quorum.

  • support=bravo refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in GovernorBravo.
  • quorum=bravo means that only For votes are counted towards quorum.
  • quorum=for,abstain means that both For and Abstain votes are counted towards quorum.

If a counting module makes use of encoded params, it should include this under a params key with a unique name that describes the behavior. For example:

  • params=fractional might refer to a scheme where votes are divided fractionally between for/against/abstain.
  • params=erc721 might refer to a scheme where specific NFTs are delegated to vote.

The string can be decoded by the standard URLSearchParams JavaScript class.

hash_proposal(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Hashing function used to (re)build the proposal id from the proposal details.

state(proposal_id: felt252) → ProposalState

external

#

Returns the state of a proposal, given its id.

proposal_threshold() → u256

external

#

The number of votes required in order for a voter to become a proposer.

proposal_snapshot(proposal_id: felt252) → u64

external

#

Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the following block.

proposal_deadline(proposal_id: felt252) → u64

external

#

Timepoint at which votes close. If using block number, votes close at the end of this block, so it is possible to cast a vote during this block.

proposal_proposer(proposal_id: felt252) → ContractAddress

external

#

The account that created a proposal.

proposal_eta(proposal_id: felt252) → u64

external

#

The time when a queued proposal becomes executable ("ETA"). Unlike proposal_snapshot and proposal_deadline, this doesn't use the governor clock, and instead relies on the executor's clock which may be different. In most cases this will be a timestamp.

proposal_needs_queuing(proposal_id: felt252) → bool

external

#

Whether a proposal needs to be queued before execution. This indicates if the proposal needs to go through a timelock.

voting_delay() → u64

external

#

Delay between when a proposal is created and when the vote starts. The unit this duration is expressed in depends on the clock (see ERC-6372) this contract uses.

This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.

voting_period() → u64

external

#

Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock (see ERC-6372) this contract uses.

The voting_delay can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay.

This value is stored when the proposal is submitted so that possible changes to the value do not affect proposals that have already been submitted.

quorum(timepoint: u64) → u256

external

#

Minimum number of votes required for a proposal to be successful.

The timepoint parameter corresponds to the snapshot used for counting vote. This allows the quorum to scale depending on values such as the total supply of a token at this timepoint.

get_votes(account: ContractAddress, timepoint: u64) → u256

external

#

Returns the voting power of an account at a specific timepoint.

This can be implemented in a number of ways, for example by reading the delegated balance from one (or multiple) ERC20Votes tokens.

get_votes_with_params(account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

external

#

Returns the voting power of an account at a specific timepoint, given additional encoded parameters.

has_voted(proposal_id: felt252, account: ContractAddress) → bool

external

#

Returns whether an account has cast a vote on a proposal.

propose(calls: Span<Call>, description: ByteArray) → felt252

external

#

Creates a new proposal. Voting starts after the delay specified by voting_delay and lasts for a duration specified by voting_period. Returns the id of the proposal.

This function has opt-in frontrunning protection, described in is_valid_description_for_proposer.

The state of the Governor and targets may change between the proposal creation and its execution. This may be the result of third party actions on the targeted contracts, or other governor proposals. For example, the balance of this contract could be updated or its access control permissions may be modified, possibly compromising the proposal's ability to execute successfully (e.g. the governor doesn't have enough value to cover a proposal with multiple transfers).

Requirements:

  • The proposer must be authorized to submit the proposal.
  • The proposer must have enough votes to submit the proposal if proposal_threshold is greater than zero.
  • The proposal must not already exist.

Emits a ProposalCreated event.

queue(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Queues a proposal. Some governors require this step to be performed before execution can happen. If queuing is not necessary, this function may revert. Queuing a proposal requires the quorum to be reached, the vote to be successful, and the deadline to be reached.

Returns the id of the proposal.

Requirements:

  • The proposal must be in the Succeeded state.
  • The queue operation must return a non-zero ETA.

Emits a ProposalQueued event.

execute(calls: span<Call>, description_hash: felt252) → felt252

external

#

Executes a successful proposal. This requires the quorum to be reached, the vote to be successful, and the deadline to be reached. Depending on the governor it might also be required that the proposal was queued and that some delay passed.

Some modules can modify the requirements for execution, for example by adding an additional timelock (See timelock_controller).

Returns the id of the proposal.

Requirements:

  • The proposal must be in the Succeeded or Queued state.

Emits a ProposalExecuted event.

cancel(calls: Span<Call>, description_hash: felt252) → felt252

external

#

Cancels a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e. before the vote starts.

Returns the id of the proposal.

Requirements:

  • The proposal must be in the Pending state.
  • The caller must be the proposer of the proposal.

Emits a ProposalCanceled event.

cast_vote(proposal_id: felt252, support: u8) → u256

external

#

Cast a vote.

Requirements:

  • The proposal must be active.

Emits a VoteCast event.

cast_vote_with_reason(proposal_id: felt252, support: u8, reason: ByteArray) → u256

external

#

Cast a vote with a reason.

Requirements:

  • The proposal must be active.

Emits a VoteCast event.

cast_vote_with_reason_and_params(proposal_id: felt252, support: u8, reason: ByteArray, params: Span<felt252>) → u256

external

#

Cast a vote with a reason and additional serialized params.

Requirements:

  • The proposal must be active.

Emits either:

cast_vote_by_sig(proposal_id: felt252, support: u8, voter: ContractAddress, signature: Span<felt252>) → u256

external

#

Cast a vote using the voter's signature.

Requirements:

  • The proposal must be active.
  • The nonce in the signed message must match the account's current nonce.
  • voter must implement SRC6::is_valid_signature.
  • signature must be valid for the message hash.

Emits a VoteCast event.

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

#

Cast a vote with a reason and additional serialized params using the voter's signature.

Requirements:

  • The proposal must be active.
  • The nonce in the signed message must match the account's current nonce.
  • voter must implement SRC6::is_valid_signature.
  • signature must be valid for the message hash.

Emits either:

nonces(voter: ContractAddress) → felt252

external

#

Returns the next unused nonce for an address.

relay(call: Call)

external

#

Relays a transaction or function call to an arbitrary target.

In cases where the governance executor is some contract other than the governor itself, like when using a timelock, this function can be invoked in a governance proposal to recover tokens that were sent to the governor contract by mistake.

If the executor is simply the governor itself, use of relay is redundant.

Internal functions

initializer(ref self: ContractState)

internal

#

Initializes the contract by registering the supported interface id.

get_proposal(self: @ContractState, proposal_id: felt252) → ProposalCore

internal

#

Returns the proposal object given its id.

is_valid_description_for_proposer(self: @ContractState, proposer: ContractAddress, description: ByteArray) → bool

internal

#

Checks if the proposer is authorized to submit a proposal with the given description.

If the proposal description ends with #proposer=0x???, where 0x??? is an address written as a hex string (case insensitive), then the submission of this proposal will only be authorized to said address.

This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure that no other address can submit the same proposal. An attacker would have to either remove or change that part, which would result in a different proposal id.

In Starknet, the Sequencer ensures the order of transactions, but frontrunning can still be achieved by nodes, and potentially other actors in the future with sequencer decentralization.

If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes:

  • If the 0x??? part is not a valid hex string.
  • If the 0x??? part is a valid hex string, but does not contain exactly 64 hex digits.
  • If it ends with the expected suffix followed by newlines or other whitespace.
  • If it ends with some other similar suffix, e.g. #other=abc.
  • If it does not end with any such suffix.

_hash_proposal(self: @ContractState, calls: Span<Call>, description_hash: felt252) → felt252

internal

#

Returns the proposal id computed from the given parameters.

The proposal id is computed as a Pedersen hash of:

  • The array of calls being proposed
  • The description hash

_proposal_snapshot(self: @ContractState, proposal_id: felt252) → u64

internal

#

Timepoint used to retrieve user's votes and quorum. If using block number, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the following block.

_proposal_deadline(self: @ContractState, proposal_id: felt252) → u64

internal

#

Timepoint at which votes close. If using block number, votes close at the end of this block, so it is possible to cast a vote during this block.

_proposal_proposer(self: @ContractState, proposal_id: felt252) → ContractAddress

internal

#

The account that created a proposal.

_proposal_eta(self: @ContractState, proposal_id: felt252) → u64

internal

#

The time when a queued proposal becomes executable ("ETA"). Unlike proposal_snapshot and proposal_deadline, this doesn't use the governor clock, and instead relies on the executor's clock which may be different. In most cases this will be a timestamp.

assert_only_governance(self: @ContractState)

internal

#

Asserts that the caller is the governance executor.

When the executor is not the governor itself (i.e. a timelock), it can call functions that are restricted with this modifier, and also potentially execute transactions on behalf of the governor. Because of this, this module is designed to work with the TimelockController as the unique potential external executor. The timelock MUST have the governor as the only proposer, canceller, and executor.

validate_state(self: @ContractState, proposal_id: felt252, state: ProposalState)

internal

#

Validates that a proposal is in the expected state. Otherwise it panics.

use_nonce(ref self: ContractState) → felt252

internal

#

Consumes a nonce, returns the current value, and increments nonce.

_get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

internal

#

Internal wrapper for GovernorVotesTrait::get_votes.

_proposal_threshold(self: @ContractState) → u256

internal

#

Internal wrapper for GovernorProposeTrait::proposal_threshold.

_state(self: @ContractState, proposal_id: felt252) → ProposalState

internal

#

Returns the state of a proposal, given its id.

Requirements:

  • The proposal must exist.

_propose(ref self: ContractState, calls: Span<Call>, description_hash: felt252) → felt252

internal

#

Internal propose mechanism. Returns the proposal id.

Requirements:

  • The proposal must not already exist.

Emits a ProposalCreated event.

_cancel(ref self: ContractState, proposal_id: felt252)

internal

#

Internal cancel mechanism with minimal restrictions.

A proposal can be cancelled in any state other than Canceled or Executed.

Once cancelled, a proposal can't be re-submitted.

_count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, weight: u256, params: Span<felt252>)

internal

#

Internal wrapper for GovernorCountingTrait::count_vote.

_cast_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, reason: ByteArray, params: Span<felt252>) → u256

internal

#

Internal vote-casting mechanism.

Checks that the vote is pending and that it has not been cast yet. This function retrieves the voting weight using get_votes and then calls the _count_vote internal function.

Emits either:

Events

ProposalCreated(proposal_id: felt252, proposer: ContractAddress, calls: Span<Call>, signatures: Span<Span<felt252>>, vote_start: u64, vote_end: u64, description: ByteArray)

event

#

Emitted when a proposal is created.

ProposalQueued(proposal_id: felt252, eta_seconds: u64)

event

#

Emitted when a proposal is queued.

ProposalExecuted(proposal_id: felt252)

event

#

Emitted when a proposal is executed.

ProposalCanceled(proposal_id: felt252)

event

#

Emitted when a proposal is canceled.

VoteCast(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray)

event

#

Emitted when a vote is cast.

VoteCastWithParams(voter: ContractAddress, proposal_id: felt252, support: u8, weight: u256, reason: ByteArray, params: Span<felt252>)

event

#

Emitted when a vote is cast with params.

Governor extensions

The Governor component can (and must) be extended by implementing the extensions traits to add the desired functionality. This can be achieved by directly implementing the traits on your contract, or by using a set of ready-to-use extensions provided by the library, which are presented below.

use openzeppelin_governance::governor::extensions::GovernorCoreExecutionComponent;

Extension of GovernorComponent providing an execution mechanism directly through the Governor itself. For a timelocked execution mechanism, see GovernorTimelockExecutionComponent.

Extension traits implementations

GovernorExecution

Extension traits functions

state(self: @ContractState, proposal_id: felt252) → ProposalState

internal

#

Returns the state of a proposal given its id.

Requirements:

  • The proposal must exist.

executor(self: @ContractState) → ContractAddress

internal

#

Returns the executor address.

In this case, it returns the governor contract address since execution is performed directly through it.

execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252)

internal

#

Executes the proposal's operations directly through the governor contract.

queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252) → u64

internal

#

In this implementation, queuing is not required so it returns 0.

proposal_needs_queuing(self: @ContractState, proposal_id: felt252) → bool

internal

#

In this implementation, it always returns false.

cancel_operations(ref self: ContractState, proposal_id: felt252, description_hash: felt252)

internal

#

Cancels a proposal's operations.

use openzeppelin_governance::governor::extensions::GovernorCountingSimpleComponent;

Extension of GovernorComponent for simple vote counting with three options.

Extension traits implementations

GovernorCounting

Extension traits functions

counting_mode(self: @ContractState) → ByteArray

internal

#

Returns "support=bravo&quorum=for,abstain".

  • support=bravo indicates that the support follows the Governor Bravo format where voters can vote For, Against, or Abstain
  • quorum=for,abstain indicates that both For and Abstain votes count toward quorum

count_vote(ref self: ContractState, proposal_id: felt252, account: ContractAddress, support: u8, total_weight: u256, params: Span<felt252>) → u256

internal

#

Records a vote for a proposal.

The support value follows the VoteType enum (0=Against, 1=For, 2=Abstain).

Returns the weight that was counted.

has_voted(self: @ContractState, proposal_id: felt252, account: ContractAddress) → bool

internal

#

Returns whether an account has cast a vote on a proposal.

quorum_reached(self: @ContractState, proposal_id: felt252) → bool

internal

#

Returns whether a proposal has reached quorum.

In this implementation, both For and Abstain votes count toward quorum.

vote_succeeded(self: @ContractState, proposal_id: felt252) → bool

internal

#

Returns whether a proposal has succeeded.

In this implementation, the For votes must be strictly greater than Against votes.

use openzeppelin_governance::governor::extensions::GovernorSettingsComponent;

Extension of GovernorComponent for settings that are updatable through governance.

Extension traits implementations

GovernorSettings

Embeddable implementations

GovernorSettingsAdminImpl

Internal implementations

InternalImpl

Events

Extension traits functions

voting_delay(self: @ContractState) → u64

internal

#

Returns the delay, between when a proposal is created and when voting starts.

voting_period(self: @ContractState) → u64

internal

#

Returns the time period, during which votes can be cast.

proposal_threshold(self: @ContractState) → u256

internal

#

Returns the minimum number of votes required for an account to create a proposal.

Embeddable functions

set_voting_delay(ref self: ContractState, new_voting_delay: u64)

external

#

Sets the voting delay.

Requirements:

  • Caller must be the governance executor.

This function does not emit an event if the new voting delay is the same as the old one.

May emit a VotingDelayUpdated event.

set_voting_period(ref self: ContractState, new_voting_period: u64)

external

#

Sets the voting period.

This function does not emit an event if the new voting period is the same as the old one.

Requirements:

  • Caller must be the governance executor.
  • new_voting_period must be greater than 0.

May emit a VotingPeriodUpdated event.

set_proposal_threshold(ref self: ContractState, new_proposal_threshold: u256)

external

#

Sets the proposal threshold.

This function does not emit an event if the new proposal threshold is the same as the old one.

Requirements:

  • Caller must be the governance executor.

May emit a ProposalThresholdUpdated event.

Internal functions

initializer(ref self: ContractState, initial_voting_delay: u64, initial_voting_period: u64, initial_proposal_threshold: u256)

internal

#

Initializes the component by setting the default values.

Requirements:

  • new_voting_period must be greater than 0.

Emits a VotingDelayUpdated, VotingPeriodUpdated, and ProposalThresholdUpdated event.

assert_only_governance(ref self: ContractState)

internal

#

Asserts that the caller is the governance executor.

_set_voting_delay(ref self: ContractState, new_voting_delay: u64)

internal

#

Internal function to update the voting delay.

This function does not emit an event if the new voting delay is the same as the old one.

May emit a VotingDelayUpdated event.

_set_voting_period(ref self: ContractState, new_voting_period: u64)

internal

#

Internal function to update the voting period.

Requirements:

  • new_voting_period must be greater than 0.

This function does not emit an event if the new voting period is the same as the old one.

May emit a VotingPeriodUpdated event.

_set_proposal_threshold(ref self: ContractState, new_proposal_threshold: u256)

internal

#

Internal function to update the proposal threshold.

This function does not emit an event if the new proposal threshold is the same as the old one.

May emit a ProposalThresholdUpdated event.

Events

VotingDelayUpdated(old_voting_delay: u64, new_voting_delay: u64)

event

#

Emitted when the voting delay is updated.

VotingPeriodUpdated(old_voting_period: u64, new_voting_period: u64)

event

#

Emitted when the voting period is updated.

ProposalThresholdUpdated(old_proposal_threshold: u256, new_proposal_threshold: u256)

event

#

Emitted when the proposal threshold is updated.

use openzeppelin_governance::governor::extensions::GovernorVotesComponent;

Extension of GovernorComponent for voting weight extraction from a token with the IVotes extension.

Extension traits implementations

GovernorVotes

Embeddable implementations

VotesTokenImpl

Internal implementations

InternalImpl

Extension traits functions

clock(self: @ContractState) → u64

internal

#

Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. See ERC-6372#clock.

Requirements:

  • This function MUST always be non-decreasing.

CLOCK_MODE(self: @ContractState) → ByteArray

internal

#

Returns a description of the clock the governor is operating in. See ERC-6372#CLOCK_MODE.

Requirements:

  • The output MUST be formatted like a URL query string, decodable in standard JavaScript.

get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

internal

#

Returns the voting power of account at a specific timepoint using the votes token.

Embeddable functions

token(self: @ContractState) → ContractAddress

external

#

Returns the votes token that voting power is sourced from.

Internal functions

initializer(ref self: ContractState, votes_token: ContractAddress)

internal

#

Initializes the component by setting the votes token.

Requirements:

  • votes_token must not be zero.
use openzeppelin_governance::governor::extensions::GovernorVotesQuorumFractionComponent;

Extension of GovernorComponent for voting weight extraction from a token with the IVotes extension and a quorum expressed as a fraction of the total supply.

Extension traits implementations

GovernorQuorum

GovernorVotes

Embeddable implementations

QuorumFractionImpl

Internal implementations

InternalImpl

Events

Extension traits functions

quorum(self: @ContractState, timepoint: u64) → u256

internal

#

It is computed as a percentage of the votes token total supply at a given timepoint in the past.

clock(self: @ContractState) → u64

internal

#

Returns the current timepoint determined by the governor's operational mode, intended for use in time-sensitive logic. See ERC-6372#clock.

Requirements:

  • This function MUST always be non-decreasing.

CLOCK_MODE(self: @ContractState) → ByteArray

internal

#

Returns a description of the clock the governor is operating in. See ERC-6372#CLOCK_MODE.

Requirements:

  • The output MUST be formatted like a URL query string, decodable in standard JavaScript.

get_votes(self: @ContractState, account: ContractAddress, timepoint: u64, params: Span<felt252>) → u256

internal

#

Returns the voting power of account at a specific timepoint using the votes token.

Embeddable functions

token(self: @ContractState) → ContractAddress

external

#

Returns the address of the votes token used for voting power extraction.

current_quorum_numerator(self: @ContractState) → u256

external

#

Returns the current quorum numerator value.

quorum_numerator(self: @ContractState, timepoint: u64) → u256

external

#

Returns the quorum numerator value at a specific timepoint in the past.

quorum_denominator(self: @ContractState) → u256

external

#

Returns the quorum denominator value.

Internal functions

initializer(self: @ComponentState<TContractState>, votes_token: ContractAddress, quorum_numerator: u256)

internal

#

Initializes the component by setting the votes token and the initial quorum numerator value.

Requirements:

  • votes_token must not be zero.
  • quorum_numerator must be less than quorum_denominator.

Emits a QuorumNumeratorUpdated event.

update_quorum_numerator(self: @ComponentState<TContractState>, new_quorum_numerator: u256)

internal

#

Updates the quorum numerator.

This function does not emit an event if the new quorum numerator is the same as the old one.

Requirements:

  • new_quorum_numerator must be less than quorum_denominator.

May emit a QuorumNumeratorUpdated event.

Events

QuorumNumeratorUpdated(old_quorum_numerator: u256, new_quorum_numerator: u256)

event

#

Emitted when the quorum numerator is updated.

use openzeppelin_governance::governor::extensions::GovernorTimelockExecutionComponent;

Extension of GovernorComponent that binds the execution process to an instance of a contract implementing TimelockControllerComponent. This adds a delay, enforced by the timelock to all successful proposals (in addition to the voting duration).

The Governor needs the PROPOSER, EXECUTOR, and CANCELLER roles to work properly.

Using this model means the proposal will be operated by the timelock and not by the governor. Thus, the assets and permissions must be attached to the timelock. Any asset sent to the governor will be inaccessible from a proposal, unless executed via Governor::relay.

Setting up the timelock to have additional proposers or cancellers besides the governor is very risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance proposals that have been approved by the voters, effectively executing a Denial of Service attack.

Extension traits implementations

GovernorExecution

Embeddable implementations

TimelockedImpl

Internal implementations

InternalImpl

Events

Extension traits functions

state(self: @ContractState, proposal_id: felt252) → ProposalState

internal

#

Returns the state of a proposal given its id.

Requirements:

  • The proposal must exist.

executor(self: @ContractState) → ContractAddress

internal

#

Returns the executor address.

In this module, the executor is the timelock controller.

execute_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252)

internal

#

Runs the already queued proposal through the timelock.

queue_operations(ref self: ContractState, proposal_id: felt252, calls: Span<Call>, description_hash: felt252) → u64

internal

#

Queue a proposal to the timelock.

Returns the eta for the execution of the queued proposal.

proposal_needs_queuing(self: @ContractState, proposal_id: felt252) → bool

internal

#

In this implementation, it always returns true.

cancel_operations(ref self: ContractState, proposal_id: felt252, description_hash: felt252)

internal

#

Cancels the timelocked proposal if it has already been queued.

Embeddable functions

timelock(self: @ContractState) → ContractAddress

external

#

Returns the timelock controller address.

get_timelock_id(self: @ContractState) → felt252

external

#

Returns the timelock proposal id for a given proposal id.

update_timelock(ref self: ContractState, new_timelock: ContractAddress)

external

#

Updates the associated timelock.

Requirements:

  • The caller must be the governance.

Emits a TimelockUpdated event.

Internal functions

initializer(ref self: ContractState, timelock: ContractAddress)

internal

#

Initializes the timelock controller.

Requirements:

  • The timelock must not be the zero address.

assert_only_governance(self: @ContractState)

internal

#

Ensures the caller is the executor (the timelock controller in this case).

timelock_salt(self: @ContractState, description_hash: felt252) → felt252

internal

#

Computes the TimelockController operation salt as the XOR of the governor address and description_hash.

It is computed with the governor address itself to avoid collisions across governor instances using the same timelock.

get_timelock_dispatcher(self: @ContractState) → ITimelockDispatcher

internal

#

Returns a dispatcher for interacting with the timelock controller.

_update_timelock(ref self: ContractState, new_timelock: ContractAddress)

internal

#

Internal function to update the timelock controller address.

Emits a TimelockUpdated event.

Events

TimelockUpdated(old_timelock: ContractAddress, new_timelock: ContractAddress)

event

#

Emitted when the timelock controller is updated.

Multisig

A Multisig module enhances security and decentralization by requiring multiple signers to approve and execute transactions. Features include configurable quorum, signer management, and self-administration, ensuring collective decision-making and transparency for critical operations.

use openzeppelin_governance::multisig::MultisigComponent;

Component that implements IMultisig and provides functionality for multisignature wallets, including transaction management, quorum handling, and signer operations.

Embeddable Implementations

MultisigImpl

Internal Implementations

InternalImpl

Events

Embeddable functions

get_quorum(self: @ContractState) → u32

external

#

Returns the current quorum value.

is_signer(self: @ContractState, signer: ContractAddress) → bool

external

#

Checks if a given signer is registered.

get_signers(self: @ContractState) → Span<ContractAddress>

external

#

Returns a list of all current signers.

is_confirmed(self: @ContractState, id: TransactionID) → bool

external

#

Returns whether the transaction with the given id has been confirmed. A confirmed transaction has received the required number of confirmations (quorum).

is_confirmed_by(self: @ContractState, id: TransactionID, signer: ContractAddress) → bool

external

#

Returns whether the transaction with the given id has been confirmed by the specified signer.

is_executed(self: @ContractState, id: TransactionID) → bool

external

#

Returns whether the transaction with the given id has been executed.

get_submitted_block(self: @ContractState, id: TransactionID) → u64

external

#

Returns the block number when the transaction with the given id was submitted.

get_transaction_state(self: @ContractState, id: TransactionID) → TransactionState

external

#

Returns the current state of the transaction with the given id.

The possible states are:

  • NotFound: the transaction does not exist.
  • Pending: the transaction exists but hasn't reached the required confirmations.
  • Confirmed: the transaction has reached the required confirmations but hasn't been executed.
  • Executed: the transaction has been executed.

get_transaction_confirmations(self: @ContractState, id: TransactionID) → u32

external

#

Returns the number of confirmations from registered signers for the transaction with the specified id.

hash_transaction(self: @ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)

external

#

Returns the computed identifier of a transaction containing a single call.

hash_transaction_batch(self: @ContractState, calls: Span<Call>, salt: felt252)

external

#

Returns the computed identifier of a transaction containing a batch of calls.

add_signers(ref self: ContractState, new_quorum: u32, signers_to_add: Span<ContractAddress>)

external

#

Adds new signers and updates the quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be less than or equal to the total number of signers after addition.

Emits a SignerAdded event for each signer added.

Emits a QuorumUpdated event if the quorum changes.

remove_signers(ref self: ContractState, new_quorum: u32, signers_to_remove: Span<ContractAddress>)

external

#

Removes signers and updates the quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be less than or equal to the total number of signers after removal.

Emits a SignerRemoved event for each signer removed.

Emits a QuorumUpdated event if the quorum changes.

replace_signer(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)

external

#

Replaces an existing signer with a new signer.

Requirements:

  • The caller must be the contract itself.
  • signer_to_remove must be an existing signer.
  • signer_to_add must not be an existing signer.

Emits a SignerRemoved event for the removed signer.

Emits a SignerAdded event for the new signer.

change_quorum(ref self: ContractState, new_quorum: u32)

external

#

Updates the quorum value to new_quorum.

Requirements:

  • The caller must be the contract itself.
  • new_quorum must be non-zero.
  • new_quorum must be less than or equal to the total number of signers.

Emits a QuorumUpdated event if the quorum changes.

submit_transaction(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)

external

#

Submits a new transaction for confirmation.

Requirements:

  • The caller must be a registered signer.
  • The transaction must not have been submitted before.

Emits a TransactionSubmitted event.

Emits a CallSalt event if salt is not zero.

submit_transaction_batch(ref self: ContractState, calls: Span<Call>, salt: felt252)

external

#

Submits a new batch transaction for confirmation.

Requirements:

  • The caller must be a registered signer.
  • The transaction must not have been submitted before.

Emits a TransactionSubmitted event.

Emits a CallSalt event if salt is not zero.

confirm_transaction(ref self: ContractState, id: TransactionID)

external

#

Confirms a transaction with the given id.

Requirements:

  • The caller must be a registered signer.
  • The transaction must exist and not be executed.
  • The caller must not have already confirmed the transaction.

Emits a TransactionConfirmed event.

revoke_confirmation(ref self: ContractState, id: TransactionID)

external

#

Revokes a previous confirmation for a transaction with the given id.

Requirements:

  • The transaction must exist and not be executed.
  • The caller must have previously confirmed the transaction.

Emits a ConfirmationRevoked event.

execute_transaction(ref self: ContractState, to: ContractAddress, selector: felt252, calldata: Span<felt252>, salt: felt252)

external

#

Executes a confirmed transaction.

Requirements:

  • The caller must be a registered signer.
  • The transaction must be confirmed and not yet executed.

Emits a TransactionExecuted event.

execute_transaction_batch(ref self: ContractState, calls: Span<Call>, salt: felt252)

external

#

Executes a confirmed batch transaction.

Requirements:

  • The caller must be a registered signer.
  • The transaction must be confirmed and not yet executed.

Emits a TransactionExecuted event.

Internal functions

initializer(ref self: ContractState, quorum: u32, signers: Span<ContractAddress>)

internal

#

Initializes the Multisig component with the initial quorum and signers. This function must be called during contract initialization to set up the initial state.

Requirements:

  • quorum must be non-zero and less than or equal to the number of signers.

Emits a SignerAdded event for each signer added.

Emits a QuorumUpdated event.

resolve_tx_state(self: @ContractState, id: TransactionID) → TransactionState

internal

#

Resolves and returns the current state of the transaction with the given id.

The possible states are:

  • NotFound: the transaction does not exist.
  • Pending: the transaction exists but hasn't reached the required confirmations.
  • Confirmed: the transaction has reached the required confirmations but hasn't been executed.
  • Executed: the transaction has been executed.

assert_one_of_signers(self: @ContractState, caller: ContractAddress)

internal

#

Asserts that the caller is one of the registered signers.

Requirements:

  • The caller must be a registered signer.

assert_tx_exists(self: @ContractState, id: TransactionID)

internal

#

Asserts that a transaction with the given id exists.

Requirements:

  • The transaction with the given id must have been submitted.

assert_only_self(self: @ContractState)

internal

#

Asserts that the caller is the contract itself.

Requirements:

  • The caller must be the contract's own address.

_add_signers(ref self: ContractState, new_quorum: u32, signers_to_add: Span<ContractAddress>)

internal

#

Adds new signers and updates the quorum.

Requirements:

  • Each signer address must be non-zero.
  • new_quorum must be non-zero and less than or equal to the total number of signers after addition.

Emits a SignerAdded event for each new signer added.

Emits a QuorumUpdated event if the quorum changes.

_remove_signers(ref self: ContractState, new_quorum: u32, signers_to_remove: Span<ContractAddress>)

internal

#

Removes existing signers and updates the quorum.

Requirements:

  • new_quorum must be non-zero and less than or equal to the total number of signers after removal.

Emits a SignerRemoved event for each signer removed.

Emits a QuorumUpdated event if the quorum changes.

_replace_signer(ref self: ContractState, signer_to_remove: ContractAddress, signer_to_add: ContractAddress)

internal

#

Replaces an existing signer with a new signer.

Requirements:

  • signer_to_remove must be an existing signer.
  • signer_to_add must not be an existing signer.
  • signer_to_add must be a non-zero address.

Emits a SignerRemoved event for the removed signer.

Emits a SignerAdded event for the new signer.

_change_quorum(ref self: ContractState, new_quorum: u32)

internal

#

Updates the quorum value to new_quorum if it differs from the current quorum.

Requirements:

  • new_quorum must be non-zero.
  • new_quorum must be less than or equal to the total number of signers.

Emits a QuorumUpdated event if the quorum changes.

Events

SignerAdded(signer: ContractAddress)

event

#

Emitted when a new signer is added.

SignerRemoved(signer: ContractAddress)

event

#

Emitted when a signer is removed.

QuorumUpdated(old_quorum: u32, new_quorum: u32)

event

#

Emitted when the quorum value is updated.

TransactionSubmitted(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a new transaction is submitted by a signer.

TransactionConfirmed(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a transaction is confirmed by a signer.

ConfirmationRevoked(id: TransactionID, signer: ContractAddress)

event

#

Emitted when a signer revokes his confirmation.

TransactionExecuted(id: TransactionID)

event

#

Emitted when a transaction is executed.

CallSalt(id: felt252, salt: felt252)

event

#

Emitted when a new transaction is submitted with non-zero salt.

Timelock

In a governance system, TimelockControllerComponent is in charge of introducing a delay between a proposal and its execution.

use openzeppelin_governance::timelock::TimelockControllerComponent;

Component that implements ITimelock and enables the implementing contract to act as a timelock controller.

Embeddable Mixin Implementations

TimelockMixinImpl

Embeddable Implementations

TimelockImpl

SRC5Impl

AccessControlImpl

AccessControlCamelImpl

Internal Implementations

InternalImpl

Events

Embeddable functions

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 current state of the operation with the given id.

The possible states are:

  • Unset: the operation has not been scheduled or has been canceled.
  • Waiting: the operation has been scheduled and is pending the scheduled delay.
  • Ready: the timer has expired, and the operation is eligible for execution.
  • Done: the operation has been executed.

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_ROLE role.
  • The proposal must not already exist.
  • delay must be greater than or equal to the min delay.

Emits CallScheduled event. Emits CallSalt event if salt is not zero.

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_ROLE role.
  • The proposal must not already exist.
  • delay must be greater than or equal to the min delay.

Emits one CallScheduled event for each transaction in the batch. Emits CallSalt event if salt is not zero.

cancel(ref self: ContractState, id: felt252)

external

#

Cancels an operation. A canceled operation returns to Unset OperationState.

Requirements:

  • The caller must have the CANCELLER_ROLE role.
  • id must be a pending 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.
  • id must be in Ready OperationState.
  • predecessor must either be 0 or 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.
  • id must be in Ready OperationState.
  • predecessor must either be 0 or 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.

Internal functions

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:

  • id must be in the Ready OperationState.
  • predecessor must either be zero or be in the Done OperationState.

_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:

  • id must 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.

Events

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.

CallSalt(id: felt252, salt: felt252)

event

#

Emitted when a new proposal is scheduled with non-zero salt.

CallCancelled(id: felt252)

event

#

Emitted when operation id is cancelled.

MinDelayChanged(old_duration: u64, new_duration: u64)

event

#

Emitted when the minimum delay for future operations is modified.

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.

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.

Voting Units Trait Implementations

ERC20VotesImpl

ERC721VotesImpl

Embeddable Implementations

VotesImpl

Internal implementations

InternalImpl

Events

get_voting_units(self: @ContractState, 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: @ContractState, 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.

Embeddable functions

get_votes(self: @ContractState, account: ContractAddress) → u256

external

#

Returns the current amount of votes that account has.

get_past_votes(self: @ContractState, account: ContractAddress, timepoint: u64) → u256

external

#

Returns the amount of votes that account had at a specific moment in the past.

Requirements:

  • timepoint must be in the past.

get_past_total_supply(self: @ContractState, 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:

  • timepoint must be in the past.

delegates(self: @ContractState, account: ContractAddress) → ContractAddress

external

#

Returns the delegate that account has chosen.

delegate(ref self: ContractState, 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: ContractState, delegator: ContractAddress, delegatee: ContractAddress, nonce: felt252, expiry: u64, signature: Span<felt252>)

external

#

Delegates votes from delegator to delegatee through a SNIP-12 message signature validation.

Requirements:

  • expiry must not be in the past.
  • nonce must match the account's current nonce.
  • delegator must implement SRC6::is_valid_signature.
  • signature should be valid for the message hash.

Emits a DelegateChanged event.

May emit one or two DelegateVotesChanged events.

clock(self: @ContractState) → u64

external

#

Returns the current timepoint determined by the contract's operational mode, intended for use in time-sensitive logic. See ERC-6372#clock.

Requirements:

  • This function MUST always be non-decreasing.

CLOCK_MODE(self: @ContractState) → u64

external

#

Returns a description of the clock the contract is operating in. See ERC-6372#CLOCK_MODE.

Requirements:

  • The output MUST be formatted like a URL query string, decodable in standard JavaScript.

Internal functions

get_total_supply(self: @ContractState) → u256

internal

#

Returns the current total supply of votes.

move_delegate_votes(ref self: ContractState, 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: ContractState, 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: @ContractState, account: ContractAddress) → u64

internal

#

Returns the number of checkpoints for account.

checkpoints(self: @ContractState, account: ContractAddress, pos: u64) → Checkpoint

internal

#

Returns the pos-th checkpoint for account.

_delegate(ref self: ContractState, 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.

Events

DelegateChanged(delegator: ContractAddress, from_delegate: ContractAddress, to_delegate: ContractAddress)

event

#

Emitted when an account changes their delegate.

DelegateVotesChanged(delegate: ContractAddress, previous_votes: u256, new_votes: u256)

event

#

Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.

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.

Functions

Functions

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.