Quadratic Voting System Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Quadratic Voting System Development
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Developing quadratic voting system

Quadratic voting solves a fundamental problem of token-weighted voting: a whale with 1000x tokens gets 1000x influence. QV sets a different rule: voting power is proportional to the square root of spent resources. 100 voting credits give 10 units of voting power. 900 credits — 30. To match the power of 9 people with 1 credit each, you need to spend 81 credits.

Math: influence = √credits. This makes it economically inefficient for one participant to dominate compared to a broad coalition.

Theoretical foundation

QV was proposed by economists Eric Posner and Glen Weyl in "Radical Markets". The intuition: in standard voting, 1 person = 1 vote, but preference intensity isn't measured. Someone who cares deeply and someone indifferent have equal weight. QV lets you express intensity through spent credits — closer to real economic preferences.

Example: 100 people slightly prefer option A. 10 people strongly want option B. In standard voting, A wins. In QV, if each of the 10 spends 100 credits on B (power = 10 × √100 = 100), they can override a coalition of 100, each spending 1 credit (power = 100 × √1 = 100). With balanced preferences, the more intensely desired outcome wins.

Voting credit systems

Voice Credits model

Standard scheme: each participant gets fixed voice credits budget per voting period. Credits don't carry over and aren't transferred — each period gets fresh allocation.

contract QuadraticVoting {
    struct VotingRound {
        uint256 startTime;
        uint256 endTime;
        mapping(uint256 => int256) optionVotes;  // optionId => total votes (sqrt-weighted)
    }

    uint256 public constant CREDITS_PER_ROUND = 100;

    // Spent credits of participant in current round
    mapping(address => mapping(uint256 => uint256)) public creditsSpent;

    function vote(
        uint256 roundId,
        uint256 optionId,
        uint256 credits,  // credits to spend on this option
        bool support
    ) external {
        VotingRound storage round = rounds[roundId];
        require(block.timestamp >= round.startTime && block.timestamp < round.endTime, "Round inactive");

        uint256 totalSpent = creditsSpent[msg.sender][roundId] + credits;
        require(totalSpent <= CREDITS_PER_ROUND, "Exceeds budget");

        // QV: voting power = sqrt(credits)
        uint256 votes = sqrt(credits);

        creditsSpent[msg.sender][roundId] = totalSpent;

        if (support) {
            round.optionVotes[optionId] += int256(votes);
        } else {
            round.optionVotes[optionId] -= int256(votes);
        }

        emit VoteCast(msg.sender, roundId, optionId, credits, votes, support);
    }

    // Integer square root (Babylonian method)
    function sqrt(uint256 x) internal pure returns (uint256 y) {
        if (x == 0) return 0;
        uint256 z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }
}

Token-weighted credits

Alternative scheme: credits are proportional to token balance (as in Gitcoin Grants). Holder of 1000 tokens has 1000 credits. But voting power is still √ of spent credits. This gives wealthy participants more credits, but not linear influence.

Comparison: at token-proportional credits with 10,000 vs 100 balance (100x difference) — voting power differs by √100 = 10x, not 100x. Significantly better than standard token-weighted.

Delegated QV

A participant can delegate credits to another. Delegate votes with a batch of credits, but √ is still applied to total credits per option from each original owner.

Important nuance: credit aggregation from delegates must preserve source information. If you just sum delegatee credits into a pool — you lose QV property.

// Correct aggregation: each delegation entry separate
struct Delegation {
    address delegator;
    uint256 credits;
}

// Delegate voting: applies QV to each delegation separately
function voteAsDelegate(
    uint256 roundId,
    uint256 optionId,
    Delegation[] calldata delegations
) external {
    int256 totalVotes = 0;
    for (uint i = 0; i < delegations.length; i++) {
        require(
            delegatedCredits[delegations[i].delegator][msg.sender][roundId]
            >= delegations[i].credits,
            "Insufficient delegated credits"
        );
        totalVotes += int256(sqrt(delegations[i].credits));
    }
    rounds[roundId].optionVotes[optionId] += totalVotes;
}

Sybil resistance: QV's main problem

QV breaks completely without Sybil defense. One participant with 100 credits gets power 10. Hundred participants with 1 credit each get total power 100. By splitting identity into N addresses, an attacker multiplies power by √N.

Proof of Humanity

Registered unique person in Proof of Humanity or Worldcoin gets 1 credit allocation. Not vulnerable to Sybil — can't create thousand real people.

Integration via on-chain verification:

interface IProofOfHumanity {
    function isRegistered(address _submissionID) external view returns (bool);
}

contract QVWithPoH {
    IProofOfHumanity public poh;

    function registerForRound(uint256 roundId) external {
        require(poh.isRegistered(msg.sender), "Not registered in PoH");
        require(!registeredForRound[roundId][msg.sender], "Already registered");
        registeredForRound[roundId][msg.sender] = true;
        creditsBalance[roundId][msg.sender] = CREDITS_PER_ROUND;
    }
}

Problem with PoH: limited coverage, registration takes time, disputeable. For DAO with global audience — entry barrier.

Worldcoin World ID

More scalable solution. Iris scan → ZK proof of uniqueness. On-chain verification through semaphore protocol without personal data disclosure.

import "@worldcoin/world-id-contracts/src/interfaces/IWorldID.sol";
import { ByteHasher } from "@worldcoin/world-id-contracts/src/helpers/ByteHasher.sol";

contract QVWithWorldID {
    using ByteHasher for bytes;

    IWorldID internal worldId;
    uint256 internal groupId = 1; // Orb-verified
    uint256 internal externalNullifierHash;

    function registerWithWorldID(
        address signal,
        uint256 root,
        uint256 nullifierHash,
        uint256[8] calldata proof
    ) external {
        // Verifies ZK proof of uniqueness
        worldId.verifyProof(
            root,
            groupId,
            abi.encodePacked(signal).hashToField(),
            nullifierHash,
            externalNullifierHash,
            proof
        );

        require(!nullifierUsed[nullifierHash], "Already registered");
        nullifierUsed[nullifierHash] = true;
        // grant credits
    }
}

Stake-based anti-sybil

For DeFi-oriented DAO: require token stake for participation. Creating many Sybil accounts becomes expensive. Combined with QV: stake determines base credit, but voting power is still √ of spent.

Quadratic Funding (QV extension)

Gitcoin uses QF (Quadratic Funding) — a derivative of QV. Funding mechanism for public goods: projects receive matching funds proportional to square of sum of square roots of individual contributions.

Matching = (Σ √contribution_i)²

Example: project A got 100 contributions of $1. Matching ∝ (100 × √1)² = 10,000. Project B got 1 contribution of $100. Matching ∝ (1 × √100)² = 100. With same contribution sum, broad-support project gets 100x more matching.

Gitcoin Grants implemented this on Ethereum (Optimism to reduce gas costs). This is the most well-known production implementation of QV/QF in crypto.

Full system architecture

On-chain components

  • QuadraticVoting.sol: core contract with credit logic and voting
  • IdentityRegistry.sol: linking addresses to verified identities (PoH/Worldcoin)
  • VotingRoundFactory.sol: creating rounds with parameters (duration, options, credit allocation)

Off-chain components

Snapshot integration: most DAOs use Snapshot for off-chain QV voting — free and unlimited participants. Snapshot supports QV strategy.

Results calculator: off-chain service for complex QF calculations, then publish results on-chain.

Frontend: interface where participant sees credit budget, sliders to distribute across options, live preview voting power for each decision.

Parameters and tuning

Parameter Recommendation Rationale
Base credits 99-100 Convenient for √ calculation
Round duration 7-14 days Time for thoughtful participation
Credit carry-over No Prevents accumulation and attacks
Minimum stake 0.01-0.1% supply Basic anti-sybil without high barrier
Sybil protection PoH + stake Multi-layer defense

Limitations and honest view

QV doesn't solve all governance problems. Weaknesses:

Collusion: group of participants can coordinate credit distribution to maximize combined influence. Harder than in standard voting, but not impossible. MACI (Minimum Anti-Collusion Infrastructure) solves this via ZK cryptography.

Rational ignorance: most participants won't spend time studying 20 proposals in a round. QV lowers the cost of ignoring, but doesn't eliminate it.

Optimal strategy: mathematically optimal strategy for participants isn't obvious. Can reduce participation among non-technical participants.

QV fits better for limited option sets (priority selection, grant distribution) than for binary yes/no protocol decisions.

Developing full QV system with PoH/Worldcoin integration: 8-12 weeks. Basic on-chain QV without anti-sybil — 3-4 weeks.