If you’ve ever donated on Gitcoin, you’ve participated in a Quadratic Funding (QF) round, perhaps without fully understanding why your $1 donation sometimes unlocked ten times that amount in matching funds, while a whale’s $10,000 donation barely moved the needle. That asymmetry isn’t a bug. It’s the entire point.

This article unpacks QF from first principles: the economic philosophy behind it, the mathematics that make it work, the real-world constraints that complicate it, and a full Solidity implementation that brings it on-chain using Foundry. By the end, you’ll understand not just what QF is, but why it is the way it is, and what it takes to actually build it.

The Problem QF Is Trying to Solve

Before we look at the solution, we need to understand the failure modes it addresses. Two dominant models of resource allocation exist, and both are broken in predictable ways.

The Failure of Pure Markets (Capitalism’s Blind Spot)

In a free market, funding follows private interest. A project receives exactly the sum of what individuals choose to contribute:

F = Σ cᵢ

The problem is that markets are optimised for private goods, excludable goods (if you don’t pay, you don’t get access), and rival goods (your consumption reduces what’s available to others). Public goods are the opposite: they’re non-excludable and non-rival. Clean air, open-source software, free documentation, public research, everyone benefits regardless of whether they contributed.

This creates the free-rider problem. Because you can enjoy a public good without paying for it, rational agents choose not to contribute, expecting others to fund it. The result is chronic underfunding of the things communities actually need most. In a linear funding model, only the single contributor with the highest marginal valuation has a meaningful influence. Everyone else free-rides.

For instance, imagine an open-source developer building a critical cryptographic library that secures $50 billion worth of DeFi protocols. The library is free to use. Every protocol benefits, but none feels individually responsible for funding it. The developer ends up making $3,000 from crowdfunding despite enabling billions in value. This is the market failure QF is designed to correct.

The Failure of One-Person-One-Vote Democracy

Democratic systems solve the free-rider problem by forcing collective decisions, but they introduce a different distortion: they are blind to the intensity of preferences.

Under majority rule, a project mildly preferred by 51% of voters will be funded. A project desperately needed by 49% will receive nothing. This systematically disadvantages minority communities, niche but critical infrastructure, and “entrepreneurial” public goods innovations that most people don’t yet understand but a passionate few see as transformative.

For instance, A proposal to fund a new park that 60% of citizens vaguely support defeats a proposal to fund wheelchair ramp retrofits that only 15% of citizens care about, even though 15% having an intense, life-affecting stake in the outcome.

The Middle Ground: What QF Aims For

Quadratic Funding, introduced by Vitalik Buterin, Zoë Hitzig, and Glen Weyl in their 2018 paper Liberal Radicalism, is designed to sit between these two failure modes. It is:

As responsive as a market: anyone can signal support for any project at any time, and preferences are expressed through voluntary financial contributions.Resistant to wealth dominance: a dollar from a millionaire does not carry the same weight as a dollar from an ordinary contributor, because what matters most is the number of contributors, not the amount.Sensitive to preference intensity: contributors signal how much they care through the size of their donation, but in a way that rewards breadth over depth.

The mechanism that achieves this balance is a surprisingly elegant formula.

The Formula — What It Is and Why It Works This Way

The Core Equation

The total funding a project receives under Quadratic Funding is:

Fₚ = ( Σᵢ √cᵢₚ )²

Where:

Fₚ Is the total funding allocated to the project pcᵢₚ is the contribution of the individual i to project pΣᵢ √cᵢₚ is the sum of the square roots of all individual contributions

The matching amount from the shared pool is then:

Matching = Fₚ − Σ cᵢₚ = ( Σᵢ √cᵢₚ )² − total direct donations

That is, QF calculates what the project should receive, then fills in the gap with matching funds.

Breaking It Down Step-by-Step

Let’s use a concrete example. Suppose a project receives three donations:

Contributor Amount Alice $10 Bob $3 Carol $20

Step 1 — Take the square root of each contribution:

Contributor Amount √Amount Alice $10 ≈ 3.162 Bob $3 ≈ 1.732 Carol $20 ≈ 4.472

Step 2 — Sum the square roots:

3.162 + 1.732 + 4.472 = 9.366

Step 3 — Square the sum:

9.366² ≈ $87.72

Step 4 — Subtract direct donations:

Direct donations: $10 + $3 + $20 = $33
Matching amount: $87.72 − $33 = $54.72

So three contributors donating a combined $33 unlock $54.72 in matching funds, a 165% boost.

Now compare what happens if a single donor gives the same $33 total:

√33 ≈ 5.745
5.745² = 33.00
Matching = $33 − $33 = $0

A single $33 donation generates zero matching. The mechanism is explicitly designed to reward community breadth, not individual wealth.

Why the Square Root? The Mathematical Intuition

The choice of the square root is not arbitrary. It’s the precise function that embodies a key democratic principle: diminishing marginal returns on influence.

Consider what different functions would produce:

Linear (pure capitalism): F = Σ cᵢ; A $100 donation contributes exactly 100× more than a $1 donation. Wealth = power.

Pure democracy (1p1v): Every address counts equally regardless of donation size. A $0.01 donation has the same weight as a $10,000 one. Easy to game with fake identities, and ignores preference intensity.

Square root (QF): A $100 donation contributes √100 = 10 units of weight. A $1 donation contributes √1 = 1 unit of weight. So the $100 donor is only 10× as influential as the $1 donor, despite contributing 100× as much money. This compresses the power of wealth while still rewarding greater financial commitment, a genuine middle ground.

The “quadratic” in Quadratic Funding refers to the squaring operation in the final step. The cost to achieve a given influence is quadratic: to double your weight, you must contribute four times as much.

The Power of Collective Action: A Vivid Illustration

To see QF’s most important property, consider two scenarios for a project with a $1,000 matching pool:

Scenario A: One wealthy backer

1 donor gives $1,000√1000 ≈ 31.6231.62² = 1,000Matching = $0

Scenario B: A community rallies

100 donors each give $1100 × √1 = 100100² = $10,000Matching = $10,000 − $100 = $9,900

One hundred people each contributing $1 generate nearly $10,000 in matching. A single donor giving $1,000 generates nothing. This is not a flaw; it is the mechanism working exactly as intended. Community consensus unlocks shared resources. Individual wealth does not.

Real-World Constraints — From Theory to Capital-Constrained QF

The pure QF formula has one fatal flaw for real-world deployment: it can claim arbitrarily more matches than exist in the pool.

In the example above, the $100 community round would need $9,900 in matching, but what if only $5,000 is available? The formula, taken literally, would be insolvent.

Introducing Alpha: Capital-Constrained QF (CQF)

The solution is to introduce a weighting parameter α (alpha) that scales QF results to fit within the actual budget. The CQF formula for a project’s payout becomes:

Payout = α × QF_score + (1 − α) × direct_contributions

Where:

When α = 1: pure QF (full matching amplification)When α = 0: pure direct funding (no matching amplification)When 0 < α < 1: a blend that exactly clears the available budget

The optimal alpha is calculated as:

α = (matching_pool − total_direct_contributions) / (total_QF_score − total_direct_contributions)

This ensures the total payouts across all projects precisely equal the available matching pool, no overspend, no underspend.

In my Solidity implementation, this is handled in calculateOptimalAlpha():

function calculateOptimalAlpha() public returns (uint256 alpha) {
uint256 totalQFScore = calculateTotalQFScore();
uint256 totalDirectContributions = totalContribution; uint256 numerator = totalMatchingFund;
uint256 denominator = totalQFScore; if (numerator >= denominator) {
alpha = 1e18; // Full QF: pool covers everything
} else if (numerator <= totalDirectContributions) {
alpha = 0; // Pool too small: pure direct
} else {
alpha = ((numerator – totalDirectContributions) * 1e18)
/ (denominator – totalDirectContributions);
}
// Clamped to [0, 1e18]
}

Alpha is then used in finalizeRound() to calculate the matching payout for every project, ensuring total distributions never exceed totalMatchingFund.

The Sybil Attack — QF’s Achilles Heel

QF’s greatest strength, rewarding the number of contributors, is also its greatest vulnerability. If you can fake an identity, you can fake community support.

How Sybil Attacks Exploit the Formula

A Sybil attack occurs when a single entity creates multiple fake identities to appear as multiple contributors. In QF, the impact is severe.

The $1-to-$1,000 amplifier: Suppose an attacker controls 100 fake wallets, each contributing $0.01:

Total donated: 100 × $0.01 = $1
√ of each: 100 × √0.01 = 100 × 0.1 = 10
Squared sum: 10² = $100
Matching: $100 − $1 = $99

A $1 “investment” across 100 fake identities generates $99 in matching, a 9,900% return. The attacker is draining the matching pool from legitimate projects.

The Reciprocal Backing Ring: A group of 20 project creators coordinate to each donate to each other’s projects using fresh wallets. Each cross-donation looks like independent community support. The QF formula amplifies all of it, and every participant takes a larger slice of the matching pool at the expense of genuinely community-backed projects.

The botnet approach: An attacker deploys a bot to generate thousands of wallets, each sending negligible ETH (or even zero, if the contract is misconfigured). If identity isn’t verified, the formula treats every wallet as a unique human signal.

How My Contract Defends Against Sybil Attacks

The contract implements a dual-mode Sybil resistance system through the ISybilResistance interface:

interface ISybilResistance {
function isVerified(address _address) external view returns (bool);
}

This interface is intentionally abstract. It can be wired to:

Gitcoin Passport — an identity aggregation service that scores wallet “humanity” based on connected accounts (GitHub, Twitter, ENS, etc.)WorldID — biometric proof of personhood via iris scanningInternal whitelist — a curated list of KYC’d addresses managed by the round operator

The onlyVerified modifier gates every contribution:

modifier onlyVerified() {
if (sybilResistanceEnabled) {
require(sybilResistance.isVerified(msg.sender), “Not verified”);
} else if (whitelistMode) {
require(verifiedAddresses[msg.sender], “Not whitelisted”);
}
_;
}

And round operators can seamlessly switch between modes:

function setSybilResistance(address _sybilResistanceAddress) public onlyOwner {
sybilResistance = ISybilResistance(_sybilResistanceAddress);
sybilResistanceEnabled = (_sybilResistanceAddress != address(0));
whitelistMode = false; // Disable whitelist when using external provider
}function enableWhitelistMode() public onlyOwner {
whitelistMode = true;
sybilResistanceEnabled = false;
}

No identity verification is perfect, but the combination of on-chain modifiers and off-chain verification providers raises the cost of Sybil attacks significantly, especially when economic barriers (gas costs, minimum donations) are factored in.

The Engineering — Building QF in Solidity

The 24KB Problem

Every Ethereum smart contract has a hard deployment size limit of 24 kilobytes (the Spurious Dragon EIP-170 limit). Implementing the full CQF formula, with square root calculations, precision scaling, alpha computation, round management, Sybil resistance, and withdrawal logic, pushes dangerously close to this ceiling.

The contract addresses this with three optimisation strategies:

1. Library extraction

The most computation-heavy math, the square root summation, is isolated into a clean internal function (sqrtFixed) that the Solidity compiler can efficiently inline:

function sqrtFixed(uint256 x) public pure returns (uint256 y) {
if (x == 0) return 0;
uint256 scaledInput = x * PRECISION_FACTOR; // Scale by 1e9
uint256 z = (scaledInput + 1) / 2;
y = scaledInput;
while (z < y) {
y = z;
z = (scaledInput / z + z) / 2;
}
return y;
}

2. Function internalization

Helper functions that are only called from within the contract are declared internal rather than public. This allows the compiler to optimise call jumps and significantly reduce bytecode size.

3. Three-phase alpha calculation

Rather than computing the entire CQF match in a single monolithic function, the logic is broken into three discrete phases: summing square roots across contributions, calculating total QF scores, and then applying alpha to scale the final distribution. This modular approach keeps each function lean enough to stay within stack depth limits and keeps the overall bytecode well under the 24KB ceiling.

Precision Math: Handling Square

Roots Without Floating Points

Solidity has no native floating-point support. All arithmetic is integer-based. This creates a problem: √(2 ether) should return approximately 1.414, but integer math would simply return 1, losing half the precision.

The solution is fixed-point arithmetic with a precision scaling factor of 1e9 (stored as PRECISION_FACTOR):

uint256 public constant PRECISION_FACTOR = 1e9;

When computing a square root, the input is first multiplied by PRECISION_FACTOR, and the integer square root is taken on the scaled value. The result is then “unscaled” later by dividing by PRECISION_FACTOR² = 1e18:

uint256 projectQFScore = (sumOfSqrts * sumOfSqrts) / (PRECISION_FACTOR * PRECISION_FACTOR);

This gives us 9 decimal places of precision, more than sufficient for ETH-denominated donations measured in wei (where 1 ETH = 1e18 wei).

Concrete example:

Contribution: 1e18 wei (1 ETH)scaledInput = 1e18 × 1e9 = 1e27sqrtFixed(1e18) ≈ √(1e27) ≈ 1e13.5 ≈ 3.162 × 10¹³This integer represents 3.162 with 13 digits of precision

Round Lifecycle

The contract models a complete funding round lifecycle:

[Deploy] → startRound() → [Contributions] → endRound() → finalizeRound() → withdrawProjectFunds()

Each state transition has access control and validity checks:

modifier roundIsActive() {
require(roundActive, “No round”);
require(block.timestamp >= roundStartTime, “Not started”);
require(block.timestamp <= roundEndTime, “Ended”);
_;
}

finalizeRound() can only be called after the round has ended, preventing mid-round manipulation of matching calculations. Once finalized, project recipients can call withdrawProjectFunds() to pull their direct donations plus matching, with protection against double-withdrawal:

uint256 alreadyWithdrawn = projectWithdrawnAmount[_projectId];
require(totalPayout > alreadyWithdrawn, “No funds left”);
uint256 availableToWithdraw = totalPayout – alreadyWithdrawn;
projectWithdrawnAmount[_projectId] = totalPayout;
(bool success,) = payable(msg.sender).call{value: availableToWithdraw}(“”);

Note: the use of .call{value: …} instead of .transfer() This is the modern Solidity best practice, as transfer() hardcodes a 2,300 gas stipend that can fail on smart contract recipients.

The Full Calculation Flow — Putting It All Together

Let’s trace a complete round from start to finish with a realistic example.

Setup:

Matching pool: 10 ETHThree projects: LibraryX, ProtocolY, ToolZ

Contributions received:

Project Contributors Amounts (ETH) LibraryX 50 people 0.01 each → 0.5 total ProtocolY 3 people 2, 1, 0.5 → 3.5 total ToolZ 10 people 0.1 each → 1.0 total

Step 1 — Calculate QF scores:

LibraryX: (50 × √0.01)² = (50 × 0.1)² = 5² = 25

ProtocolY: (√2 + √1 + √0.5)² ≈ (1.414 + 1 + 0.707)² ≈ 3.121² ≈ 9.74

ToolZ: (10 × √0.1)² = (10 × 0.316)² ≈ 3.16² ≈ 9.99

Step 2 — Calculate alpha (total QF score ≈ 44.73, total direct = 5 ETH, pool = 10 ETH):

α = (10 − 5) / (44.73 − 5) ≈ 5 / 39.73 ≈ 0.1259

Step 3 — Apply CQF formula:

LibraryX: 0.1259 × 25 + (1 − 0.1259) × 0.5 ≈ 3.15 + 0.44 ≈ 3.59 ETH

ProtocolY: 0.1259 × 9.74 + 0.8741 × 3.5 ≈ 1.23 + 3.06 ≈ 4.29 ETH

ToolZ: 0.1259 × 9.99 + 0.8741 × 1.0 ≈ 1.26 + 0.87 ≈ 2.13 ETH

Total distributed: 3.59 + 4.29 + 2.13 ≈ 10.01 ETH (rounding accounts for tiny discrepancy)

The key takeaway: LibraryX, despite having only 0.5 ETH in direct donations, the least of the three, receives the most matching because 50 people showed up for it. ProtocolY raised 7× more in direct donations, yet LibraryX wins the community signal contest. This is QF functioning as designed.

Bonus Mechanism — Assurance Contracts

One extension worth noting, especially relevant for high-fixed-cost public goods like infrastructure, is the assurance contract model (sometimes called “dominant assurance contracts”).

The problem: a project with a $100K fixed cost must raise the full amount to launch. Under standard QF, contributions might trickle in, but if only $40K is raised, the project can’t launch, and all contributors want their money back. This coordination failure discourages early contributions.

The solution: all-or-nothing thresholds. Contributions are held in escrow until a funding target is met. If the target is hit within the round, contributions are released and matching flows. If not, everyone is refunded.

This could be implemented in the contract by adding a minimumFundingThreshold to the Project struct and modifying withdrawProjectFunds() to check whether the threshold was reached before releasing funds.

Why This Matters Beyond Web3

Quadratic Funding is not merely a DeFi mechanism. It’s a proposal for a fundamentally different relationship between communities, resources, and public goods. one where:

A developer in Lagos building open infrastructure for Nigeria can receive meaningful funding if their community shows up, regardless of whether Silicon Valley VCs understand the problem.Minority communities with intense needs can outcompete majority interests with mild preferences.The system is mathematically neutral and non-authoritarian: the algorithm allocates based on revealed community preference, not committee decisions or donor politics.

Gitcoin Grants has run over 20 rounds using QF, distributing over $60M to open-source developers. The experiments have been messy, Sybil resistance remains imperfect, round design is an art as much as a science, but the fundamental insight holds: a community of small contributors can and should unlock more than a single large patron.

Conclusion

Quadratic Funding takes a beautiful mathematical insight, that the square root compresses the influence of wealth while preserving signals of preference intensity, and constructs from it a complete system for democratically allocating shared resources to public goods.

The formula Fₚ = (Σ√cᵢ)² is simple to write but rich in implications. It rewards breadth over depth. It amplifies community consensus. It punishes concentrated wealth. And, when constrained to a real budget via the CQF alpha parameter, it remains mathematically solvent while preserving its democratic character.

Building it in Solidity requires confronting concrete engineering challenges: integer-only arithmetic demands fixed-point precision scaling; Sybil resistance requires external identity infrastructure wired through a clean interface; capital constraints require a careful alpha calculation; and the 24KB bytecode limit demands architectural discipline.

The full implementation is available at github.com/damboy0/Quadratic-Fund. Explore the src/QF.sol file alongside this article to see theory become code.

Public goods are chronically underfunded, not because people don’t care about them, but because the systems we use to fund them don’t capture how much people care. Quadratic Funding is a genuine attempt to fix that, one square root at a time.

References

Buterin, V., Hitzig, Z., & Weyl, E. G. (2018). Liberal Radicalism: A Flexible Design for Philanthropic Matching Funds. Available at SSRN: https://ssrn.com/abstract=3243656Newbery, E. (2024). Quadratic Funding & Project Choice. Master’s Thesis: https://thesis.dial.uclouvain.be/bitstreams/5d51729c-e350-4fc2-a3f5-12c70fa80d13/downloadGitcoin Grants: gitcoin.co/grants — the primary real-world application of QF for open-source software.WTF is QF?: wtfisqf.com — an interactive simulator for visualising matching impacts.EIP-170: Contract code size limit — Ethereum Improvement Proposal that established the 24KB deployment ceiling: https://eips.ethereum.org/EIPS/eip-170

Quadratic Funding: The Mathematics Behind Fair Public Goods Financing was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

By

Leave a Reply

Your email address will not be published. Required fields are marked *