Skip to content

Repository files navigation

ETH Security QF Calculator

A standalone simulator that lets anyone explore how different QF calculation settings reshape matching outcomes for the ETH Security QF round.

Built by TheDAO, powered by Giveth's QF stack. Quantstamp and CertiK are featured as major round donors.

The dashboard is a single-page Next.js 16 app that runs entirely in the browser — no analytics, no per-user backend, no donor PII.

Provide the dataset

The app expects a CSV at public/data.csv. This file is fetched at runtime by the dashboard and never leaves the browser.

The CSV must include (at minimum):

Column Purpose
project_name Project display name and grouping key.
donor_label Donor identifier. Accepted aliases: userId, donor_id, donor.
amount_usd USD value of the donation. Accepted aliases: amountUSD, amount usd.
currency Currency code, e.g. USDC, ETH, TIK.
amount_native Native token amount (used to display CertiK Tokens received).
isBadgeholder Boolean flag — was the donor a badge holder at donation time.
isMatchingIncluded Boolean flag — does this donation pass the round's sybil / humanness check.

Aliases are matched case-insensitively. Additional columns are ignored.

PII guardrail

The loader refuses to start if the CSV still contains non-empty values in any of these forbidden columns:

  • email
  • voter
  • payoutAddress
  • safeTransactionId
  • tokenAddress
  • recurringDonationId

Scrub these before exporting. If the donor column upstream is a raw wallet address, the loader will deterministically remap it to opaque labels (Donor 1, Donor 2, …) at load time.

Run locally

npm install
npm run dev

Open http://localhost:3000. If public/data.csv is missing or mis-shaped, the error state explains what to fix.

What the simulator covers

  • Algorithms: Regular QF and COCM (Markov style, harsh mode OFF). Both are direct ports of fundingutils.py from the v6 calculator.
  • Badge holder boost: Off (1×) or 4× multiplier on every badge holder donation that enters the QF math.
  • Sybil / humanness: Toggle between "all donors qualify" and "QF-eligible only" (isMatchingIncluded).
  • Matching limits: None · 5% per-project cap · 0.333 ETH per-project floor · both. Cap is applied first, then the floor is funded by surplus from non-capped projects above the floor — identical to apply_max_first_then_surplus_floor in the Python.
  • Anti-gaming: 80% cap per donor per project, applied as the very first pre-processing step. Excess is discarded.
  • CertiK Tokens (TIK): Own column, sortable. Plus a "TIK only" toggle to see what the distribution looks like if only TIK donations counted.
  • Comparison: Side-by-side scenarios with a Δ% column per project.

Architecture

src/
  app/                Next 16 routing + theme
  components/         Dashboard, ScenarioPanel, ResultsTable, branding, Footer
  lib/
    csv.ts            Minimal CSV parser
    loader.ts         Fetch /data.csv + PII guardrail + donor abstraction
    eth.ts            getETHPrice() — currently returns a fixed $2150
    types.ts          Donation, Settings, RoundConfig, ScenarioResult
    qf/
      matrix.ts            Sparse donation matrix
      standardQf.ts        Regular QF
      cocm.ts              COCM (Markov, harsh togglable)
      matchingLimits.ts    apply_max_first_then_surplus_floor port
      runner.ts            Pipeline orchestration

All matching math runs in the main thread. With a 120-project / 10k-donation dataset the typical end-to-end compute for COCM is well under a second on a modern laptop; the dashboard shows a "Computing…" banner while it runs.

Algorithm parity vs. fundingutils.py

  • standard_qfstandardQf — direct port (sum of sqrt minus sum).
  • COCM (calcstyle='markov', harsh=False)cocm — direct port with sparse optimisations for browser performance. Cluster dataframe is identified with the donation dataframe (same convention as the v6 calculator).
  • apply_max_first_then_surplus_floorapplyMaxFirstThenSurplusFloor — byte-for-byte translation including epsilon checks and infeasibility errors.

If the cap/floor combination is infeasible the runner falls back to a no-cap, no-floor distribution and surfaces the reason as a scenario warning instead of crashing the dashboard.

Deploying

npm run build then npm start. Static hosts work fine — the only runtime requirement is that /data.csv is served alongside the bundle. Set the getETHPrice() value in src/lib/eth.ts (currently 2150) when you want a live feed.

About

Result dashboard for QF rounds hosted on Giveth

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages