GovernorUpgradeable
Inherits: Initializable, ContextUpgradeable, ERC165Upgradeable, EIP712Upgradeable, NoncesUpgradeable, IGovernor, IERC721Receiver, IERC1155Receiver
*Core of the governance system, designed to be extended through various modules. This contract is abstract and requires several functions to be implemented in various modules:
- A counting module must implement _quorumReached, {_voteSucceeded} and {_countVote}
- A voting module must implement {_getVotes}
- Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented*
State Variables
BALLOT_TYPEHASH
bytes32 public constant BALLOT_TYPEHASH =
keccak256("Ballot(uint256 proposalId,uint8 support,address voter,uint256 nonce)");
EXTENDED_BALLOT_TYPEHASH
bytes32 public constant EXTENDED_BALLOT_TYPEHASH =
keccak256("ExtendedBallot(uint256 proposalId,uint8 support,address voter,uint256 nonce,string reason,bytes params)");
ALL_PROPOSAL_STATES_BITMAP
bytes32 private constant ALL_PROPOSAL_STATES_BITMAP = bytes32((2 ** (uint8(type(ProposalState).max) + 1)) - 1);
GovernorStorageLocation
bytes32 private constant GovernorStorageLocation = 0x7c712897014dbe49c045ef1299aa2d5f9e67e48eea4403efa21f1e0f3ac0cb00;
Functions
_getGovernorStorage
function _getGovernorStorage() private pure returns (GovernorStorage storage $);
onlyGovernance
Restricts a function so it can only be executed through governance proposals. For example, governance parameter setters in {GovernorSettings} are protected using this modifier. The governance executing address may be different from the Governor's own address, for example it could be a timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus, for example, additional timelock proposers are not able to change governance parameters without going through the governance protocol (since v4.6).
modifier onlyGovernance();
__Governor_init
Sets the value for name and {version}
function __Governor_init(string memory name_) internal onlyInitializing;
__Governor_init_unchained
function __Governor_init_unchained(string memory name_) internal onlyInitializing;
receive
Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract)
receive() external payable virtual;
supportsInterface
Query if a contract implements an interface
Interface identification is specified in ERC-165. This function uses less than 30,000 gas.
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(IERC165, ERC165Upgradeable)
returns (bool);
Parameters
Name | Type | Description |
---|---|---|
interfaceId | bytes4 |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | true if the contract implements interfaceID and interfaceID is not 0xffffffff, false otherwise |
name
module:core
Name of the governor instance (used in building the EIP-712 domain separator).
function name() public view virtual returns (string memory);
version
module:core
Version of the governor instance (used in building the EIP-712 domain separator). Default: "1"
function version() public view virtual returns (string memory);
hashProposal
See IGovernor-hashProposal.
The proposal id is produced by hashing the ABI encoded targets
array, the values
array, the calldatas
array
and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id
can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in
advance, before the proposal is submitted.
Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the
same proposal (with same operation and same description) will have the same id if submitted on multiple governors
across multiple networks. This also means that in order to execute the same operation twice (on the same
governor) the proposer will have to change the description in order to avoid proposal id conflicts.
function hashProposal(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public pure virtual returns (uint256);
getProposalId
module:core
Function used to get the proposal id from the proposal details.
function getProposalId(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public view virtual returns (uint256);
state
module:core
Current state of a proposal, following Compound's convention
function state(uint256 proposalId) public view virtual returns (ProposalState);
proposalThreshold
module:core
The number of votes required in order for a voter to become a proposer.
function proposalThreshold() public view virtual returns (uint256);
proposalSnapshot
module:core
Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the following block.
function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);
proposalDeadline
module:core
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.
function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);
proposalProposer
module:core
The account that created a proposal.
function proposalProposer(uint256 proposalId) public view virtual returns (address);
proposalEta
module:core
The time when a queued proposal becomes executable ("ETA"). Unlike {proposalSnapshot} and {proposalDeadline}, 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.
function proposalEta(uint256 proposalId) public view virtual returns (uint256);
proposalNeedsQueuing
module:core
Whether a proposal needs to be queued before execution.
function proposalNeedsQueuing(uint256) public view virtual returns (bool);
_checkGovernance
Reverts if the msg.sender
is not the executor. In case the executor is not this contract
itself, the function reverts if msg.data
is not whitelisted as a result of an execute
operation. See {onlyGovernance}.
function _checkGovernance() internal virtual;
_quorumReached
Amount of votes already cast passes the threshold limit.
function _quorumReached(uint256 proposalId) internal view virtual returns (bool);
_voteSucceeded
Is the proposal successful or not.
function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool);
_getVotes
Get the voting weight of account
at a specific timepoint
, for a vote as described by params
.
function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256);
_countVote
Register a vote for proposalId
by account
with a given support
, voting weight
and voting params
.
Note: Support is generic and can represent various things depending on the voting system used.
function _countVote(uint256 proposalId, address account, uint8 support, uint256 totalWeight, bytes memory params)
internal
virtual
returns (uint256);
_tallyUpdated
Hook that should be called every time the tally for a proposal is updated. Note: This function must run successfully. Reverts will result in the bricking of governance
function _tallyUpdated(uint256 proposalId) internal virtual;
_defaultParams
Default additional encoded parameters used by castVote methods that don't include them Note: Should be overridden by specific implementations to use an appropriate value, the meaning of the additional params, in the context of that implementation
function _defaultParams() internal view virtual returns (bytes memory);
propose
See IGovernor-propose. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}.
function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description)
public
virtual
returns (uint256);
_propose
Internal propose mechanism. Can be overridden to add more logic on proposal creation. Emits a IGovernor-ProposalCreated event.
function _propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description,
address proposer
) internal virtual returns (uint256 proposalId);
queue
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. Emits a {ProposalQueued} event.
function queue(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
public
virtual
returns (uint256);
_queueOperations
Internal queuing mechanism. Can be overridden (without a super call) to modify the way queuing is
performed (for example adding a vault/timelock).
This is empty by default, and must be overridden to implement queuing.
This function returns a timestamp that describes the expected ETA for execution. If the returned value is 0
(which is the default value), the core will consider queueing did not succeed, and the public queue function
will revert.
NOTE: Calling this function directly will NOT check the current state of the proposal, or emit the
ProposalQueued
event. Queuing a proposal should be done using {queue}.
function _queueOperations(uint256, address[] memory, uint256[] memory, bytes[] memory, bytes32)
internal
virtual
returns (uint48);
execute
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. Emits a {ProposalExecuted} event. NOTE: Some modules can modify the requirements for execution, for example by adding an additional timelock.
function execute(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
public
payable
virtual
returns (uint256);
_executeOperations
Internal execution mechanism. Can be overridden (without a super call) to modify the way execution is
performed (for example adding a vault/timelock).
NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to
true or emit the ProposalExecuted
event. Executing a proposal should be done using execute.
function _executeOperations(
uint256,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32
) internal virtual;
cancel
Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e. before the vote starts. Emits a {ProposalCanceled} event.
function cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
public
virtual
returns (uint256);
_cancel
Internal cancel mechanism with minimal restrictions. A proposal can be cancelled in any state other than Canceled, Expired, or Executed. Once cancelled a proposal can't be re-submitted. Emits a IGovernor-ProposalCanceled event.
function _cancel(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash)
internal
virtual
returns (uint256);
getVotes
module:reputation
Voting power of an account
at a specific timepoint
.
Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
multiple), {ERC20Votes} tokens.
function getVotes(address account, uint256 timepoint) public view virtual returns (uint256);
getVotesWithParams
module:reputation
Voting power of an account
at a specific timepoint
given additional encoded parameters.
function getVotesWithParams(address account, uint256 timepoint, bytes memory params)
public
view
virtual
returns (uint256);
castVote
Cast a vote Emits a {VoteCast} event.
function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256);
castVoteWithReason
Cast a vote with a reason Emits a {VoteCast} event.
function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason)
public
virtual
returns (uint256);
castVoteWithReasonAndParams
Cast a vote with a reason and additional encoded parameters Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
function castVoteWithReasonAndParams(uint256 proposalId, uint8 support, string calldata reason, bytes memory params)
public
virtual
returns (uint256);
castVoteBySig
Cast a vote using the voter's signature, including ERC-1271 signature support. Emits a {VoteCast} event.
function castVoteBySig(uint256 proposalId, uint8 support, address voter, bytes memory signature)
public
virtual
returns (uint256);
castVoteWithReasonAndParamsBySig
Cast a vote with a reason and additional encoded parameters using the voter's signature, including ERC-1271 signature support. Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
function castVoteWithReasonAndParamsBySig(
uint256 proposalId,
uint8 support,
address voter,
string calldata reason,
bytes memory params,
bytes memory signature
) public virtual returns (uint256);
_validateVoteSig
Validate the signature
used in castVoteBySig function.
function _validateVoteSig(uint256 proposalId, uint8 support, address voter, bytes memory signature)
internal
virtual
returns (bool);
_validateExtendedVoteSig
Validate the signature
used in castVoteWithReasonAndParamsBySig function.
function _validateExtendedVoteSig(
uint256 proposalId,
uint8 support,
address voter,
string memory reason,
bytes memory params,
bytes memory signature
) internal virtual returns (bool);
_castVote
Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve voting weight using IGovernor-getVotes and call the {_countVote} internal function. Uses the _defaultParams(). Emits a {IGovernor-VoteCast} event.
function _castVote(uint256 proposalId, address account, uint8 support, string memory reason)
internal
virtual
returns (uint256);
_castVote
Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve voting weight using IGovernor-getVotes and call the {_countVote} internal function. Emits a {IGovernor-VoteCast} event.
function _castVote(uint256 proposalId, address account, uint8 support, string memory reason, bytes memory params)
internal
virtual
returns (uint256);
relay
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 or Ether that was sent to the governor contract by mistake.
Note that if the executor is simply the governor itself, use of relay
is redundant.
function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance;
_executor
Address through which the governor executes action. Will be overloaded by module that execute actions through another contract such as a timelock.
function _executor() internal view virtual returns (address);
onERC721Received
See IERC721Receiver-onERC721Received. Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4);
onERC1155Received
See IERC1155Receiver-onERC1155Received. Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4);
onERC1155BatchReceived
See IERC1155Receiver-onERC1155BatchReceived. Receiving tokens is disabled if the governance executor is other than the governor itself (eg. when using with a timelock).
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory)
public
virtual
returns (bytes4);
_encodeStateBitmap
Encodes a ProposalState
into a bytes32
representation where each bit enabled corresponds to
the underlying position in the ProposalState
enum. For example:
0x000...10000
^^^^^^------ ...
^----- Succeeded
^---- Defeated
^--- Canceled
^-- Active
^- Pending
function _encodeStateBitmap(ProposalState proposalState) internal pure returns (bytes32);
_validateStateBitmap
Check that the current state of a proposal matches the requirements described by the allowedStates
bitmap.
This bitmap should be built using _encodeStateBitmap
.
If requirements are not met, reverts with a {GovernorUnexpectedProposalState} error.
function _validateStateBitmap(uint256 proposalId, bytes32 allowedStates) internal view returns (ProposalState);
_isValidDescriptionForProposer
function _isValidDescriptionForProposer(address proposer, string memory description)
internal
view
virtual
returns (bool);
_validateCancel
Check if the caller
can cancel the proposal with the given proposalId
.
The default implementation allows the proposal proposer to cancel the proposal during the pending state.
function _validateCancel(uint256 proposalId, address caller) internal view virtual returns (bool);
clock
Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
function clock() public view virtual returns (uint48);
CLOCK_MODE
Description of the clock
function CLOCK_MODE() public view virtual returns (string memory);
votingDelay
module:user-config
Delay, between the proposal is created and 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. NOTE: While this interface returns a uint256, timepoints are stored as uint48 following the ERC-6372 clock type. Consequently this value must fit in a uint48 (when added to the current clock). See {IERC6372-clock}.
function votingDelay() public view virtual returns (uint256);
votingPeriod
module:user-config
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. NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting duration compared to the voting delay. NOTE: 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. The type used to save it is a uint32. Consequently, while this interface returns a uint256, the value it returns should fit in a uint32.
function votingPeriod() public view virtual returns (uint256);
quorum
module:user-config
Minimum number of cast voted required for a proposal to be successful.
NOTE: The timepoint
parameter corresponds to the snapshot used for counting vote. This allows to scale the
quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}).
function quorum(uint256 timepoint) public view virtual returns (uint256);
_unsafeReadBytesOffset
Reads a bytes32 from a bytes array without bounds checking. NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the assembly block as such would prevent some optimizations.
function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value);
Structs
ProposalCore
struct ProposalCore {
address proposer;
uint48 voteStart;
uint32 voteDuration;
bool executed;
bool canceled;
uint48 etaSeconds;
}
GovernorStorage
Note: storage-location: erc7201:openzeppelin.storage.Governor
struct GovernorStorage {
string _name;
mapping(uint256 proposalId => ProposalCore) _proposals;
DoubleEndedQueue.Bytes32Deque _governanceCall;
}