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

How to Implement a Quadratic Voting System

This guide provides a technical walkthrough for implementing quadratic voting, a mechanism that reduces whale dominance by making vote costs scale quadratically. It covers the core algorithm, Sybil resistance strategies, and practical Solidity examples.
Chainscore © 2026
introduction
DEVELOPER TUTORIAL

How to Implement a Quadratic Voting System

A step-by-step guide to building a secure and efficient quadratic voting mechanism using smart contracts.

Quadratic voting (QV) is a collective decision-making mechanism where participants allocate a budget of voice credits to express the intensity of their preferences. The cost to cast n votes for a single proposal is n² credits. This quadratic cost structure makes it exponentially more expensive to concentrate votes, protecting against Sybil attacks and whale dominance by ensuring one entity with 10x the credits only gets √10 (≈3.16) times the voting power. It's used in Gitcoin Grants for public goods funding and by Radicle for decentralized governance.

To implement QV, you first need a system to distribute and track voice credits. A common approach is to assign each eligible voter a fixed budget (e.g., 99 credits) at the start of a voting round. The core smart contract function calculates the cost of a vote. For a user casting votesForProposal votes, the required credits are votesForProposal ** 2. You must check the user has sufficient remaining credits before deducting the cost and updating the proposal's tally. Always use a pull-over-push pattern for state updates to prevent reentrancy attacks.

A critical implementation detail is preventing double-signature attacks where a user could vote multiple times by splitting credits across different keys. Mitigate this by using a commit-reveal scheme or a nullifier mechanism, like those in semaphore-style zero-knowledge proofs, to ensure one-person-one-identity. For on-chain voting, consider using an ERC-20 token for credits or a merkle tree for off-chain credit allocation with on-chain verification to save gas. Store vote counts as int256 to allow for both positive (support) and negative (oppose) quadratic voting.

Here is a simplified Solidity code snippet for the core voting logic, excluding security modifiers and identity verification:

solidity
function castVote(uint256 proposalId, int256 votes) external {
    uint256 cost = uint256(votes * votes); // votes² cost
    require(credits[msg.sender] >= cost, "Insufficient credits");
    credits[msg.sender] -= cost;
    proposalVotes[proposalId] += votes;
}

This function assumes credits tracks a user's balance and votes can be positive or negative. In production, you must add checks for vote limits and use OpenZeppelin's SafeCast library.

After the voting period ends, you need a tallying mechanism. The winning proposal is the one with the highest sum of vote weights. For funding allocation, like in Gitcoin, you can use the quadratic funding formula to match contributions, which amplifies projects with broad, small support. Always verify the final results on-chain and consider emitting events for each vote to allow off-chain indexers and frontends to track the process in real-time without expensive on-chain queries.

Key considerations for a production system include: gas optimization using batch processing or Layer 2 solutions like Arbitrum; upgradeability via a proxy pattern for formula adjustments; and transparency through a verifiable audit trail. Test extensively with scenarios like coordinated vote buying and edge cases in credit calculation. For further reading, review Vitalik Buterin's blog post on liberal radicalism and the CLR.fund and Gitcoin's source code for real-world implementations.

prerequisites
TECHNICAL FOUNDATIONS

Prerequisites

Before building a quadratic voting system, you need a solid grasp of the underlying technologies and design principles.

Implementing a quadratic voting (QV) system requires a specific technical foundation. You must be proficient in smart contract development using Solidity (for Ethereum) or a similar language for your target chain. A strong understanding of cryptographic primitives is essential, particularly digital signatures for authentication and zero-knowledge proofs if you plan to implement privacy features. Familiarity with decentralized identity (DID) standards like Verifiable Credentials or off-chain attestation services (e.g., Worldcoin, Gitcoin Passport) is also crucial for managing unique voter identity and preventing Sybil attacks.

Your development environment must be configured for blockchain interaction. This includes using a framework like Hardhat or Foundry for local testing and deployment, and a library such as ethers.js or viem for frontend integration. You will need access to a testnet (like Sepolia or Goerli) and test ETH/other tokens to deploy and interact with your contracts. Understanding gas optimization is critical, as QV calculations can be computationally expensive on-chain; you may need to implement batch processing or commit-reveal schemes to manage costs.

The core logic of QV involves calculating the square root of the total credits a voter allocates to each option. In Solidity, this requires a reliable square root function. Since the native sqrt function in Solidity 0.8.x only works for unsigned integers, you must implement or import a library (like OpenZeppelin's Math library) that can handle the necessary precision. You'll also need a secure mechanism for tracking and spending voting credits, typically implemented as an ERC-20 style internal accounting system or a non-transferable soulbound token (SBT).

Data storage design is a key architectural decision. You must decide what is stored on-chain versus off-chain. Storing vote commitments, final results, and credit totals on-chain provides transparency and verifiability. However, to preserve privacy and reduce gas costs, you may store individual vote breakdowns off-chain in a decentralized storage solution like IPFS or Ceramic, submitting only cryptographic proofs (e.g., Merkle roots) to the chain. This hybrid approach is common in systems like MACI (Minimal Anti-Collusion Infrastructure).

Finally, consider the user experience and security model. You need a clear plan for voter registration and authentication to ensure one-person-one-identity. You must design the voting lifecycle: a registration period, a voting period where users allocate credits, and a tallying phase where results are calculated and finalized. Implementing a timelock or governance delay for the tallying phase can allow for challenges and audits, enhancing the system's security and legitimacy before results are executed.

mathematical-model
IMPLEMENTATION GUIDE

The Quadratic Voting Formula

A technical guide to implementing quadratic voting, a governance mechanism that reduces the power of large token holders by making additional votes increasingly expensive.

Quadratic voting (QV) is a collective decision-making process where participants allocate a budget of voice credits to express the intensity of their preferences. Unlike one-token-one-vote systems, the cost of casting votes increases quadratically. To cast v votes on a proposal, a user must spend v² voice credits from their budget. This formula, cost = v², is the core mechanism that makes QV capital-efficient for expressing strong preferences while preventing whale domination. It transforms governance from a simple tally into a market for influence, where each additional vote has a higher marginal cost.

Implementing QV requires designing two key components: the credit system and the voting interface. First, determine how voice credits are distributed. Common methods include equal allocation per participant (e.g., 100 credits each) or allocation based on a non-transferable reputation score. These credits are not tokens; they are purpose-bound accounting units reset each voting round. The front-end must clearly show users their remaining credit balance and the escalating cost of additional votes, typically through a real-time calculator that updates as they adjust sliders.

The backend logic centers on validating the quadratic cost. When a user submits votes, the system must verify sum(votes_i²) <= user_credit_balance for all their votes across proposals. A Solidity smart contract example for a single proposal demonstrates the check:

solidity
function castVote(uint256 proposalId, uint256 voteCount) external {
    uint256 cost = voteCount * voteCount;
    require(credits[msg.sender] >= cost, "Insufficient credits");
    credits[msg.sender] -= cost;
    votes[proposalId] += voteCount;
}

For multiple proposals, you must sum the squared votes before checking the balance.

A critical implementation detail is preventing Sybil attacks, where an attacker creates multiple identities to gain more credits. Pairing QV with proof-of-personhood systems like Worldcoin, BrightID, or Idena is essential. Alternatively, projects can use a trusted list of eligible addresses (e.g., token holders above a snapshot threshold). Without such a guardrail, the "one-person, one-vudget" principle fails, and the quadratic cost becomes meaningless against a swarm of fake accounts.

To calculate the final result, sum the net votes (for votes minus against votes) for each proposal. The proposal with the highest net total wins. This outcome reflects the aggregated preference intensity of the group. Prominent implementations include Gitcoin Grants, which uses QV to fund public goods, and the Colorado Democratic Party's internal elections. These cases show QV effectively surfaces community-supported projects that might be overlooked by plutocratic voting.

When deploying, consider gas optimization for on-chain voting and the user experience of credit management. For frequent votes, a layer-2 solution or a commit-reveal scheme can reduce costs. Ultimately, quadratic voting is a powerful tool for more equitable governance, but its success depends on robust implementation of identity verification, clear UX, and transparent cost-calculation logic.

sybil-resistance-methods
QUADRATIC VOTING

Sybil Resistance Requirements

Quadratic Voting (QV) is a governance mechanism designed to reflect the intensity of voter preferences while limiting the influence of wealthy or malicious actors. Implementing it requires robust sybil resistance to prevent vote manipulation.

02

Cost Function & Vote Pricing

In QV, the cost of casting multiple votes for a single option increases quadratically. The formula is typically cost = (number_of_votes)^2. Key implementation details:

  • Credit Allocation: Each participant receives a fixed budget of voice credits (e.g., 100 credits).
  • Pricing Mechanism: To cast 5 votes on a proposal costs 25 credits (5²). Casting 10 votes costs 100 credits.
  • Precision: Systems must handle fractional voting and precise credit deduction to maintain the mathematical integrity of the cost curve.
03

On-Chain vs. Off-Chain Computation

QV calculations can be resource-intensive. Choosing where to compute is critical.

  • On-Chain (e.g., Solidity): Maximizes transparency and censorship resistance but incurs high gas fees for complex math. Suitable for final tallying on L2s like Arbitrum or Optimism.
  • Off-Chain (e.g., SnarkyJS): Compute votes and proofs off-chain, then submit a zk-SNARK proof of correct tally on-chain. This preserves privacy and reduces cost.
  • Hybrid Approach: Use an oracle or dedicated voting infrastructure (like Vocdoni) to compute results with cryptographic guarantees.
04

Cryptographic Commit-Reveal Schemes

To prevent strategic voting and bribery, votes are often hidden during the voting period using a commit-reveal scheme.

  1. Commit Phase: Voters submit a cryptographic hash of their vote (and a secret salt).
  2. Reveal Phase: After voting ends, voters reveal their original vote and salt. The system verifies it matches the commit hash. This process ensures votes cannot be changed based on others' actions and mitigates coercion, as the final vote is unknown until revealed.
ARCHITECTURE

Quadratic Voting Implementations Comparison

Comparison of technical approaches for implementing quadratic voting on-chain.

Feature / MetricDirect On-ChainZK-SNARKs (e.g., MACI)State Channels / Rollups

Privacy of Vote

Partial

Gas Cost per Vote

~$10-50 (Mainnet)

~$2-5 (zkRollup)

< $0.01 (L2)

Verification Time

1 block

~20-30 sec (proof gen)

Instant (off-chain)

Sybil Resistance

Requires Token/NFT

Semaphore/RLN

Parent Chain Dependent

Implementation Complexity

Low

High

Medium

Real-time Tally

After Finalization

Max Voters (Practical)

~10,000

1,000,000

~100,000 per channel

Client-Side Proof

contract-architecture
SMART CONTRACT ARCHITECTURE

How to Implement a Quadratic Voting System

A technical guide to building a gas-efficient and secure quadratic voting mechanism on Ethereum, using the ERC-20 token standard for vote credits.

Quadratic voting is a governance mechanism designed to more accurately reflect the intensity of participant preferences. Unlike one-token-one-vote systems, it uses a quadratic cost function: the cost of casting n votes for a single proposal is n² vote credits. This makes it exponentially more expensive to concentrate voting power, protecting against whale dominance. In this implementation, we use a dedicated VoteCredit ERC-20 token to represent voting power, separating it from a governance token to allow for flexible credit distribution strategies like airdrops or purchases.

The core contract architecture involves two main components: a QuadraticVoting contract and a VoteCredit ERC-20. The voting contract manages proposals, tracks votes, and enforces the quadratic cost logic. A user must first approve the voting contract to spend their VoteCredit tokens. When voting, the contract calculates the required credits using the formula votes² and transfers them from the voter, storing the vote weight as sqrt(creditsSpent). This ensures one credit spent equals one vote, but purchasing that vote costs the square of the desired amount.

Here is a simplified core function for casting a vote:

solidity
function castVote(uint256 proposalId, uint256 voteWeight) external {
    uint256 creditsRequired = voteWeight * voteWeight;
    voteCredits.transferFrom(msg.sender, address(this), creditsRequired);
    votes[proposalId][msg.sender] += voteWeight;
    totalVotes[proposalId] += voteWeight;
}

Key considerations include preventing double voting on the same proposal, using a snapshot mechanism to lock credit balances at proposal creation, and implementing a timelock for execution. The VoteCredit contract can include minting/burning logic controlled by the governance system to manage the overall credit supply.

Security is paramount. Use OpenZeppelin's SafeMath library or Solidity 0.8.x's built-in overflow checks for the quadratic calculation. Implement reentrancy guards on the castVote function. To save gas, consider storing vote weights in a packed uint128 and using a Merkle tree or a commitment scheme for large-scale votes, where users submit a hash of their vote and later reveal it, allowing for batch processing and reduced on-chain footprint. Always audit the credit approval mechanism to prevent unauthorized transfers.

This pattern is used in projects like Gitcoin Grants for funding allocation. To extend it, you can add delegation (where delegated voting power also follows quadratic costs), allow voting with multiple choice options, or integrate with a TimeLock contract for proposal execution. The separation of vote credits from governance tokens provides a flexible foundation for experimenting with democratic funding and collective decision-making in DAOs.

solidity-example
CORE SOLIDITY CODE EXAMPLE

How to Implement a Quadratic Voting System

This guide provides a functional implementation of a quadratic voting contract, explaining the core mechanics of vote weighting and cost calculation on-chain.

Quadratic voting is a governance mechanism where the cost of a vote increases quadratically with the number of votes cast. This system aims to better reflect the intensity of voter preference while preventing dominance by large token holders. In a simple on-chain implementation, users spend a governance token (like an ERC-20) to purchase "voice credits," which they can then allocate to different proposals. The key formula is: cost = votes². Casting 1 vote costs 1 token, 2 votes cost 4 tokens, 3 votes cost 9 tokens, and so on.

The Solidity contract needs to manage several states: tracking each user's remaining voice credits, recording votes per proposal, and calculating costs correctly. A basic structure includes a mapping for user credits (mapping(address => uint256) public credits) and a nested mapping for votes per proposal (mapping(uint256 => mapping(address => uint256)) public votes). The core function, castVotes, must validate that the user has enough credits for the desired vote power before deducting the quadratic cost and updating the vote tally.

Here is a simplified version of the critical _castVote internal function logic:

solidity
function _castVote(address voter, uint256 proposalId, uint256 voteAmount) internal {
    uint256 cost = voteAmount * voteAmount; // Quadratic cost calculation
    require(credits[voter] >= cost, "Insufficient credits");

    credits[voter] -= cost;
    votes[proposalId][voter] += voteAmount;
    totalVotes[proposalId] += voteAmount;

    emit VoteCast(voter, proposalId, voteAmount, cost);
}

This ensures the financial barrier scales quadratically, making it exponentially more expensive to concentrate voting power.

Important considerations for a production system include:

  • Preventing Sybil Attacks: The system often requires a separate identity verification layer (like BrightID or proof-of-personhood) to issue initial credits, as naive token-based distribution recreates plutocracy.
  • Credit Allocation: A common pattern is to airdrop a fixed amount of voice credits (e.g., 99) to each verified user at the start of an election period.
  • Batch Voting: For UX, implement a castVotes function that allows allocating credits across multiple proposals in a single transaction, reducing gas costs.
  • View Functions: Add helper functions to check the current cost of a vote amount (getVoteCost) and a user's remaining credit balance.

To test this contract, write Foundry or Hardhat tests that verify the quadratic cost math. A key test should confirm that casting 5 votes costs 25 credits, not 5. Also, test edge cases like attempting to over-spend credits and ensuring vote totals update correctly. For inspiration and more complex implementations like Quadratic Funding, review projects such as Gitcoin Grants or the clr.fund protocol, which use similar mechanics for public goods funding.

While this on-chain core handles the vote tally and cost, a complete governance dashboard would need to integrate an off-chain component for proposal discussion and a front-end to visualize vote distribution. The contract's event emissions (VoteCast) are crucial for these subgraphs and interfaces. Remember that the security of the overall system heavily depends on the fairness of the initial credit distribution and the resilience of the identity solution against collusion.

QUADRATIC VOTING

Frequently Asked Questions

Common technical questions and solutions for developers implementing quadratic voting on-chain.

Quadratic voting (QV) is a collective decision-making mechanism where participants allocate a budget of voice credits to vote on proposals. The key innovation is the quadratic cost function: the cost to cast n votes for a single option is n² credits. This makes strong preferences exponentially more expensive, encouraging voters to distribute support across multiple options they care about.

On-chain implementation typically involves:

  1. A voting token or non-transferable credits for identity.
  2. A cost calculation in the smart contract (cost = votes²).
  3. A commit-reveal scheme or zk-proofs to prevent front-running and preserve privacy during the voting period.
  4. A tallying function that sums the square roots of spent credits per option to determine the outcome.

Protocols like Gitcoin Grants use QV to fund public goods, demonstrating its effectiveness in mitigating Sybil attacks and whale dominance.

conclusion-next-steps
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have now built the core components of a quadratic voting system. This guide covered the foundational smart contract logic, frontend integration, and key security considerations.

Your implementation demonstrates how quadratic voting mitigates the "tyranny of the majority" by making it exponentially more expensive for a single entity to dominate decisions. The key technical components you've built include: a QuadraticVoting contract that calculates vote costs using sqrt, a token faucet or payment handler for credits, and a frontend that visualizes the quadratic cost curve. Remember that in production, you must replace the simple sqrt function with a secure, audited library like those from OpenZeppelin or ABDK Math to prevent precision errors and overflows.

For a production-ready system, several critical next steps are required. First, integrate a robust identity solution like Worldcoin, BrightID, or Gitcoin Passport to implement one-person-one-vote (1p1v) sybil resistance. Second, consider moving vote credit allocation and tallying off-chain using a zero-knowledge proof (ZKP) system like Semaphore or zkSNARKs to preserve voter privacy while maintaining a public, verifiable result. Finally, explore governance frameworks such as OpenZeppelin Governor with a custom voting module to manage proposal lifecycle and execution.

To deepen your understanding, study real-world implementations. Gitcoin Grants uses quadratic funding, a close relative of quadratic voting, to allocate community donations. The RadicalxChange foundation provides extensive research and resources. For further development, review the MACI (Minimal Anti-Collusion Infrastructure) framework by Privacy & Scaling Explorations, which combines quadratic voting with cryptographic privacy to prevent collusion and vote buying.