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 Token-Voting for Community Feature Proposals

A technical guide for developers implementing token-based voting systems to manage community feature proposals, covering on-chain contracts, Snapshot strategies, and execution workflows.
Chainscore © 2026
introduction
GOVERNANCE IMPLEMENTATION

Setting Up Token-Voting for Community Feature Proposals

A technical guide to implementing a secure, on-chain token-voting system for managing protocol upgrades and feature requests.

Token-voting systems are the cornerstone of decentralized governance, allowing communities to collectively decide on protocol changes, treasury allocations, and feature roadmaps. Unlike simple signaling, on-chain voting executes proposals automatically via smart contracts when a quorum and majority are met. This guide focuses on setting up a system for community feature proposals, where token holders vote on new functionalities like adding a lending market or adjusting fee parameters. We'll use a Solidity-based, upgradeable Governor contract as our reference implementation, compatible with OpenZeppelin's Governor framework.

The core architecture involves three key contracts: the Governance Token (ERC-20Votes or ERC-5805), the Governor Contract, and a TimelockController. The token must implement vote delegation and snapshotting (like ERC20Votes). The Governor contract (e.g., GovernorCountingSimple) defines the voting rules: votingDelay (blocks before voting starts), votingPeriod (blocks voting is open), and proposalThreshold (minimum tokens needed to propose). The Timelock queues and executes successful proposals after a delay, providing a safety mechanism for review. For a feature proposal, the target is typically the protocol's core contract, with calldata for the upgrade function.

To propose a feature, a community member calls propose() on the Governor contract with an array of target addresses, values, and calldata. For example, to propose adding USDC as a new collateral asset to a lending protocol, the calldata would encode a call to addMarket(address(USDC), 75_00) setting a 75% loan-to-value ratio. The proposal is then subject to the votingDelay. During the votingPeriod, token holders cast votes by calling castVote(proposalId, support), where support is 0 (against), 1 (for), or 2 (abstain). Voting weight is typically calculated from a snapshot of token balances at the proposal's creation block.

A proposal succeeds if it meets two conditions by the end of the voting period: it achieves a quorum (a minimum percentage of the total token supply voting) and a simple majority of for votes over against. The specific logic is defined in the Governor's counting module. If successful, the proposal moves to the TimelockController queue. After the timelock delay (e.g., 2 days), anyone can call execute() to run the proposal's transactions. This delay allows the community a final window to react if a malicious proposal slips through. Failed proposals simply expire.

Critical security considerations include setting appropriate parameters: a high proposalThreshold prevents spam, a sufficient votingPeriod (e.g., 3-7 days) ensures broad participation, and a meaningful timelock delay allows for emergency responses. Use OpenZeppelin's audited contracts as a foundation. For voter engagement, integrate with front-end tools like Tally or Snapshot (for off-chain signaling with on-chain execution). Always test governance upgrades on a testnet with a forked mainnet state to simulate real token distribution and voting behavior before a mainnet deployment.

prerequisites
TOKEN-VOTING DAO

Prerequisites and System Design

This guide outlines the technical foundation and architectural decisions required to implement a secure and functional token-voting system for on-chain governance.

Before deploying a token-voting system, you must establish the core components. The primary prerequisite is a governance token with a defined distribution, typically an ERC-20 or ERC-1155 standard. This token must be non-transferable during active voting periods to prevent vote-buying attacks, a feature often implemented via a timelock or snapshot mechanism. You will also need a development environment like Hardhat or Foundry, a wallet with test ETH, and familiarity with a smart contract framework such as OpenZeppelin's Governor contracts, which provide a battle-tested foundation for proposal lifecycle management.

The system design centers on a modular architecture separating concerns for security and upgradeability. A standard stack includes: a Governor contract (e.g., GovernorCompatibilityBravo) that manages proposal creation, voting, and execution; a Voting Token contract that determines voting power; and an optional TimelockController (like OpenZeppelin's) to queue and delay executed transactions, providing a safety review period. This separation allows the voting token logic to be upgraded independently of the core governance rules. Key design parameters you must decide include the voting delay (time between proposal submission and voting start), voting period (duration of the vote), and proposal threshold (minimum token balance to submit a proposal).

For on-chain execution, proposals are structured as arrays of calldata targeting specific smart contract functions. For example, a proposal to update a protocol fee might contain a single transaction calling setFee(uint256) on the treasury contract. The Governor contract uses a quorum requirement—a minimum percentage of total token supply that must participate for a vote to be valid—to prevent low-turnout decisions. After a successful vote, the proposal actions are executed directly on-chain, often via the Timelock after a delay. This design ensures transparency and enforces that code is law, but requires careful parameter tuning to balance efficiency with security against governance attacks.

Off-chain components like Snapshot are commonly integrated for gas-free, sentiment-checking votes on complex or non-urgent topics. In a hybrid model, a Snapshot vote can inform an on-chain execution proposal. The system must also integrate with front-end tooling; libraries like Tally or Boardroom provide user interfaces for proposal browsing and voting. When designing, consider gas optimization for voters—strategies like vote delegation (ERC-20Votes) allow users to delegate their voting power to a representative, reducing the number of transactions needed during the voting period and increasing participation.

key-concepts
TOKEN-VOTING IMPLEMENTATION

Core Governance Components

Essential tools and smart contract standards for launching a community-driven governance system.

05

Setting Voting Parameters

Critical governance parameters must be configured for security and effectiveness. Poor settings can lead to voter apathy or governance attacks.

Key parameters:

  • Quorum: Minimum voting power required for a proposal to pass (e.g., 4% of total supply).
  • Voting delay: Time between proposal submission and voting start (e.g., 1 day).
  • Voting period: Duration votes can be cast (e.g., 3-7 days).
  • Proposal threshold: Minimum token balance needed to submit a proposal.
06

Security & Audit Considerations

Governance contracts control treasury funds and protocol parameters, making them high-value targets.

Essential security steps:

  • Professional audits: Engage firms like OpenZeppelin, Trail of Bits, or Quantstamp.
  • Timelock controllers: Introduce a delay between vote passage and execution to allow for review.
  • Guardian/pause roles: Emergency mechanisms for critical vulnerabilities.
  • Bug bounties: Programs on platforms like Immunefi to crowd-source security review.

The 2022 Nomad bridge hack exploited a governance proposal, underscoring the stakes.

proposal-standards
GOVERNANCE FOUNDATION

Step 1: Defining Proposal Standards

The first step in implementing token-voting is to define the formal standards that govern how proposals are created, structured, and processed. This creates a predictable and secure framework for community decision-making.

A proposal standard is a smart contract interface that defines the required data structure and lifecycle functions for a governance proposal. The most common standard is the EIP-4824: DAOs proposal interface, which establishes a common JSON schema for proposal metadata. Adopting a standard like this ensures interoperability with existing tooling, such as Tally or Snapshot, and provides a clear blueprint for developers. Your standard should specify the proposal's core attributes: a unique id, a title, a link to the full description (often an IPFS hash), the proposer's address, and the current status (e.g., Pending, Active, Executed).

For a feature proposal system, you must extend the base standard with domain-specific fields. Essential additions include: specification (a technical document or PRD), implementationAddress (the contract where the feature will live), testResults (a link to audit reports or test suite outputs), and fundingRequired (the amount of treasury tokens needed for development). Structuring this data in a predictable format allows both human voters and automated scripts to parse and evaluate proposals consistently. This reduces ambiguity and sets clear expectations for what constitutes a complete submission.

The standard must also define the proposal's lifecycle, which is managed by the governance contract. Key state transitions are: propose() to create a draft, queue() after a successful vote, and execute() to run the proposal's on-chain logic. For feature proposals, the execute function typically calls a TimelockController to schedule the transaction that upgrades the protocol or interacts with the implementationAddress. Defining these states and the rules for moving between them—such as required vote thresholds and timelock delays—is critical for security and operational clarity.

Finally, publish your proposal standard as a formal document, such as a Protocol Improvement Proposal (PIP) on your project's governance forum. Reference real-world examples, like Uniswap's governance process or Compound's Proposal schema. This transparent documentation serves as the single source of truth for your community, enabling developers to build compliant interfaces and ensuring all participants understand the rules of engagement before a single line of voting contract code is written.

ARCHITECTURE DECISION

Step 2: Voting Implementation (On-Chain vs. Off-Chain)

How On-Chain Voting Works

On-chain voting executes the entire governance process—proposal submission, voting, and execution—directly on the blockchain using smart contracts. Votes are cast by sending transactions, and the results are immutably recorded on-chain.

Key Characteristics:

  • Transparency & Immutability: Every vote is a public, verifiable transaction.
  • Automatic Execution: Proposals can include executable code that runs automatically if the vote passes (e.g., transferring treasury funds).
  • Gas Costs: Voters pay transaction fees (gas) to cast their vote, which can be a barrier.
  • Voting Weight: Typically based on token balance at a specific block (snapshot).

Best For:

  • High-stakes decisions requiring automatic execution (treasury payouts, parameter changes).
  • DAOs where maximum transparency and censorship-resistance are critical.
  • Smaller, highly engaged communities where gas costs are less prohibitive.

Example Protocols: Compound Governance, Uniswap Governance.

vote-delegation
GOVERNANCE SETUP

Step 3: Implementing Vote Delegation

This guide explains how to implement a token-weighted delegation system, allowing community members to delegate their voting power for feature proposals.

Vote delegation is a core mechanism for scaling governance participation. It allows token holders who are less active or lack technical expertise to delegate their voting power to a trusted representative, or delegatee. This system is used by protocols like Compound and Uniswap to ensure proposals are decided by engaged participants while maintaining broad token-based legitimacy. Implementing it requires modifying your governance smart contract to track delegation relationships and calculate voting power based on a user's own tokens plus those delegated to them.

The standard implementation involves a mapping in your governance contract, such as mapping(address => address) public delegates;. When a user calls a delegate(address to) function, their delegatee is recorded. The contract's getVotes(address account) function must then traverse this mapping: it sums the balance of the account and the balances of all addresses who have delegated to that account. Critical checks include preventing delegation loops (A delegates to B, B delegates to A) and ensuring delegated votes are snapshotted at the proposal creation block to prevent manipulation.

Here is a simplified Solidity snippet for the core delegation logic:

solidity
contract TokenVoting {
    mapping(address => uint256) public balances;
    mapping(address => address) public delegates;

    function delegate(address delegatee) public {
        require(delegatee != msg.sender, "Self-delegation is automatic.");
        require(delegatee != address(0), "Cannot delegate to zero address.");
        // Check for delegation loops (simplified check)
        address currentDelegate = delegates[msg.sender];
        require(currentDelegate != delegatee, "Already delegated to this address.");

        delegates[msg.sender] = delegatee;
        emit DelegateChanged(msg.sender, currentDelegate, delegatee);
    }

    function getVotes(address account) public view returns (uint256) {
        uint256 votes = balances[account];
        // Inefficient for production; use a checkpointing system for scalability.
        for(uint256 i = 0; i < allAddresses.length; i++) {
            if(delegates[allAddresses[i]] == account) {
                votes += balances[allAddresses[i]];
            }
        }
        return votes;
    }
}

For production, use a checkpointing system like OpenZeppelin's ERC20Votes to efficiently track historical balances.

After deploying the contract, the frontend must allow users to connect their wallet, see their current delegate, and initiate a new delegation transaction. A common pattern is to show a searchable list of prominent community members or allow input of any Ethereum address. It's crucial to inform users that delegation is not a transfer of tokens; it only assigns voting power and can be changed by the delegator at any time. The state change is recorded on-chain, making the delegation relationship transparent and verifiable.

To complete the setup, integrate this delegation system with your proposal lifecycle. When a user creates or votes on a proposal, the contract should call getVotes(sender) to determine their voting weight. Best practices include adding events like DelegateChanged and DelegateVotesChanged for off-chain indexing and providing a read-only function for delegates to see the total voting power they currently represent. This creates a functional, transparent foundation for community-led decision-making on feature proposals.

proposal-execution
IMPLEMENTATION

Step 4: Executing Approved Proposals

After a community proposal passes, the final step is on-chain execution. This guide details how to trigger the approved action using the DAO's treasury and smart contracts.

A successful on-chain vote grants the proposal contract the explicit permission to execute its encoded logic. This execution is typically a single transaction that interacts with the DAO's treasury or other smart contracts. For a feature proposal, this often means calling a function on a protocol's admin contract, such as upgradeTo(address newImplementation) for a proxy upgrade or setFee(uint256 newFee) for a parameter change. The execution call is permissioned, meaning only the proposal contract itself can make it, and only after the voting period has concluded with a passing result.

To execute, you need the proposal's unique ID and the encoded calldata for the target action. Most DAO frameworks like OpenZeppelin Governor, Aragon OSx, or DAOstack provide a standard execute function. For example, using OpenZeppelin's Governor contract, you would call Governor.execute(proposalId). This function will internally validate the proposal's state (e.g., Succeeded), and then use the call opcode to forward the proposal's calldata to the target address, spending the DAO's funds if the proposal includes a treasury transfer.

Execution can fail for several reasons, requiring careful pre-execution checks. Common failures include: the proposal state not being Succeeded, insufficient gas for the target transaction, a revert in the target contract's logic, or the target contract's state having changed since the proposal was created (a front-running risk). It is a best practice to simulate the execution via callStatic or estimateGas in a development environment before broadcasting the final transaction to the mainnet.

For a concrete example, imagine a passed proposal to set a new stakingReward rate of 15% on a protocol's staking contract. The execution transaction would call Governor.execute(proposalId), which internally calls StakingContract.setRewardRate(1500) (where 1500 represents 15.00%). This single on-chain action finalizes the community's decision, updating the protocol's parameters directly from the decentralized treasury without requiring a centralized admin key.

After successful execution, the proposal state changes to Executed, and the changes are live on-chain. The transaction hash serves as the immutable proof of execution. DAO tools like Tally, Boardroom, or the protocol's own frontend should reflect this updated state, providing transparency and closing the governance loop for that proposal. Failed executions should be analyzed, and the proposal may need to be re-submitted if the core issue (like a parameter miscalculation) is addressable.

TOKEN-VOTING IMPLEMENTATION

Governance Framework Comparison

A comparison of popular frameworks for implementing on-chain token-weighted voting.

Feature / MetricOpenZeppelin GovernorCompound Governor BravoAragon OSx

Core Architecture

Modular contracts (Governor, Timelock, Votes)

Monolithic contract with extensions

Plugin-based DAO framework

Voting Token Standard

ERC-20Votes, ERC-5805, ERC-6372

ERC-20 with checkpointing

ERC-20, native token, NFT (via plugins)

Proposal Lifecycle

Created → Active → Succeeded/Defeated → Queued → Executed

Created → Active → Canceled/Succeeded/Queued/Executed

Created → Active → Approved/Rejected → Executed

Voting Period (default)

1-2 weeks (configurable)

~3 days (configurable)

Fully configurable

Voting Delay (default)

1 block (configurable)

1 block (configurable)

Fully configurable

Quorum Mechanism

Fixed number, percentage of supply, linear/absolute

Percentage of supply

Configurable (absolute, relative, linear)

Gas Cost for Proposal Creation

~500k - 1M gas

~700k - 1.2M gas

~1.5M - 2.5M gas (includes DAO deployment)

Time-lock Support

Upgradeability Pattern

Transparent Proxy (UUPS recommended)

Not upgradeable by default

Plugin-based, DAO can upgrade plugins

Formal Verification

Multi-chain Deployment

TOKEN-VOTING SETUP

Frequently Asked Questions

Common technical questions and solutions for implementing and troubleshooting on-chain token-voting for community governance proposals.

A simple token-voting contract is a basic implementation where token holders directly vote on proposals, often using a single function like vote(uint proposalId, bool support). This is suitable for simple yes/no decisions.

A Governor contract, like OpenZeppelin's Governor, is a modular, upgradeable standard (EIP-5805) that separates proposal lifecycle management from voting logic. It uses a TimelockController for execution delay, supports vote delegation via ERC20Votes, and includes modules for vote counting (e.g., GovernorCountingSimple) and quorum management. For production systems requiring complex proposal logic, security, and gas efficiency, a Governor standard is recommended. Simple contracts are prone to reentrancy and lack standardized interfaces for tooling integration.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have successfully configured a token-voting system for community governance. This guide covered the core setup, but governance is an ongoing process.

Your token-voting system is now a functional on-chain mechanism for decentralized decision-making. The core components—a Governor contract (like OpenZeppelin's), a Votes-compatible token (e.g., ERC20Votes or ERC721Votes), and a TimelockController—are deployed and integrated. Proposals can be created, voted on by token holders based on their delegated voting power, and executed after a successful vote and timelock delay. This structure ensures that protocol upgrades and treasury allocations reflect the will of the token-holding community.

To move from a basic setup to a robust governance framework, consider these next steps. First, establish clear governance parameters in your Governor contract: the proposal threshold (minimum tokens to propose), voting delay and period durations, and quorum requirements. These should balance accessibility with security. Second, create off-chain infrastructure: a front-end interface (using a library like Tally or Boardroom) for proposal browsing and voting, and a dedicated forum (e.g., Discourse or Commonwealth) for pre-proposal discussion and temperature checks. This prevents governance spam and fosters informed debate.

Finally, proactive community management is critical for long-term health. Develop and publish transparent governance documentation outlining proposal lifecycle, delegate responsibilities, and conflict resolution. Consider implementing a grants program or a small working group empowered by the treasury to execute on approved proposals. Monitor participation rates and be prepared to adjust parameters via governance itself. For further learning, review successful implementations like Compound Governance or Uniswap Governance, and consult the OpenZeppelin Governor documentation for advanced customization options.

How to Set Up Token-Voting for Feature Proposals | ChainScore Guides