Governance Token
Table of Contents
Overview
Constants | Value |
---|---|
Address | 0x4200000000000000000000000000000000000042 |
Token name | Optimism |
Token symbol | OP |
Token decimals | 18 |
GovernanceToken
is an ERC20 token contract that inherits from ERC20Burnable
,
ERC20Votes
, and Ownable
. It allows token holders to delegate their voting power to other addresses, enabling a representative
voting system. The contract integrates with the GovernanceDelegation
contract through a hook-based approach to support
advanced delegation.
Hook-based Integration with GovernanceDelegation
Advanced delegation includes relative and absolute partial delegation, which allow delegators to distribute their voting
power among multiple delegates in a fractional manner. The _afterTokenTransfer
function in the GovernanceToken
is
modified to call the afterTokenTransfer
function in the GovernanceDelegation
contract, allowing the GovernanceDelegation
contract to consume the hooks and update its delegation and checkpoint mappings accordingly.
If the call to the GovernanceDelegation
's afterTokenTransfer
function fails, the token transfer MUST revert. This ensures
that the GovernanceDelegation
contract remains in sync with the GovernanceToken
. Otherwise, the GovernanceToken
could
be left in an inconsistent state relative to the GovernanceDelegation
contract, such as when a token transfer is successful
but the delegation state is not updated.
All delegation-related state, including the delegates
, checkpoints
, and numCheckpoints
mappings, is gradually
shifted from the GovernanceToken
to the GovernanceDelegation
contract through transactions that call the
GovernanceDelegation
's hook (e.g. transfers). In the hook, the GovernanceDelegation
contract should check if the to
and from
addresses have been migrated. If an address hasn't been migrated, the GovernanceDelegation
contract should
write the data from the GovernanceToken
's mappings for that address to its own state. When reading delegation data in the
GovernanceDelegation
contract for a delegator that hasn't been migrated, the GovernanceDelegation
should pull the data
from the GovernanceToken
's state.
For backwards compatibility, the getter methods in the GovernanceToken
MUST check if the data of a given address has been
migrated or not. If the data has been migrated, the GovernanceToken
MUST forward the call to the GovernanceDelegation
contract. Otherwise, the GovernanceToken
MUST read from its state.
The delegate
and delegateBySig
functions in the GovernanceToken
MUST forward the calls to the GovernanceDelegation
contract, which implements the required delegation logic.
Token Minting
GovernanceToken
MUST have a mint(address,uint256)
function with external visibility that allows the contract owner
to mint an arbitrary number of new tokens to a specific address. This function MUST only be called by the contract
owner, the MintManager
, as enforced by the onlyOwner
modifier inherited from the Ownable
contract. When tokens
are minted, the voting power of the recipient address MUST be updated accordingly in the GovernanceDelegation
contract
via the afterTokenTransfer
hook. The total token supply is capped to 2^208 - 1
to prevent overflow risks in the voting
system. If the total supply exceeds this limit, _mint(address,uint256)
, as inherited from ERC20Votes
, MUST revert.
Token Burning
The contract MUST allow token holders to burn their own tokens using the inherited burn(uint256)
or
burnFrom(address,uint256)
functions inherited from ERC20Burnable
. When tokens are burned, the total supply and the
holder's voting power MUST be reduced accordingly in the GovernanceDelegation
contract via the afterTokenTransfer
hook.
Voting Power
Each token corresponds to one unit of voting power. By default, token balance does not account for voting power. To have their voting power counted, token holders MUST delegate their voting power to an address (can be their own address). The contract MUST offer public accessors for querying voting power, as outlined below.
Queries
- The
getVotes(address)(uint256)
function MUST retrieve the current voting power of an address from theGovernanceDelegation
contract. - The
getPastVotes(address,uint256)(uint256)
function MUST allow querying the voting power of an address at a specific block number in the past from theGovernanceDelegation
contract. - The
getPastTotalSupply(uint256)(uint256)
function MUST return the total voting power at a specific block number in the past from theGovernanceDelegation
contract.
Delegation
Vote power can be delegated either by calling the delegate(address)
function directly (to delegate as the msg.sender
)
or by providing a signature to be used with function delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)
,
as inherited from ERC20Votes
. These functions are modified to forward the calls to the GovernanceDelegation
contract
which implements the required logic.
The GovernanceDelegation
contract maintains the necessary invariants, such as preventing circular delegation chains, ensuring
vote weight consistency, and managing checkpoints. It is incorporated as a predeploy of the OP stack to avoid manual deployments
across the Superchain.