GovernanceToken
Table of Contents
Overview
The GovernanceToken is an ERC20 token that serves as the governance token for the OP Stack. It enables token holders to participate in governance through voting and delegation mechanisms while supporting controlled token inflation through owner-managed minting.
Definitions
MintManager
The contract that owns the GovernanceToken and has exclusive authority to mint new tokens. The MintManager enforces on-chain rate limits and caps on minting operations according to governance-approved token inflation schedules.
Assumptions
aGT-001: Owner operates within governance constraints
The contract owner (MintManager) is trusted to mint tokens only in accordance with governance decisions and established protocol rules.
Mitigations
- Owner is expected to be a governance-controlled MintManager contract
- MintManager enforces on-chain rate limits and caps on minting operations
- Ownership transfers are transparent and subject to community oversight
Invariants
iGT-001: Voting power reflects delegated balance
The voting power of any address always equals the sum of token balances that have been delegated to that address.
Impact
Severity: High
If this invariant is violated, governance voting would become unreliable. Addresses could have voting power that doesn't correspond to actual delegated tokens, allowing manipulation of governance decisions and undermining the integrity of the voting system.
iGT-002: Delegation does not restrict transfers
Token holders can always transfer their tokens regardless of whether they have delegated their voting power or whether their tokens have been delegated to them by others.
Impact
Severity: High
If this invariant is violated, tokens would become illiquid when delegated, preventing normal token transfers and breaking the fungibility of the token. This would severely impact the token's utility and market functionality.
iGT-003: Unauthorized minting is impossible
Only the contract owner can successfully mint new tokens through the mint function.
Impact
Severity: Critical
If this invariant is violated, unauthorized parties could mint unlimited tokens, completely destroying the token's economic value, diluting existing holders, and compromising the entire governance system.
iGT-004: Standard ERC20Votes compliance
The contract maintains full compatibility with ERC20, ERC20Votes, ERC20Permit, and ERC20Burnable standards without custom modifications that break standard behavior.
Impact
Severity: Critical
If this invariant is violated, the token would lose compatibility with standard governance systems, wallets, and DeFi protocols. Governance contracts expecting standard ERC20Votes behavior would malfunction, voting power calculations could become incorrect, and the token would not be usable in standard governance frameworks like OpenZeppelin Governor or Compound-style governance systems.
Function Specification
mint
function mint(address _account, uint256 _amount) public onlyOwner
Mints new governance tokens to the specified account.
Parameters:
_account: The address that will receive the newly minted tokens_amount: The number of tokens to mint (in wei, with 18 decimals)
Behavior:
- MUST revert if caller is not the contract owner
- MUST mint
_amounttokens to_account - MUST increase total supply by
_amount - MUST update voting power for
_accountif they have delegated to themselves or if another address has delegated to them - MUST emit Transfer event from zero address to
_account - MUST revert if total supply would exceed 2^208 - 1
burn
function burn(uint256 amount) public
Allows token holders to burn their own tokens.
Parameters:
amount: The number of tokens to burn
Behavior:
- MUST revert if caller's balance is less than
amount - MUST reduce caller's balance by
amount - MUST reduce total supply by
amount - MUST update voting power for the caller's delegate
- MUST emit Transfer event from caller to zero address
burnFrom
function burnFrom(address account, uint256 amount) public
Allows burning tokens from another account with proper allowance.
Parameters:
account: The address from which tokens will be burnedamount: The number of tokens to burn
Behavior:
- MUST revert if caller's allowance for
accountis less thanamount - MUST revert if
account's balance is less thanamount - MUST reduce
account's balance byamount - MUST reduce caller's allowance by
amount - MUST reduce total supply by
amount - MUST update voting power for
account's delegate - MUST emit Transfer event from
accountto zero address - MUST emit Approval event reflecting the reduced allowance
delegate
function delegate(address delegatee) public
Delegates the caller's voting power to another address.
Parameters:
delegatee: The address to delegate voting power to (can be the caller's own address)
Behavior:
- MUST update the delegation mapping to record that caller delegates to
delegatee - MUST transfer voting power from the caller's previous delegate to the new
delegatee - MUST create a checkpoint recording the voting power change
- MUST emit DelegateChanged event with the caller, previous delegate, and new delegate
- MUST emit DelegateVotesChanged events for both the previous and new delegates
- MUST NOT prevent the caller from transferring tokens after delegation
delegateBySig
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) public
Delegates voting power using an EIP-712 signature, enabling gasless delegation.
Parameters:
delegatee: The address to delegate voting power tononce: The nonce for replay protectionexpiry: The timestamp after which the signature expiresv: The recovery byte of the signaturer: The first 32 bytes of the signatures: The second 32 bytes of the signature
Behavior:
- MUST revert if the signature has expired (block.timestamp > expiry)
- MUST revert if the nonce is incorrect for the signer
- MUST recover the signer address from the signature
- MUST revert if signature is invalid
- MUST perform delegation on behalf of the recovered signer address
- MUST increment the nonce for the signer
- MUST emit DelegateChanged and DelegateVotesChanged events as in delegate function
getVotes
function getVotes(address account) public view returns (uint256)
Returns the current voting power of an address.
Parameters:
account: The address to query
Behavior:
- MUST return the current voting power delegated to
account - MUST reflect all delegations made up to the current block
- MUST NOT include tokens held by
accountunless they have delegated to themselves
getPastVotes
function getPastVotes(address account, uint256 blockNumber) public view returns (uint256)
Returns the voting power of an address at a specific block in the past.
Parameters:
account: The address to queryblockNumber: The block number to query (must be in the past)
Behavior:
- MUST revert if
blockNumberis greater than or equal to the current block number - MUST return the voting power delegated to
accountat the specified block - MUST use checkpoints to efficiently retrieve historical voting power
getPastTotalSupply
function getPastTotalSupply(uint256 blockNumber) public view returns (uint256)
Returns the total voting power at a specific block in the past.
Parameters:
blockNumber: The block number to query (must be in the past)
Behavior:
- MUST revert if
blockNumberis greater than or equal to the current block number - MUST return the total supply of tokens at the specified block
- MUST use checkpoints to efficiently retrieve historical total supply
delegates
function delegates(address account) public view returns (address)
Returns the address that an account has delegated their voting power to.
Parameters:
account: The address to query
Behavior:
- MUST return the address that
accountis currently delegating to - MUST return the zero address if
accounthas never delegated
transfer
function transfer(address to, uint256 amount) public returns (bool)
Transfers tokens from the caller to another address.
Parameters:
to: The recipient addressamount: The number of tokens to transfer
Behavior:
- MUST revert if caller's balance is less than
amount - MUST revert if
tois the zero address - MUST reduce caller's balance by
amount - MUST increase
to's balance byamount - MUST update voting power for both the caller's delegate and
to's delegate - MUST emit Transfer event
- MUST return true on success
transferFrom
function transferFrom(address from, address to, uint256 amount) public returns (bool)
Transfers tokens from one address to another using allowance mechanism.
Parameters:
from: The address to transfer tokens fromto: The recipient addressamount: The number of tokens to transfer
Behavior:
- MUST revert if caller's allowance for
fromis less thanamount(unless allowance is max uint256) - MUST revert if
from's balance is less thanamount - MUST revert if
tois the zero address - MUST reduce
from's balance byamount - MUST increase
to's balance byamount - MUST reduce caller's allowance by
amount(unless allowance is max uint256) - MUST update voting power for both
from's delegate andto's delegate - MUST emit Transfer event
- MUST emit Approval event if allowance was reduced
- MUST return true on success
approve
function approve(address spender, uint256 amount) public returns (bool)
Approves another address to spend tokens on behalf of the caller.
Parameters:
spender: The address authorized to spend tokensamount: The number of tokens approved for spending
Behavior:
- MUST set the allowance for
spendertoamount - MUST emit Approval event
- MUST return true on success
- MUST allow setting allowance to zero to revoke approval
permit
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public
Approves spending using an EIP-2612 signature, enabling gasless approvals.
Parameters:
owner: The address granting the approvalspender: The address receiving the approvalvalue: The amount approved for spendingdeadline: The timestamp after which the signature expiresv: The recovery byte of the signaturer: The first 32 bytes of the signatures: The second 32 bytes of the signature
Behavior:
- MUST revert if the signature has expired (block.timestamp > deadline)
- MUST recover the signer address from the EIP-712 signature
- MUST revert if recovered signer does not match
owner - MUST revert if signature is invalid
- MUST set the allowance for
spendertovalue - MUST increment the nonce for
owner - MUST emit Approval event