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 Delegated Voting Framework

A technical guide for developers to implement a secure, gas-efficient delegated voting system using Solidity, covering delegation registry design, power calculation, and frontend integration.
Chainscore © 2026
introduction
GOVERNANCE

Introduction to Delegated Voting

Delegated voting is a foundational governance model that allows token holders to assign their voting power to representatives, enabling efficient and scalable decision-making in decentralized organizations.

Delegated voting, or liquid democracy, is a hybrid governance system that combines direct and representative democracy. In this model, token holders can either vote on proposals directly or delegate their voting power to a chosen representative, known as a delegate. This delegation is not permanent; it can be changed or revoked at any time, making the voting power "liquid." This system is used by major protocols like Uniswap, Compound, and Aave to manage treasury funds, upgrade smart contracts, and set key protocol parameters.

The primary advantage of delegated voting is scalability. In a large, global community, expecting every member to research and vote on every proposal is impractical. Delegation allows for specialization, where informed and active community members can represent the interests of passive holders. However, this introduces a principal-agent problem: delegates may not always act in their constituents' best interests. Effective frameworks mitigate this through delegate transparency, reputation systems, and the constant threat of vote withdrawal.

Setting up a basic delegated voting framework typically involves a vote-escrow token model. A user's voting power is proportional to the amount and duration they lock their governance tokens (e.g., veCRV for Curve Finance). This VotingEscrow smart contract issues a non-transferable NFT representing the lock, which then grants voting power. Delegation is implemented by allowing the NFT holder to point their voting power to another address. The core function for delegation is often as simple as delegate(address delegatee).

A critical technical component is the snapshot mechanism. To prevent last-minute manipulation, most systems use a snapshot of token balances or lock weights taken at a specific block number before a vote begins. This is calculated off-chain by platforms like Snapshot.org or on-chain via a contract call. When a user delegates, it affects all future snapshots until they change their delegate. The voting contract checks the snapshot to determine each address's voting power for a given proposal.

For developers, implementing delegation requires careful smart contract design. Key considerations include:

  • Gas efficiency: Optimizing state updates for frequent delegation changes.
  • Security: Ensuring delegated power cannot be used maliciously if a delegate's keys are compromised.
  • Transparency: Emitting clear events like DelegateChanged(indexed delegator, indexed fromDelegate, indexed toDelegate) for easy off-chain tracking. OpenZeppelin's ERC20Votes and ERC721Votes contracts provide standard, audited implementations of snapshot and delegation logic to build upon.

Successful delegated governance depends on more than just code. It requires active delegate communities, clear communication channels, and tools for voters to assess delegate platforms and voting history. Projects should integrate with delegate discovery platforms like Tally or Boardroom and consider implementing delegate incentives, such as a share of protocol fees, to encourage responsible participation and long-term alignment with the network's success.

prerequisites
DELEGATED VOTING FRAMEWORK

Prerequisites and Setup

This guide outlines the technical prerequisites and initial setup required to implement a delegated voting system using smart contracts.

A delegated voting framework allows token holders to delegate their voting power to representatives, enabling scalable governance for DAOs and decentralized protocols. The core system is built on three main smart contracts: a Voting Token (e.g., an ERC-20 or ERC-1155 with snapshot capabilities), a Governance contract that manages proposals and tallying logic, and a Delegation registry that tracks delegation relationships. Before writing any code, you must choose a development environment. We recommend using Hardhat or Foundry for local testing and deployment, as they provide robust tooling for Ethereum Virtual Machine (EVM) development.

You will need a basic understanding of Solidity for writing the contracts and JavaScript/TypeScript for writing tests and scripts. Essential dependencies include OpenZeppelin's contracts library (@openzeppelin/contracts), which provides secure, audited implementations for standards like ERC-20 and governance utilities. For the delegation logic, you can extend OpenZeppelin's Votes abstract contract (introduced in v4.5) or implement a custom snapshot mechanism using a checkpointing pattern to prevent double-voting. Ensure your Node.js version is 16.x or later and that you have a package manager like npm or yarn installed.

Begin by initializing your project. With Hardhat, run npx hardhat init and select the TypeScript template. Install OpenZeppelin contracts: npm install @openzeppelin/contracts. For Foundry, use forge init and then forge install openzeppelin/openzeppelin-contracts. The first contract to create is the voting token. Import @openzeppelin/contracts/token/ERC20/ERC20.sol and @openzeppelin/contracts/governance/utils/Votes.sol. Your token must inherit from both ERC20 and Votes, overriding the _afterTokenTransfer function to automatically update delegation checkpoints when tokens are moved.

Next, set up the delegation registry. The Votes extension provides a delegate function, but you may need a custom contract to manage more complex delegation rules, like tiered delegation or time-locks. A basic setup involves a mapping from delegator to delegatee and emitting events for transparency. The governance contract will query this registry to determine a voter's voting power at a specific block number (using snapshot). For testing, write unit tests that simulate token transfers, delegation calls, and proposal creation. Use hardhat-chai-matchers or Foundry's built-in testing to assert correct state changes.

Finally, configure your deployment script. You will need to deploy the token, delegation, and governance contracts in sequence, often passing the token address to the governance constructor. For a test deployment, you can use Hardhat's network to a local node or a testnet like Sepolia. Remember to verify your contracts on a block explorer after deployment using plugins like @nomiclabs/hardhat-etherscan. This foundational setup creates a secure and upgradeable base for your delegated voting application, ready for integrating front-end interfaces and more advanced features like timelocks and multi-signature execution.

core-architecture
CORE SYSTEM ARCHITECTURE

Setting Up a Delegated Voting Framework

A delegated voting framework allows token holders to delegate their voting power to representatives, enabling efficient governance in DAOs and on-chain protocols. This guide covers the core architecture and implementation steps.

Delegated voting is a foundational governance mechanism used by protocols like Compound and Uniswap. Instead of requiring every token holder to vote on each proposal, users can delegate their voting power to a trusted representative or delegate. This system improves participation rates and decision-making efficiency by consolidating voting power into fewer, more active addresses. The core contract architecture typically involves a governance token (e.g., an ERC-20 with voting extensions) and a separate governor contract that manages proposals and tallies votes based on delegated balances.

The first step in implementation is designing the delegation logic. For an ERC-20 token, this often means implementing the ERC20Votes extension from OpenZeppelin, which maintains a history of checkpoints for each account's voting power. When a user delegates, either to themselves or another address, the contract records a snapshot of their balance. The key function is delegate(address delegatee), which updates the delegatee for the caller. It's crucial to ensure delegation is gas-efficient and that historical data is accessible for past votes, which is managed through checkpoint arrays.

Next, you must integrate the token with a governor contract. The Governor contract from OpenZeppelin, such as GovernorCompatibilityBravo, is a common starting point. It will call the token's getVotes(address account, uint256 blockNumber) function to determine voting power at the proposal's snapshot block. The proposal lifecycle—create, vote, queue, execute—is managed here. Security considerations include setting appropriate proposal thresholds, voting delays, and quorum requirements to prevent spam and ensure legitimate governance outcomes.

A critical architectural decision is choosing between gasless (signature-based) delegation and transaction-based delegation. For better UX, you can implement EIP-712 signed delegations, allowing users to approve a delegation without paying gas until it's executed by a relayer. This is similar to how Snapshot handles off-chain signaling. However, for on-chain execution, the final state change must be a transaction. Testing the entire flow with a framework like Hardhat or Foundry is essential to verify vote tallying and delegation updates work correctly across blocks.

Finally, consider real-world parameters and upgrades. For example, Uniswap's governance uses a timelock controller to delay executed proposals, adding a security layer. The delegation system should also be compatible with governance treasuries and cross-chain governance solutions if needed. Always audit the contract interactions, especially the functions that transfer voting power, to prevent vulnerabilities like double-voting or manipulation of historical snapshots.

key-concepts
DELEGATED VOTING

Key Concepts for Implementation

A delegated voting framework separates governance participation from token ownership. This guide covers the core technical components required to build a secure and efficient system.

03

Proposal Lifecycle & State Machine

A proposal moves through a defined sequence of states (e.g., Pending, Active, Succeeded, Queued, Executed). The contract must enforce timing and quorum rules at each transition.

  • Typical States: Pending -> Active (voting period) -> Succeeded/Defeated -> Queued (timelock) -> Executed.
  • Critical Parameters: votingDelay (blocks before voting starts), votingPeriod (duration), quorumVotes (minimum participation required).
  • Execution: Successful proposals often route through a Timelock contract, which enforces a mandatory delay before the governing action is performed.
04

Vote Casting & Tallying

The mechanism by which delegates submit their vote and the system calculates the final result.

  • Vote Types: Common patterns are For/Against or For/Against/Abstain. More complex systems may use weighted or ranked-choice voting.
  • Gas Optimization: Use signature-based voting (EIP-712) to allow delegates to vote off-chain and submit a signed message, drastically reducing gas costs.
  • Tallying: The contract must correctly sum votes, respecting the snapshot weights and delegation mappings. Results should be immutable and publicly verifiable on-chain.
06

Quorum & Threshold Calculations

These parameters define the minimum participation and support needed for a proposal to pass, protecting against low-turnout attacks.

  • Quorum: The minimum percentage of total voting power that must participate (vote For, Against, or Abstain) for the vote to be valid. Can be a fixed number or dynamic based on past turnout.
  • Threshold: The percentage of participating votes that must be For for the proposal to succeed (e.g., >50% simple majority, or 66.6% super-majority).
  • Design Choice: A high quorum ensures broad consensus but can lead to governance stagnation. Dynamic quorums (like OZ's GovernorVotesQuorumFraction) adjust based on total token supply.
contract-implementation
SMART CONTRACT IMPLEMENTATION

Setting Up a Delegated Voting Framework

A step-by-step guide to building a gas-efficient, secure delegated voting system on EVM-compatible blockchains using Solidity.

A delegated voting framework, often used in DAO governance, allows token holders to delegate their voting power to representatives. This system improves participation by letting less active members trust experts to vote on their behalf. The core contract must manage three primary states: the list of proposals, the tally of votes for each, and a registry of delegations linking delegates to their delegators. Implementing this requires careful consideration of gas costs, vote finality, and security against double-voting or manipulation.

The contract structure typically includes a mapping for delegations (address delegate => address delegator), an array of Proposal structs, and a record of votes cast. A critical function is delegate(address to), which allows a user to assign their voting power. This function must check for delegation loops (e.g., A delegates to B, B delegates to A) to prevent locked states and update the voting power of the previous and new delegates. Using the OpenZeppelin Governor contracts as a foundation can save development time and audit scrutiny.

Vote casting must account for delegated power. Instead of a simple vote(uint proposalId), the function should be castVote(uint proposalId, uint8 support). The contract logic sums the voter's own token balance plus the balance of all addresses that have delegated to them. To optimize gas, store a snapshot of balances at the proposal creation block using a pattern like ERC20Votes or OpenZeppelin's GovernorVotes extension. This prevents manipulation by transferring tokens after a proposal is live.

Security is paramount. Implement checks in the vote function to ensure: a proposal is active, the voter has not already voted, and the delegate's voting power is correctly calculated. Use the Checks-Effects-Interactions pattern and consider adding a timelock for executing passed proposals. For on-chain execution, the contract should include an executeProposal function that can only be called after the voting period ends and the proposal meets quorum and majority thresholds.

Testing the contract thoroughly is essential. Write unit tests (using Foundry or Hardhat) for edge cases: self-delegation, transferring tokens after delegation, revoking delegation mid-vote, and proposal execution failure. A complete framework also needs a front-end to interact with the contract, displaying proposals, delegation status, and facilitating vote casting. This guide provides the foundational smart contract logic; integrating with a standard like GovernorCompatibilityBravo can ensure compatibility with existing DAO tooling like Tally and Snapshot.

FRAMEWORK ARCHITECTURE

Delegation Strategy Comparison

A comparison of common delegation models for on-chain governance, detailing their technical implementation, security trade-offs, and operational complexity.

Feature / MetricDirect DelegationDelegation PoolSmart Contract Proxy

Implementation Complexity

Low

Medium

High

Voter Sovereignty

High

Medium

Low

Gas Cost per Vote

User pays

Pool pays

Proxy pays

Slashing Risk

Delegator

Pool members

Proxy contract

Revocation Latency

< 1 block

1-12 hours

Requires upgrade

Typical Use Case

Small DAOs, trusted delegates

Liquid staking protocols

Enterprise or institutional voters

Example Protocol

Compound Governance

Lido on Ethereum

Aave Arc

frontend-integration
FRONTEND AND INTERFACE INTEGRATION

Setting Up a Delegated Voting Framework

A technical guide to building a frontend for a delegated voting system, connecting user interfaces to on-chain governance smart contracts.

A delegated voting framework allows token holders to delegate their voting power to representatives, a core mechanism in protocols like Compound and Uniswap. The frontend's primary role is to facilitate this delegation process and enable delegates to cast votes on proposals. This requires integrating with two main smart contract functions: delegate(address delegatee) to assign voting power and castVote(uint256 proposalId, uint8 support) to execute a vote. The interface must clearly display delegate performance metrics, active proposals, and the user's current delegation status to inform decision-making.

To begin, you need to connect your dApp to the governance contract using a library like Ethers.js or Viem. First, instantiate a provider and the contract ABI. For example, using Ethers: const contract = new ethers.Contract(contractAddress, governanceABI, signer);. The frontend must then fetch critical on-chain data: the user's token balance, their current delegate, a list of top delegates (often queried via subgraph or custom indexer), and all active proposals with their proposalId, description, and voting status. This data forms the foundation of the user interface.

The delegation interface should allow users to easily assign their voting power. Implement a function that calls contract.delegate(delegateAddress) when a user selects a delegate. It's crucial to calculate and display the voting power impact—show how many votes the delegate will gain. Always request transaction confirmation and handle revert cases, such as trying to delegate to the zero address. For a better UX, consider integrating delegate profiles with on-chain reputation metrics like prior proposal participation and voting history, which can be sourced from a subgraph.

For the voting interface, each proposal needs a clear summary and voting buttons (For, Against, Abstain). When a user votes, the frontend calls contract.castVote(proposalId, supportEnum). Remember, the support parameter is typically an integer (1=For, 2=Against, 3=Abstain). The UI must prevent voting on inactive proposals and should update the proposal's tally in real-time after a successful transaction. Using React state or a similar framework is essential to reflect these changes immediately without requiring a page refresh.

State management is critical for a seamless experience. Use a context provider or state management library to store global data like the connected wallet address, token balance, and delegation info. This prevents prop-drilling and ensures the UI updates consistently after on-chain interactions. Implement transaction toast notifications to inform users of pending, successful, or failed transactions. For advanced features, consider integrating Snapshot-style off-chain voting signatures for gasless voting, or adding delegate communication channels via platforms like Discourse or Commonwealth.

Finally, thorough testing and security are paramount. Test all contract interactions on a testnet like Sepolia or Goerli. Use the WalletConnect or MetaMask SDK for robust wallet connection. Audit your frontend for common vulnerabilities: never store private keys, validate all contract inputs, and sanitize proposal data fetched from IPFS to prevent XSS attacks. A well-built delegated voting frontend not only executes transactions but also educates and empowers the community, turning governance participation from a chore into an intuitive and informed action.

security-considerations
DELEGATED VOTING

Security and Gas Optimization

Implementing a delegated voting framework requires careful consideration of security models and gas efficiency to ensure protocol sustainability and user adoption.

03

Gas Cost Analysis for Voting

Understanding and minimizing the gas costs of key voting operations is critical for user adoption.

  • Proposal creation: The most expensive operation, often costing 500k-1M+ gas. Costs scale with proposal calldata size.
  • Casting a vote: ~50k-100k gas for on-chain voting. Using EIP-712 signatures can reduce this to ~25k gas for the relayer.
  • Delegating votes: ~50k gas to update a delegation, which writes a new checkpoint.

Optimize by batching operations and encouraging off-chain signature voting.

06

Voting Strategy & Quorum

Choosing the right voting strategy and quorum threshold balances security with governance participation.

  • Vote Types: Majority, approval voting, or quadratic voting (ERC-5806).
  • Quorum: The minimum voting power required for a proposal to pass. A dynamic quorum (based on past turnout) can be more resilient than a fixed percentage.
  • Security vs. Liveness: A high quorum (e.g., 4% of supply) increases security but risks governance deadlock. A low quorum (1%) is easier to pass but more vulnerable to attacks.

Analyze token distribution to set appropriate parameters.

DELEGATED VOTING

Frequently Asked Questions

Common technical questions and troubleshooting for implementing a delegated voting framework on-chain.

A delegated voting framework is a governance model where token holders delegate their voting power to representatives, known as delegates or validators, who vote on proposals on their behalf. On-chain, this is implemented using smart contracts that track delegation mappings and tally votes.

Core Mechanics:

  1. Delegation: A token holder calls a delegate(address to) function, linking their voting weight to the delegate's address.
  2. Vote Casting: Delegates submit votes on proposals. The contract calculates their voting power as the sum of tokens delegated to them.
  3. Tallying: The contract aggregates votes, applying each delegate's voting power to their chosen option (For, Against, Abstain).

Popular implementations include Compound's Governor Bravo and OpenZeppelin's Governor contracts, which provide modular, audited bases for building custom systems.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have successfully configured a delegated voting framework, from smart contract deployment to frontend integration. This guide covered the essential steps to build a functional governance system.

Your new framework enables token holders to delegate voting power, submit proposals, and cast votes on-chain. The core components—the governance token contract, the governor contract, and the timelock controller—are now deployed and interacting. You have also set up a basic frontend using a library like Tally or Snapshot to provide a user-friendly interface for delegation and voting. The system's parameters, such as the voting delay, voting period, and proposal threshold, are configured to match your project's needs.

To ensure the system's security and effectiveness, your next steps should involve rigorous testing and community onboarding. Conduct thorough audits on the smart contracts, focusing on edge cases in the voting and delegation logic. Use a testnet to simulate governance proposals and delegation campaigns with a small group of users. This process will help identify any parameter adjustments needed, like the quorum percentage or the timelock delay, before launching on mainnet. Document the governance process clearly for your community.

For advanced functionality, consider integrating with existing tooling. Platforms like OpenZeppelin Defender can automate proposal execution and monitoring via its Admin module. You can also explore integrating Safe{Wallet} as the treasury's executor for enhanced multi-signature security. To increase voter participation, look into sybil-resistant delegation strategies or integrating with Snapshot for off-chain signaling that can inform on-chain execution.

Maintaining and evolving the framework is an ongoing process. Establish clear channels for governance communication, such as a forum or Discord channel dedicated to proposals. Monitor key metrics like voter turnout and delegation distribution. Be prepared to upgrade the system via the governance process itself—this is the ultimate test of a decentralized framework. The code and concepts from this guide, built on standards like OpenZeppelin Governor, provide a robust foundation for your project's decentralized future.

How to Build a Delegated Voting System for DAOs | ChainScore Guides