Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Token Governance Proposal System

A technical guide for developers on implementing a complete on-chain governance workflow, from proposal creation to execution, with code examples and integration with off-chain tools like Snapshot.
Chainscore © 2026
introduction
ON-CHAIN GOVERNANCE

Setting Up a Token Governance Proposal System

A practical guide to implementing a basic on-chain governance system using smart contracts, enabling token holders to propose, vote on, and execute changes to a protocol.

On-chain governance systems allow decentralized protocols to evolve through the collective decisions of their token holders. Unlike off-chain signaling, these systems encode proposal creation, voting, and execution logic directly into smart contracts. This ensures transparency and enforces outcomes automatically. A typical system involves three core components: a governance token for voting power, a proposal contract to manage the lifecycle of initiatives, and a timelock contract to safely execute passed proposals after a delay. Popular implementations like Compound's Governor Bravo and OpenZeppelin's Governor provide standardized, audited foundations for developers.

The first step is defining the governance token, which is often an ERC-20 with snapshot voting or delegation features. For a simple setup, you can use OpenZeppelin's contracts. The governance contract itself inherits from Governor.sol and requires you to configure key parameters: votingDelay (blocks before voting starts), votingPeriod (duration of the vote), and quorum (minimum votes needed). Proposal thresholds can be set to require a minimum token balance to submit. Here's a basic contract skeleton:

solidity
import "@openzeppelin/contracts/governance/Governor.sol";
contract MyGovernor is Governor {
    constructor(IVotes _token)
        Governor("MyGovernor")
    {}
    function votingDelay() public pure override returns (uint256) { return 1; } // 1 block
    function votingPeriod() public pure override returns (uint256) { return 45818; } // ~1 week
    function quorum(uint256 blockNumber) public pure override returns (uint256) {
        return 1000e18; // 1000 tokens
    }
}

Proposals target specific function calls on other contracts. When a proposal is created, it stores an array of targets, values, and calldatas. For security, executed proposals are routed through a Timelock contract. This introduces a mandatory delay between a proposal's passing and its execution, giving users time to exit if they disagree with the outcome. The governance contract must be set as the proposer and executor on the Timelock. Voting uses the ERC-20Votes standard for snapshot-based voting power, preventing token transfers from affecting ongoing votes. Users can delegate their voting power to themselves or others to participate.

To interact with the system, a user with sufficient tokens calls propose() with the desired actions. Once the voting delay passes, token holders cast votes using castVote(), typically choosing For, Against, or Abstain. After the voting period ends, anyone can call queue() to move a successful proposal to the Timelock queue. Following the timelock delay, execute() finalizes the proposal, making the encoded function calls. It's critical to thoroughly test all state changes in a forked environment like Hardhat or Foundry before deployment. Audit the integration points, especially the permissions between the Governor, Timelock, and target contracts.

Real-world governance systems add complexity: vote delegation platforms like Tally, gasless voting via snapshot signatures, and multisig guardians for emergency actions. When designing your system, consider the trade-offs between decentralization and efficiency. A low quorum or short voting period increases agility but may reduce legitimacy. Always document the process clearly for token holders, specifying how to create proposals, delegate votes, and understand the execution timeline. Reference established documentation from Compound or OpenZeppelin for best practices and security considerations.

prerequisites
SETUP GUIDE

Prerequisites and Required Tools

Before deploying a token governance proposal system, you need the right development environment, blockchain access, and smart contract libraries. This guide outlines the essential tools and knowledge required.

A robust development environment is the foundation. You will need Node.js (version 18 or later) and a package manager like npm or yarn. For smart contract development, the Hardhat or Foundry frameworks are industry standards, providing testing, deployment, and scripting capabilities. Install these globally or within your project. A code editor such as VS Code with Solidity extensions is recommended for efficient development and debugging.

You must interact with a blockchain. For initial development and testing, a local network like Hardhat Network is ideal. For testing on public testnets (e.g., Sepolia, Goerli), you'll need an RPC provider like Alchemy or Infura and a funded wallet. Essential tools include MetaMask for browser-based interactions and a command-line tool like cast (from Foundry) for advanced scripting. Securely manage your private keys and environment variables using a .env file.

Your smart contracts will rely on established libraries. For governance, OpenZeppelin Contracts is indispensable. You will import their Governor contracts, along with Votes and TimelockController modules. Install them via npm (@openzeppelin/contracts). For token standards, you'll need the ERC-20 Votes extension or ERC-721 for NFT-based governance. Familiarity with Solidity (0.8.x) and concepts like upgradeable proxies (using @openzeppelin/contracts-upgradeable) is also crucial for future-proof systems.

Understanding the governance lifecycle is key before coding. A typical flow involves: 1) A user creates a proposal, 2) Token holders cast votes (e.g., for, against, abstain), 3) Votes are tallied after a voting period, and 4) If successful, the proposal actions are executed, often via a Timelock for security. You should decide on parameters like votingDelay, votingPeriod, and proposalThreshold early in your design process.

Finally, prepare for interaction and automation. You will write scripts to deploy contracts, create proposals, and query results. Knowledge of Ethers.js or Viem libraries is required for front-end or back-end integration. For a complete guide, refer to the OpenZeppelin Governor documentation. With these tools and concepts in place, you are ready to build a secure and functional governance system.

core-components
CORE COMPONENTS

Setting Up a Token Governance Proposal System

A token governance contract is the on-chain engine for decentralized decision-making. This guide breaks down its essential components, from proposal creation to execution.

A robust governance system requires several key on-chain components to function. The core is the governance token, which grants voting power, typically through a balanceOf or getVotes function that accounts for delegation. The Governor contract itself manages the proposal lifecycle, defining states like Pending, Active, Succeeded, and Executed. A TimelockController is a critical security module that queues and executes successful proposals after a mandatory delay, preventing rushed or malicious actions. This separation of powers—voting, queuing, and execution—is a foundational security pattern.

Proposal creation is initiated by a function like propose, which takes an array of target addresses, values, and calldata for the proposed actions. The proposer must hold a minimum number of tokens, the proposal threshold. Once created, the proposal enters a voting delay period, allowing voters time to review before the voting period begins. During voting, token holders cast their vote—typically For, Against, or Abstain—with their voting power snapshot at the start of the block. Major implementations like OpenZeppelin's Governor provide a modular base contract that you extend to configure these parameters.

The voting mechanism determines how consensus is reached. The most common is quorum-based voting, where a minimum percentage of the total token supply must participate for the vote to be valid. A proposal passes if the For votes exceed the Against votes and the quorum is met. Some systems use vote weighting strategies, such as quadratic voting or time-lock weighted voting (like in veToken models), to mitigate whale dominance. The specific logic is contained in the voting module, which can be swapped to alter the governance mechanics without rewriting the entire system.

After a successful vote, execution is not immediate. Proposals are sent to a Timelock. This contract holds the authority to execute transactions and enforces a mandatory waiting period. This delay gives the community a final chance to react—for example, by exiting a protocol—if they disagree with the now-approved action. Once the timelock delay expires, any address can call the execute function on the Governor contract, which in turn instructs the Timelock to perform the queued transactions. This multi-step process is vital for secure, transparent on-chain governance.

Here is a simplified code example for a basic proposal flow using Solidity and OpenZeppelin contracts:

solidity
// 1. Propose
function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description) public returns (uint256 proposalId) {
    require(getVotes(msg.sender, block.number - 1) >= proposalThreshold(), "Governor: proposer votes below threshold");
    proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
    // ... store proposal state
}
// 2. Cast a vote
function castVote(uint256 proposalId, uint8 support) public returns (uint256 balance) {
    // ... logic to record vote with voter's snapshot balance
}
// 3. Queue & Execute via Timelock
function queue(uint256 proposalId) public {
    _queueOperations(proposalId, eta); // Queues in Timelock
}
function execute(uint256 proposalId) public payable {
    _executeOperations(proposalId); // Executes via Timelock
}

When deploying a system, you must carefully configure parameters like the votingDelay (e.g., 1 day), votingPeriod (e.g., 3 days), proposalThreshold (e.g., 10,000 tokens), and quorum (e.g., 4% of total supply). These values define the pace and security of your governance. Always use audited, standard libraries like OpenZeppelin Governor as a foundation. For production, consider gas-efficient vote snapshotting with EIP-5805 and delegate functionality. The final system should be transparent, with all proposal data and voting history permanently recorded on-chain for verification.

key-parameters
DAO ENGINEERING

Key Governance Parameters to Configure

Configuring a proposal system requires precise parameter tuning. These settings define voting power, proposal lifecycle, and security thresholds.

02

Proposal Threshold

The minimum amount of governance token a user must hold to submit a proposal. This prevents spam while maintaining accessibility.

  • Setting it: Too low risks spam; too high centralizes proposal power.
  • Common approach: 0.5% to 2% of circulating supply or a fixed token amount (e.g., 50,000 UNI).
  • Dynamic thresholds: Some DAOs adjust this based on treasury size or past proposal volume.
03

Quorum Requirement

The minimum percentage of the total voting power that must participate for a vote to be valid. This ensures decisions reflect broad consensus.

  • Critical security parameter: Prevents a small, active group from controlling outcomes.
  • Calculation: Often a fixed percentage (e.g., 4% in Uniswap) of total token supply.
  • Adaptive quorums: Newer systems like Governor Bravo can adjust quorum based on proposal type or historical turnout.
05

Vote Weighting & Delegation

Defines how voting power is calculated and if it can be delegated. Snapshot voting (off-chain) often uses 1 token = 1 vote. On-chain systems may include:

  • Linear voting: Power proportional to token balance.
  • Quadratic voting: Power = sqrt(balance), reducing whale dominance.
  • Delegation: Allows token holders to delegate their voting power to representatives, as seen in Compound Governor Bravo.
06

Proposal Types & Thresholds

Different actions (e.g., spend treasury funds, upgrade contracts) should have different security levels. Implementing multiple proposal types allows for granular control.

  • Standard Proposal: Lower threshold for routine parameter updates.
  • Emergency Proposal: Higher threshold/quorum for critical security patches, with possible shorter timelock.
  • Example: Aragon DAOs can configure distinct voting settings for each installed app (Vault, Token Manager).
CONFIGURATION GUIDE

Governance Parameter Comparison and Recommendations

Comparison of common parameter settings for token-based governance systems, with recommendations based on community size and token distribution.

ParameterConservative (New DAO)Balanced (Established DAO)Aggressive (High-Activity DAO)

Proposal Submission Threshold

1.0% of total supply

0.5% of total supply

0.1% of total supply

Voting Delay

72 hours

48 hours

24 hours

Voting Period

7 days

5 days

3 days

Quorum Requirement

4% of total supply

2% of total supply

1% of total supply

Timelock Execution Delay

48 hours

24 hours

2 hours

Proposal Threshold for Treasury

0.5% of total supply

0.25% of total supply

0.1% of total supply

Emergency Proposal Voting Period

72 hours

48 hours

24 hours

Vote Delegation Allowed

implementation-steps
STEP-BY-STEP IMPLEMENTATION

Setting Up a Token Governance Proposal System

This guide details the technical implementation of a decentralized governance system using a token-based voting smart contract.

A token governance system typically involves three core smart contracts: a governance token (ERC-20 or ERC-20Votes), a governor contract (like OpenZeppelin's Governor), and a timelock controller. The token contract manages voting power, the governor contract handles proposal lifecycle logic, and the timelock enforces a delay between proposal execution and its effects, a critical security measure. For this implementation, we'll use Solidity and the OpenZeppelin Contracts library, which provides audited, modular components for building secure systems. Start by installing the library: npm install @openzeppelin/contracts.

First, deploy your voting token. If using a standard ERC-20, you must extend it with snapshot capabilities or use the ERC20Votes extension, which automatically snapshots balances on token transfers to prevent voting power manipulation. The constructor mints an initial supply to the deployer. After deployment, you must delegate voting power; holders must call delegate() on the token contract to activate their votes. For a DAO treasury, you would then transfer a portion of tokens to a community treasury contract.

Next, deploy the Governor contract. OpenZeppelin's Governor is abstract; you'll deploy a concrete instance like GovernorCountingSimple. Key parameters to set in the constructor are the token address, voting delay (blocks before voting starts), voting period (blocks voting is open), proposal threshold (minimum tokens to propose), and the quorum numerator (e.g., 4 for 4%). The quorum is calculated as a percentage of the total token supply at the block a proposal is created. The governor will use the token's getPastVotes function to check voting power.

The Timelock controller adds a security delay. Deploy a TimelockController with a minimum delay (e.g., 2 days). You must assign proposer and executor roles. Typically, the Governor contract is the sole proposer, and anyone (the zero address) can be an executor. After deployment, you must transfer ownership of any contracts the DAO will govern (like a Treasury) to the Timelock address. This ensures only proposals that pass governance and wait through the timelock can execute actions on these contracts.

Finally, connect the system. Update the Governor contract to use the Timelock as its executor. Proposals are created by calling propose() on the Governor with a list of target addresses, values, and calldata. After the voting delay, holders vote with castVote(). If the proposal succeeds and the timelock delay passes, anyone can call execute(). For frontend integration, use libraries like Tally or build a custom UI that interacts with the contract ABI, fetches proposal state, and connects user wallets via Ethers.js or Viem.

off-chain-tools
GOVERNANCE

Off-Chain Coordination and Tooling

Tools for managing community discussion, signaling, and proposal workflows before a vote is executed on-chain.

06

Security Best Practices

Critical considerations for designing a secure governance system to prevent exploits and voter apathy.

  • Parameter Tuning: Carefully set voting delay, voting period, and proposal threshold. A common threshold is 0.5-1% of supply.
  • Timelock Usage: All treasury actions should pass through a timelock (e.g., 2-7 days) to allow for community reaction.
  • Guardian Role: Implement a multisig or security council with limited powers (e.g., pausing) to act in emergencies, as seen in Aave and Compound.
security-considerations
SECURITY AND ATTACK VECTORS

Setting Up a Token Governance Proposal System

A secure on-chain governance system is critical for decentralized protocols. This guide covers the essential security considerations and common attack vectors when implementing a proposal system using token-based voting.

On-chain governance allows token holders to vote on protocol upgrades, treasury allocations, and parameter changes. The core components are a governance token for voting power, a timelock contract to queue and execute proposals, and the governor contract itself, which manages proposal lifecycle. Major implementations include OpenZeppelin's Governor contracts and Compound's Governor Bravo. A critical first step is defining the governance parameters: votingDelay (blocks before voting starts), votingPeriod (duration of the vote), and proposalThreshold (minimum tokens needed to submit). Setting these incorrectly can lead to voter apathy or proposal spam.

Several attack vectors can compromise a governance system. A 51% attack occurs if a single entity acquires majority voting power to pass malicious proposals. More subtle is vote buying, where attackers bribe voters off-chain to sway on-chain votes. Flash loan attacks are a significant risk; an attacker can borrow a massive amount of governance tokens, vote, and repay the loan within a single transaction, effectively voting with tokens they don't own. To mitigate this, implement vote snapshotting using a mechanism like ERC20Votes or ERC20Snapshot, which records token balances at a specific block number before the voting period begins.

The timelock contract is your primary defense mechanism. It imposes a mandatory delay between a proposal's approval and its execution. This gives the community time to review the calldata and, if malicious, execute a defensive proposal to cancel it before it runs. Always ensure the timelock is the owner of the core protocol contracts. A common mistake is granting the governor contract direct execution rights, which removes this safety net. The delay period (e.g., 2-3 days for major changes) must be long enough for community response but short enough for operational efficiency.

Proposal logic must be rigorously audited. A vulnerability in the propose(), queue(), or execute() functions can be catastrophic. Use established libraries like OpenZeppelin Governor as a foundation. For custom voting strategies, ensure they are gas-efficient and prevent reentrancy. Consider implementing quorum requirements—a minimum percentage of total token supply that must participate for a vote to be valid. Without quorum, a small, potentially malicious group could pass proposals with low turnout. Tools like Tally and Snapshot are often used for off-chain signaling to gauge sentiment before an on-chain proposal.

Continuous monitoring and incident response are essential. Set up alerts for large token transfers into voting contracts and monitor proposal submissions. Have a prepared process for emergency actions, such as pausing the governor contract via a multi-sig if a critical bug is discovered. Remember, governance security is iterative. Learn from past incidents like the Fei Protocol's governance attack where a flash loan was used to pass a proposal. Regular audits, bug bounties, and community education are the best defenses against evolving threats in decentralized governance.

TOKEN GOVERNANCE

Frequently Asked Questions

Common technical questions and solutions for developers building or interacting with on-chain governance systems.

A proposal is the formal submission of executable code or a parameter change to the governance contract. It is created by a proposer who has met a minimum token threshold. A vote is the subsequent process where token holders signal their approval or rejection of that proposal.

Key Technical Distinction:

  • Proposal State Machine: Proposals typically follow a lifecycle: Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, Executed. The Active state is the voting period.
  • Voting Power: Votes are weighted by the voter's token balance (often using a snapshot of a past block). Common patterns include token-weighted voting and delegation (e.g., Compound's Governor Bravo).
  • Execution: A successful vote does not automatically execute the proposal. A separate execute transaction must be called, often after a timelock delay for security.
conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have successfully built a foundational on-chain governance system. This guide covered the core components: a token contract, a timelock controller, and a governor contract.

Your deployed system now enables token holders to create proposals, delegate voting power, cast votes, and execute passed proposals after a mandatory delay via the timelock. The key contracts used were OpenZeppelin's ERC20Votes, Governor, and TimelockController, which provide battle-tested security patterns for managing upgrades and treasury operations. Remember that the governance parameters—like votingDelay, votingPeriod, and quorum—are set in the governor's constructor and dictate the proposal lifecycle. These should be carefully calibrated for your community's needs.

To extend this system, consider integrating with governance frontends like Tally or Boardroom, which provide user-friendly interfaces for proposal browsing and voting. For on-chain execution, you can use Safe{Wallet} as the Timelock's proposer and executor for enhanced multisig security. Explore advanced voting mechanisms such as vote delegation via ERC20Votes, gasless voting with EIP-712 signatures using OpenZeppelin's GovernorCountingSimple, or quadratic voting to mitigate whale dominance. Always verify contract interactions on a testnet like Sepolia before mainnet deployment.

The next critical phase is operational security and community onboarding. Establish clear documentation for proposal creation, outlining required formats and processes. Use a snapshot of token holders at a specific block for off-chain sentiment signaling before formal on-chain proposals. Monitor proposal execution and consider implementing a guardian or security council role within the Timelock for emergency actions. Continuously audit and, if necessary, upgrade your contracts via new governance proposals, ensuring the system evolves with your protocol's needs.

How to Set Up a Token Governance Proposal System | ChainScore Guides