LogoLogo
  • Tally Docs
  • Tally Features
    • What is Tally?
    • Token Launch
      • Claim
      • Governance Smart Contracts
      • Token Wrapper
      • Delegate Registration & Claim-and-Delegate
    • Value Accrual with Staking
      • Features & Use Cases
      • FAQ
      • Glossary
    • Governance
      • Advanced Features
        • MultiGov
        • Advanced Voting
          • Flexible Voting Extension
          • Signal Voting
            • Snapshot
          • Private Voting
        • Partial Delegation
        • Security Council Elections
        • Chain Integration
        • Proposal Templates
        • Optimistic Governance
        • Gasless Voting and Delegation (Relay)
          • Gasless Voting
          • Gasless Delegation
        • Integrations
          • Karma - Delegate Scoring
          • Discourse
          • Safe
      • Standard Features
    • Tally API
    • Tally Zero
  • How to Use Tally
    • Navigate the Tally homepage
    • Set up a Tally Profile
    • Create Proposals
      • Custom Actions
        • Chain Deployment of Uniswap v3
        • Token Vesting with Hedgey
        • Token Grants with Hedgey
        • Streaming Payments with Sablier
        • Tuple Support
      • Swaps
        • Swaps: FAQs
      • Draft Proposals
      • Test Proposals
    • Execute Proposals
      • Advanced Execution
    • Delegate on Tally
      • Delegates Page
      • Delegate Voting Power
      • Create a Delegate Statement
    • Vote on Tally
    • Stake on Tally
    • Get Notifications on Tally
    • Use Tally with a Gnosis Safe
      • Vote with a Gnosis Safe
      • Zodiac Governor Module for SubDAOs and Grants Programs
      • Upgrade Gnosis Safe to Governor with Zodiac
    • Participate in Security Council Elections
    • Using Ledger with Solana
  • Set up & Technical Documentation
    • Tally Architecture
    • Deploy a Governor DAO
      • Deploy a Governor
        • Deploy a Governor with a new token
      • Add a Governor to an existing token
      • Check for Token Contract Compatibility
        • Network Support
        • OpenZeppelin Governor
        • Compound Governor Bravo
        • Tokens: ERC-20 and NFTs
      • Choose Governor parameters
    • Add a DAO to Tally
      • DAO Admins
      • DAO Settings
    • Use Governor with Gnosis Safe
      • Gnosis Safe Overview
      • Zodiac Governor Module for SubDAOs and Grants Programs
      • Upgrade Gnosis Safe to Governor with Zodiac
    • Staking Contracts
      • Get Started
      • How Staking Works
        • Liquid Staking
          • LST Auto delegates
      • Staking Operator's Guide
      • DeFi Integration Guide
      • FAQ & Troubleshooting
    • Security
    • Chain Compatibility
  • Education
    • Intro to Governance
      • General Ecosystem Info
      • Participating in Governance
    • Governance Concepts
      • Decentralized Governance Overview
      • Onchain vs Offchain Voting
      • Application Layer vs. Base Layer Governance
      • Governance Execution Methods
      • Procedural Governance
      • Vote Delegation
    • Governance Frameworks
      • OpenZeppelin Governor
      • Curve Voting Escrow
      • Multisigs
      • Snapshot Polls
    • DAO Best Practices
      • Running an Onchain DAO Using OpenZeppelin Governor
    • Index of DAOs
      • DAOs on Tally
        • Aave (AAVE)
        • Ampleforth (FORTH)
        • Arbitrum (ARB)
        • Compound (COMP)
        • Gitcoin (GTC)
        • GMX
        • Idle Finance (IDLE)
        • Inverse Finance (INV)
        • PoolTogether (POOL)
        • Uniswap (UNI)
        • ZKsync
      • DAOs Not on Tally
        • Balancer (BAL)
        • Curve (CRV)
        • Index Coop (INDEX)
        • KyberDAO (KNC)
        • MakerDAO (MKR)
        • Sushi (SUSHI)
  • Resources
    • Tally Platform
    • Blog
    • DAO Talk Podcast
    • Newsletter
    • Twitter / X
  • Payment Addresses
Powered by GitBook
On this page
  • Event signatures
  • Function signatures
  • Proposal state lifecycle
  • Governor Parameter Changes
  • Quorum Extension
  • Clock Mode

Was this helpful?

Export as PDF
  1. Set up & Technical Documentation
  2. Deploy a Governor DAO
  3. Check for Token Contract Compatibility

OpenZeppelin Governor

Compatibility considerations when implementing OpenZeppelin governor

PreviousNetwork SupportNextCompound Governor Bravo

Last updated 1 year ago

Was this helpful?

To be compatible with the Tally app we recommend you to use OpenZeppelin's library . If you want to implement changes to this base contract, here is the interface that you should follow to make sure your contract works with our app.

Event signatures

Tally's API listens to event logs from Governor contracts when indexing them. Your contract will need to maintain the same event signatures that OZ Governor implements:

event ProposalCreated(
    uint256 proposalId,
    address proposer,
    address[] targets,
    uint256[] values,
    string[] signatures,
    bytes[] calldatas,
    uint256 startBlock,
    uint256 endBlock,
    string description
);

event ProposalQueued(uint256 proposalId, uint256 etaSeconds);
event ProposalCanceled(uint256 proposalId);
event ProposalExecuted(uint256 proposalId);

event VoteCast(
    address indexed voter, 
    uint256 proposalId, 
    uint8 support, 
    uint256 weight, 
    string reason
);

Function signatures

Tally's frontend app helps users make web3 calls to your Governor contract. The app lets users create Proposals as well as vote on, queue and execute them. In addition, the app reads state from the contract with function calls.

To be compatible with Tally, your Governor will need these function signatures:

function votingDelay() public view virtual returns (uint256);
function votingPeriod() public view virtual returns (uint256);
function quorum(uint256 timepoint) public view virtual returns (uint256);
function proposalThreshold() public view virtual returns (uint256);
function state(uint256 proposalId) public view virtual override returns (
    ProposalState
);

function getVotes(
    address account, 
    uint256 timepoint
) public view virtual returns (uint256);

function propose(
    address[] memory targets,
    uint256[] memory values,
    bytes[] memory calldatas,
    string memory description
) public virtual returns (uint256 proposalId);

function execute(
    address[] memory targets,
    uint256[] memory values,
    bytes[] memory calldatas,
    bytes32 descriptionHash
) public payable virtual returns (uint256 proposalId);

function castVote(
    uint256 proposalId, 
    uint8 support
) public virtual returns (uint256 balance);

function castVoteWithReason(
    uint256 proposalId,
    uint8 support,
    string calldata reason
) public virtual returns (uint256 balance);

function castVoteBySig(
    uint256 proposalId,
    uint8 support,
    uint8 v,
    bytes32 r,
    bytes32 s
) public virtual returns (uint256 balance);

If your OpenZeppelin governor contract uses a Timelock, it will also need this signature:

function queue(
    address[] memory targets,
    uint256[] memory values,
    bytes[] memory calldatas,
    bytes32 descriptionHash
) public virtual override returns (uint256)

Quorum

Tally needs the quorum to calculate if a proposal has passed. That means that Tally requires the Governor to have a quorum() function:

function quorum(uint256 timepoint) public view virtual returns (uint256);

Optionally, Tally also supports the quorumNumerator() and quorumDenominator() functions. Governors with quorums that are a function of token supply should implement these functions:

function quorumNumerator() public view virtual returns (uint256);
function quorumDenominator() public view virtual returns (uint256);

If the Governor is missing either quorumNumerator() or quorumDenominator(), Tally falls back to the quorum() function and assumes that the quorum is fixed.

Voting Delay

Tally needs to know the voting delay to calculate when voting starts without polling the blockchain. A votingDelay() function on Governor is required:

function votingDelay() public view virtual returns (uint256);

Voting Period

Tally needs to know the voting period to calculate when a proposal finishes voting without polling the blockchain. A votingPeriod() function on Governor is required:

function votingPeriod() public view virtual returns (uint256);

Proposal state lifecycle

Tally's app expects the following proposal states. If your Governor uses a custom proposal lifecycle, those states won't show up correctly on on Tally:

enum ProposalState {
    Pending,
    Active,
    Canceled,
    Defeated,
    Succeeded,
    Queued,
    Expired,
    Executed
}

Governor Parameter Changes

Governors can change their own parameters, like proposal times and the amount of voting power required to create and pass proposals. To make sure that Tally indexes your Governor's parameter changes, implement these event signatures:

 event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);
 event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);
 event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);
 event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator);

If your OpenZeppelin governor contract uses a Timelock, it will also need this event:

event TimelockChange(address oldTimelock, address newTimelock);

Quorum Extension

Tally handles the ProposalExtended event, which is emitted by governors that implement the PreventLateQuorum extension:

event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline);

Clock Mode

Since Governor v4.9, all voting contracts (including and ) rely on for clock management. The Governor will automatically detect the clock mode used by the token and adapt to it. There is no need to override anything in the Governor contract. You can learn more about compatibility of your token and Governor contract with clock mode .

Tally checks the contract lock using the standard. We accept blocknumber and timestamp clock modes.Specifically, Tally expects Governor and token contracts to implement a CLOCK_MODE() function that returns either mode=blocknumber&from=default or mode=blocknumber&from=<CAIP-2-ID> . If the call to the governor's CLOCK_MODE() method returns mode=timestamp then proposal start and end times will be interpreted as unix timestamps otherwise they will be interpreted as block numbers.

If you're interested in support for another contract clock, Tally would need to do some custom work. Get in touch with .

Governor contract
ERC20Votes
ERC721Votes
IERC6372
here
IERC-6372
biz@tally.xyz