Quadratic Voting (QV) is a collective decision-making process where participants allocate a budget of voice credits to vote on multiple proposals. The key innovation is that the cost of additional votes for a single proposal increases quadratically. For example, casting 1 vote costs 1 credit, 2 votes cost 4 credits, and 3 votes cost 9 credits. This mathematical relationship, formalized by Glen Weyl and others, makes it economically prohibitive for a single entity to dominate an outcome, thereby better reflecting the intensity of preferences across a diverse group. It's particularly well-suited for DAO governance and funding allocation, like in Gitcoin Grants.
Setting Up Quadratic Voting with Social Tokens
Setting Up Quadratic Voting with Social Tokens
A practical guide to implementing quadratic voting, a democratic mechanism that reduces the influence of large token holders, using social tokens for community governance.
Social tokens, such as those created via Collab.Land or Roll, represent membership, reputation, or contribution within a community. They are ideal for powering a QV system because they are inherently tied to identity and participation, not just capital. To set up QV, you first need to define the voting currency. This could be the community's native social token, a non-transferable "voice credit" token airdropped to members, or a hybrid model. The choice impacts sybil resistance; using a valuable, transferable token is simpler but vulnerable to buying votes, while a non-transferable reputation token better aligns with QV's democratic ideals.
The core implementation involves a smart contract that enforces the quadratic cost function. A basic Solidity structure includes a function where a user submits votes for different proposals. The contract must calculate the sum of the square roots of the votes cast for each proposal, then square the total to determine the credits spent, ensuring it does not exceed the user's balance. For example, voting [1, 4, 0] across three proposals calculates as (sqrt(1) + sqrt(4) + sqrt(0))^2 = (1 + 2 + 0)^2 = 9 credits spent. Always use a library like OpenZeppelin's for safe math operations and access control to secure the voting process.
A critical challenge is sybil resistance—preventing users from creating multiple identities to game the system. Effective strategies include integrating with BrightID or Worldcoin for proof of personhood, requiring a minimum token holding period (e.g., 30 days), or using POAP badges as a prerequisite for receiving voice credits. The voting interface, often built with React and ethers.js, should clearly show users their credit budget, the quadratic cost of their current selections, and real-time tallies. Transparency in the counting mechanism is essential for community trust.
After the voting period ends, the contract tallies the results. The winning proposal is the one with the highest sum of square roots of votes received. For instance, if Proposal A gets 100 votes from one user and Proposal B gets 1 vote each from 25 users, QV yields sqrt(100)=10 for A versus 25 * sqrt(1)=25 for B, making B the winner. This outcome demonstrates QV's power to favor broad, moderate support over concentrated interest. Successful implementations, such as Radicle's grant funding, show that QV fosters more equitable and engaged community governance when paired with thoughtfully designed social tokens.
Prerequisites
Before building a quadratic voting system with social tokens, you need to establish the foundational technical environment and understand the core concepts.
To follow this guide, you should have a working knowledge of JavaScript/TypeScript and basic Ethereum development concepts. Familiarity with smart contracts, wallets, and decentralized applications (dApps) is assumed. You will need Node.js (v18 or later) and npm or yarn installed on your machine. For blockchain interaction, a tool like MetaMask is required, and you should have access to a testnet (e.g., Sepolia) with test ETH from a faucet. The primary development framework used will be Vite with React and TypeScript.
The core of this system involves two main components: a social token and a voting contract. The social token, often an ERC-20 token, represents membership or reputation within a community. For this guide, we will use a simple mintable ERC-20. The voting contract will implement the quadratic voting logic, where the cost of votes scales quadratically with the number of votes cast, preventing whale dominance. We'll use OpenZeppelin contracts for secure, audited base implementations and Hardhat for local development and testing.
You'll need to set up your project environment. Start by initializing a new project and installing the necessary dependencies. Key packages include hardhat, @openzeppelin/contracts, ethers, viem, and wagmi. We recommend using pnpm for faster installs. A basic hardhat.config.ts file must be configured for the Sepolia testnet, requiring an Alchemy or Infura RPC URL and a private key from your funded test wallet stored securely in a .env file.
Understanding the quadratic formula is crucial. In a quadratic voting system, the cost to cast n votes is proportional to n². For example, 1 vote costs 1 credit, 2 votes cost 4 credits, and 3 votes cost 9 credits. This is typically implemented by having users approve the voting contract to spend their tokens and then pay the quadratic cost when casting votes. The contract must calculate the required token amount based on the difference between the user's new and previous vote totals for a given proposal.
Finally, ensure you have a plan for the frontend integration. We will use wagmi and viem to interact with the deployed contracts. This involves configuring wagmi providers, reading token balances, and writing transactions for voting. The UI will need to display proposals, current vote counts, and allow users to connect their wallet and cast votes. With these prerequisites in place, you are ready to start building the smart contract and application logic.
Key Concepts: The Quadratic Model
Quadratic Voting (QV) is a mechanism designed to more accurately reflect the intensity of individual preferences in collective decision-making, particularly for allocating shared resources like community treasuries.
The quadratic model addresses a core flaw in traditional one-token-one-vote (1T1V) governance: it allows wealthy participants to dominate outcomes. In QV, the cost of casting votes increases quadratically with the number of votes allocated to a single option. For example, to cast 1 vote costs 1 credit, 2 votes cost 4 credits (2²), and 10 votes cost 100 credits (10²). This pricing structure makes it economically irrational for any single entity to concentrate all their voting power on one proposal, promoting more equitable and diverse outcomes that better represent the collective will.
Implementing QV with social tokens or non-transferable governance tokens adds a powerful sybil-resistance layer. Since the cost is quadratic in votes, not tokens, an attacker would need to control a vast number of unique identities (sybils) to sway a vote, rather than just amassing a large token balance. This makes QV particularly effective for retroactive public goods funding (like Gitcoin Grants) and community grant allocation, where the goal is to fund projects based on broad, democratic support rather than the preferences of a few large holders.
The core mechanism is enforced by a smart contract. A voter with a budget of C credits can allocate v_i votes to proposal i. The contract ensures the sum of the squares of their votes does not exceed their budget: Σ(v_i²) ≤ C. To check this, the contract calculates the sum of squares of the voter's new vote allocations and verifies it's within their remaining credit limit, which is often derived from their token balance or a fixed allocation per epoch.
Here is a simplified Solidity function illustrating the credit check logic:
solidityfunction _checkQuadraticCost(uint256[] memory votes) internal pure returns (uint256 totalCost) { totalCost = 0; for (uint256 i = 0; i < votes.length; i++) { totalCost += votes[i] * votes[i]; } }
A front-end or off-chain client would use this logic to prevent users from submitting invalid vote bundles that exceed their quadratic budget.
While powerful, QV has practical considerations. Collusion remains a challenge, as participants could coordinate to split their budgets among each other's preferred options. Voter fatigue can also be an issue with many proposals. Furthermore, the gas cost for on-chain verification scales with the number of proposals a voter engages with. These limitations are active areas of research, with solutions exploring cryptographic proofs like MACI (Minimal Anti-Collusion Infrastructure) for collusion resistance and layer-2 scaling for cost reduction.
Governance Model Comparison
Comparison of governance models for social token communities, focusing on quadratic voting suitability.
| Governance Feature | One-Token-One-Vote | Quadratic Voting | Conviction Voting |
|---|---|---|---|
Sybil Resistance | |||
Whale Dominance Risk | Very High | Low | Medium |
Implementation Complexity | Low | Medium | High |
Gas Cost per Vote | $2-5 | $5-15 | $15-50 |
Ideal Community Size | < 100 members | 100-10k members |
|
Snapshot Integration | Native | Via Module | Via Plugin |
Vote Weight Calculation | Linear | Square Root | Time-Based |
Best For | Simple Proposals | Funding Allocation | Continuous Signaling |
Implementing a Quadratic Voting Strategy on Snapshot
A technical guide to configuring a custom quadratic voting strategy on Snapshot, using social token balances to weight votes and mitigate whale dominance in DAO governance.
Quadratic voting is a governance mechanism designed to better reflect the intensity of voter preferences while limiting the influence of large token holders, or 'whales'. Instead of a simple one-token-one-vote model, a voter's voting power is calculated as the square root of their token balance. This means a user with 100 tokens gets 10 voting power (sqrt(100) = 10), while a user with 10,000 tokens only gets 100 voting power (sqrt(10,000) = 100). The result is a more democratic distribution of influence, where many small holders can collectively outweigh a single large holder. Snapshot supports this through customizable voting strategies, which are JavaScript functions that define how voting power is fetched and calculated for each address.
To implement this, you must create a custom strategy in your Snapshot space settings. The strategy is defined by a name, a network (e.g., 1 for Ethereum Mainnet), and a strategy object containing the logic. A basic quadratic voting strategy for a standard ERC-20 token uses the erc20-balance-of strategy with a symbol and decimals, then applies the square root function. The key is the params object, which can include a quadratic boolean flag. However, for full control or integration with social tokens, you will often need to write a custom strategy.
Here is a simplified example of a custom quadratic voting strategy for an ERC-20 token deployed on Ethereum. This strategy fetches the token balance and returns the square root. The function must be hosted publicly, for instance, on GitHub Gist or IPFS, and its URL is provided to Snapshot.
javascript// Example: Quadratic Voting Strategy for ERC-20 module.exports = { name: 'erc20-quadratic', author: 'YourDAO', version: '0.1.0', network: '1', // Ethereum Mainnet strategy: { name: 'contract-call', params: { address: '0xYourTokenAddress', decimals: 18, symbol: 'SOCIAL', methodABI: { name: 'balanceOf', type: 'function', inputs: [{ name: 'account', type: 'address' }], outputs: [{ name: '', type: 'uint256' }] } } }, async getVotingPower(space, voterAddress, block) { // Fetch raw token balance using the defined contract call const balance = await this.strategy.getVotingPower(space, voterAddress, block); // Apply quadratic formula: voting power = sqrt(balance) const quadraticPower = Math.sqrt(balance); return quadraticPower; } };
For social tokens or more complex reputation systems, the strategy can pull data from platforms like Collab.Land, SourceCred, or a custom on-chain registry. Instead of a simple token balance, you might query an API endpoint that returns a user's 'contribution score' or 'reputation balance', then apply the quadratic function to that value. This aligns voting power with proven community contribution rather than pure capital. Ensure your data source is reliable and publicly verifiable to maintain the trustlessness of the Snapshot vote.
After deploying your strategy, test it thoroughly using Snapshot's Test Strategy feature. Input a few addresses with known token balances and verify the calculated voting power matches your expected quadratic values. Common pitfalls include incorrect decimal handling, unreachable API endpoints for custom data, and not accounting for the block number snapshot. Once validated, assign the strategy to a proposal in your space. Voters will see their voting power adjusted automatically, fostering a more equitable and sybil-resistant governance process.
Building a Custom Quadratic Voting Smart Contract
Implement a Sybil-resistant governance mechanism using social tokens to weight votes quadratically.
Quadratic voting is a governance mechanism designed to better reflect the intensity of voter preferences while limiting the influence of large token holders. Instead of one token equaling one vote, the cost of a vote increases quadratically with the number of votes cast. This means casting 2 votes costs 4 credits, 3 votes costs 9 credits, and so on. When combined with social tokens—which represent reputation or contribution rather than pure capital—it creates a more nuanced and resistant-to-manipulation system for community decisions. This guide walks through building a custom smart contract for this purpose on Ethereum.
The core logic revolves around tracking a voter's credits based on their social token balance. First, define the relationship: 1 social token could equal 1 voting credit. The key formula is cost = votes². A user with 100 credits can cast a maximum of 10 votes on a single proposal (10² = 100). The contract must prevent overallocation by checking usedCredits[user][proposalId] + cost <= getCredits(user). State variables include proposals, voteCount, and a mapping for usedCredits. This structure ensures the quadratic cost is enforced on-chain.
Here is a simplified Solidity snippet for the voting function:
solidityfunction castVote(uint256 proposalId, uint8 voteCount) external { uint256 cost = voteCount * voteCount; uint256 userCredits = socialToken.balanceOf(msg.sender); require(usedCredits[msg.sender][proposalId] + cost <= userCredits, "Insufficient credits"); usedCredits[msg.sender][proposalId] += cost; proposals[proposalId].totalVotes += voteCount; // Additional logic for tracking voter's choice }
This function calculates the quadratic cost, validates the user has enough social token-derived credits, and updates the proposal's tally. The socialToken would be an ERC-20 interface pointing to your social token contract.
Integrating a social token like ERC-20 or ERC-1155 is critical. The contract should call balanceOf to determine voting power. For enhanced Sybil resistance, consider using proof-of-personhood systems like Worldcoin or BrightID to mint or weight social tokens. Alternatively, tie token distribution to verifiable on-chain actions (e.g., contribution NFTs). The vote tallying should be isolated per proposal, and you must include functions to create proposals and query results. Always add a timelock or voting period to finalize outcomes.
Security considerations are paramount. Use checks-effects-interactions patterns and guard against integer overflow (though Solidity 0.8.x defaults to checked math). Consider implementing a vote delegation feature and snapshotting token balances at proposal creation time to prevent manipulation. Thoroughly test with tools like Foundry or Hardhat, simulating attacks where a user tries to vote twice or exceed their credit limit. The final contract provides a transparent, auditable foundation for community governance that values diverse participation over sheer capital weight.
Essential Resources and Tools
These tools and frameworks are commonly used to implement quadratic voting (QV) and quadratic funding (QF) models for DAOs and social token communities. Each resource focuses on a concrete layer: identity, voting mechanics, token design, and execution.
Token Design Patterns for Quadratic Voting
Quadratic voting outcomes depend heavily on social token design. Poor tokenomics can undermine even well-implemented voting systems.
Recommended patterns:
- Non-transferable or semi-transferable tokens to reduce vote buying
- Time-weighted balances to favor long-term members
- Voting power caps before quadratic scaling
Common implementations:
- ERC-20 with snapshot-based voting
- Soulbound ERC-721s used as voting credentials
- Dual-token systems separating value and governance
Design tradeoffs:
- Transferability increases liquidity but weakens governance
- Strong identity weighting improves fairness but reduces privacy
Token design should be finalized before deploying quadratic logic to avoid governance instability.
Setting Up Quadratic Voting with Social Tokens
Quadratic voting is a democratic mechanism that allocates voting power based on the square root of token holdings, preventing whale dominance. This guide explains how to implement it for community governance using social tokens.
Quadratic voting (QV) is a governance model designed to reflect the intensity of voter preferences while mitigating the influence of large token holders. Instead of granting one vote per token (one-token-one-vote), QV calculates voting power as the square root of the number of tokens a user commits to a proposal. For example, a user with 100 tokens gets 10 voting credits (√100), while a user with 10,000 tokens gets only 100 credits (√10,000). This system makes it exponentially more expensive for a single entity to dominate decisions, promoting more equitable and diverse community outcomes. It's particularly well-suited for social token communities where engagement and reputation are valued alongside financial stake.
To implement quadratic voting, you need a smart contract that handles vote credits and a frontend for user interaction. The core logic involves calculating a user's voting power and deducting the corresponding cost from their token balance. A basic Solidity function might look like this:
solidityfunction castVote(uint256 proposalId, uint256 votePower) public { uint256 cost = votePower * votePower; require(balanceOf(msg.sender) >= cost, "Insufficient tokens"); _burn(msg.sender, cost); votes[proposalId][msg.sender] += votePower; }
This function ensures a user pays tokens equal to the square of their desired voting power (votePower²). Key considerations include using a commit-reveal scheme to prevent strategic voting, implementing a vote delegation system, and setting up snapshotting to determine eligible token holders at a specific block.
Practical deployment requires integrating with existing social token standards like ERC-20 or ERC-1155 and a governance framework such as OpenZeppelin's Governor. You'll also need to decide on critical parameters: the voting period duration, quorum requirements, and a proposal threshold. For gas efficiency on Ethereum, consider using a Layer 2 solution like Arbitrum or Optimism, or an app-specific chain via Cosmos SDK or Polygon Edge. Tools like Tally or Boardroom can provide a frontend interface, while Snapshot offers an off-chain, gas-free voting layer that can be adapted for quadratic calculations using its strategies plugin system.
Successful QV implementations balance fairness with usability. The Gitcoin Grants program is a canonical example, using quadratic funding to match community donations and prevent sybil attacks with a unique passport system. For your community, start with a pilot on a testnet for a low-stakes proposal. Educate members on how vote cost works—spending 9 tokens grants 3 votes, not 9. Monitor metrics like voter participation rate and the Gini coefficient of voting power distribution to assess the system's health. Remember, the goal is not just technical implementation but fostering a culture where every member's voice has meaningful weight.
Quadratic Voting Cost Examples
A comparison of the total cost for a voter to allocate different vote weights across three proposals, demonstrating the quadratic cost scaling.
| Vote Allocation (Proposal A, B, C) | Total Votes Cast | Linear Cost (if applied) | Quadratic Cost |
|---|---|---|---|
(1, 1, 1) | 3 votes | $3.00 | $3.00 |
(5, 0, 0) | 5 votes | $5.00 | $25.00 |
(2, 2, 2) | 6 votes | $6.00 | $12.00 |
(10, 0, 0) | 10 votes | $10.00 | $100.00 |
(3, 3, 3) | 9 votes | $9.00 | $27.00 |
(8, 1, 1) | 10 votes | $10.00 | $66.00 |
(0, 0, 0) | 0 votes | $0.00 | $0.00 |
Frequently Asked Questions
Common technical questions and troubleshooting steps for developers implementing quadratic voting systems with social tokens.
Quadratic voting (QV) is a governance mechanism where the cost of casting votes increases quadratically with the number of votes allocated to a single proposal. Unlike simple token-weighted voting, where one token equals one vote, QV uses a formula like cost = votes². This means buying 2 votes costs 4 credits, and 10 votes costs 100 credits. The core difference is that QV strongly penalizes vote concentration, making it economically prohibitive for a single large holder to dominate a decision. This aligns incentives for broad consensus and reduces the "whale problem" prevalent in many DAOs. It's mathematically designed to reflect the intensity of preference across a diverse group more accurately than linear systems.
Conclusion and Next Steps
You have successfully set up a basic quadratic voting system for social token governance. This guide covered the core components: the token contract, the voting contract, and a simple frontend interface.
Your implementation now allows token holders to propose ideas and vote using a quadratic formula, where voting power is the square root of the tokens committed. This system reduces the influence of large token holders and encourages broader community participation. The key contracts you deployed include a standard ERC-20 token for representation and a custom QuadraticVoting contract to manage proposals, deposits, and vote tallying. The frontend connects via MetaMask to interact with these contracts on a testnet like Sepolia or Goerli.
To build on this foundation, consider enhancing the system's security and functionality. Implement a timelock on executed proposals to prevent malicious governance actions. Add a delegation feature so users can delegate their voting power to others. For production, you must conduct thorough audits and consider using established frameworks like OpenZeppelin's Governor for battle-tested governance logic. Always test upgrades on a forked mainnet before deployment.
For further learning, explore integrating with Sybil-resistant identity systems like BrightID or Gitcoin Passport to prevent vote manipulation through multiple accounts. Study real-world implementations such as Gitcoin Grants, which uses quadratic funding for public goods. The next step is to move your application to a mainnet, starting with a low-stakes token and a multisig guardian for the initial governance period to ensure stability as the community learns the system.