Skip to main content

ProperQF

Git Source

Title: Proper Quadratic Funding (QF) math and tallying

Author: Golem Foundation

Incremental QF tallying utilities with alpha-weighted quadratic/linear funding.

Provides storage isolation via deterministic slot, input validation helpers, and funding aggregation with well-defined rounding behavior.

Note: security-contact: [email protected]

State Variables

STORAGE_SLOT

Storage slot for ProperQF storage (ERC-7201 namespaced storage)

https://eips.ethereum.org/EIPS/eip-7201

bytes32 private constant STORAGE_SLOT =
bytes32(uint256(keccak256(abi.encode(uint256(keccak256(bytes("proper.qf.storage"))) - 1))) & ~uint256(0xff))

Functions

constructor

Constructor initializes default alpha values in storage

constructor() ;

_getProperQFStorage

Get the storage struct from the predefined slot

function _getProperQFStorage() internal pure returns (ProperQFStorage storage s);

Returns

NameTypeDescription
sProperQFStorageStorage struct containing all mutable state for ProperQF

projects

Returns project aggregated sums

function projects(uint256 projectId) public view returns (Project memory);

Parameters

NameTypeDescription
projectIduint256ID of the project to query

alphaNumerator

Returns alpha numerator

function alphaNumerator() public view returns (uint256);

alphaDenominator

Returns alpha denominator

function alphaDenominator() public view returns (uint256);

totalQuadraticSum

Returns total quadratic sum across all projects

function totalQuadraticSum() public view returns (uint256);

totalLinearSum

Returns total linear sum across all projects

function totalLinearSum() public view returns (uint256);

totalFunding

Returns alpha-weighted total funding across all projects

function totalFunding() public view returns (uint256);

_processVote

Process a vote and update the tally for the voting strategy

Implements incremental update quadratic funding algorithm with validations:

  • contribution > 0 (asset base units)
  • voteWeight > 0 and voteWeight^2 == contribution within 10% tolerance
function _processVote(uint256 projectId, uint256 contribution, uint256 voteWeight) internal virtual;

Parameters

NameTypeDescription
projectIduint256ID of project to update
contributionuint256Contribution to add in asset base units
voteWeightuint256Square root of contribution (dimensionless)

_processVoteUnchecked

Process vote without validation - for trusted callers who have already validated

Skips input validation for gas optimization when caller guarantees correctness

function _processVoteUnchecked(uint256 projectId, uint256 contribution, uint256 voteWeight) internal;

Parameters

NameTypeDescription
projectIduint256ID of project to update
contributionuint256Contribution amount (asset base units)
voteWeightuint256Vote weight (dimensionless; sqrt of contribution)

_calculateWeightedTotalFunding

Calculate alpha-weighted total funding across all projects

Rounding: per-project integer division makes sum(project funding) ≤ totalFunding. Discrepancy ε is bounded: 0 ≤ ε ≤ 2(|P|-1) where |P| is number of projects. This dust ensures no over-allocation; all funds are still fully distributed.

function _calculateWeightedTotalFunding() internal view returns (uint256);

Returns

NameTypeDescription
<none>uint256totalFunding_ Weighted total funding across all projects (asset base units)

getTally

Return current funding metrics for a specific project

Aggregates sums and computes alpha-weighted components on-demand.

Rounding: sum of per-project funding ≤ totalFunding() with small bounded dust ε.

function getTally(uint256 projectId)
public
view
returns (uint256 sumContributions, uint256 sumSquareRoots, uint256 quadraticFunding, uint256 linearFunding);

Parameters

NameTypeDescription
projectIduint256ID of project to tally

Returns

NameTypeDescription
sumContributionsuint256Total sum of contributions (asset base units)
sumSquareRootsuint256Sum of square roots of contributions (dimensionless)
quadraticFundinguint256Alpha-weighted quadratic funding: ⌊α × S_j²⌋ (asset base units)
linearFundinguint256Alpha-weighted linear funding: ⌊(1-α) × Sum_j⌋ (asset base units)

_setAlpha

Set alpha parameter determining ratio between quadratic and linear funding

function _setAlpha(uint256 newNumerator, uint256 newDenominator) internal;

Parameters

NameTypeDescription
newNumeratoruint256Numerator of new alpha (0 ≤ numerator ≤ denominator)
newDenominatoruint256Denominator of new alpha (> 0)

getAlpha

Get current alpha ratio components

function getAlpha() public view returns (uint256, uint256);

Returns

NameTypeDescription
<none>uint256numerator Current alpha numerator
<none>uint256denominator Current alpha denominator

_calculateOptimalAlpha

Calculate optimal alpha for 1:1 shares-to-assets ratio given fixed matching pool amount

Solve α where: α × totalQuadraticSum + (1−α) × totalLinearSum = totalUserDeposits + matchingPoolAmount

function _calculateOptimalAlpha(
uint256 matchingPoolAmount,
uint256 quadraticSum,
uint256 linearSum,
uint256 totalUserDeposits
) internal pure returns (uint256 optimalAlphaNumerator, uint256 optimalAlphaDenominator);

Parameters

NameTypeDescription
matchingPoolAmountuint256Matching pool amount (asset base units)
quadraticSumuint256Total quadratic sum across all proposals (dimensionless)
linearSumuint256Total linear sum across all proposals (asset base units)
totalUserDepositsuint256Total user deposits in the mechanism (asset base units)

Returns

NameTypeDescription
optimalAlphaNumeratoruint256Calculated alpha numerator
optimalAlphaDenominatoruint256Calculated alpha denominator

Events

AlphaUpdated

Emitted when alpha parameters are updated

event AlphaUpdated(uint256 oldNumerator, uint256 oldDenominator, uint256 newNumerator, uint256 newDenominator);

Parameters

NameTypeDescription
oldNumeratoruint256Previous alpha numerator
oldDenominatoruint256Previous alpha denominator
newNumeratoruint256New alpha numerator
newDenominatoruint256New alpha denominator

Errors

ContributionMustBePositive

error ContributionMustBePositive();

VoteWeightMustBePositive

error VoteWeightMustBePositive();

VoteWeightOverflow

error VoteWeightOverflow();

SquareRootTooLarge

error SquareRootTooLarge();

VoteWeightOutsideTolerance

error VoteWeightOutsideTolerance();

QuadraticSumUnderflow

error QuadraticSumUnderflow();

LinearSumUnderflow

error LinearSumUnderflow();

DenominatorMustBePositive

error DenominatorMustBePositive();

AlphaMustBeLessOrEqualToOne

error AlphaMustBeLessOrEqualToOne();

Structs

Project

Per-project aggregated sums

struct Project {
/// @notice Sum of contributions for this project (asset base units)
uint256 sumContributions;
/// @notice Sum of square roots of all contributions (dimensionless)
uint256 sumSquareRoots;
}

ProperQFStorage

Main storage struct containing all mutable state for ProperQF

struct ProperQFStorage {
/// @notice Mapping of project IDs to project data
mapping(uint256 => Project) projects;
/// @notice Numerator for alpha (dimensionless; 1.0 = denominator)
uint256 alphaNumerator;
/// @notice Denominator for alpha (must be > 0)
uint256 alphaDenominator;
/// @notice Sum of all quadratic terms across projects (dimensionless squared weights)
uint256 totalQuadraticSum;
/// @notice Sum of all linear contributions across projects (asset base units)
uint256 totalLinearSum;
/// @notice Alpha-weighted total funding across all projects (asset base units)
/// @dev Uses uint256 for precision in calculations
uint256 totalFunding;
}