"For each node on the graph, the cryptographic network randomly selects a committee, that makes the decision of what weights the edges right below that node get."
Snowmoon, chapter 17
Graph Funding is the public-goods funding system from Snowmoon, the novel by Vitalik Buterin, built for real on Ethereum. Trading fees from the $GRAPHFUND token flow into a tree of Ethereum public goods. At every fork of the tree, a small committee drawn at random decides how the money splits. Nobody ever votes on the whole budget.
Note
Not affiliated with Vitalik Buterin. Lore from Snowmoon (GPL v3). Unaudited code, volatile token, no promises.
| ๐ธ Money in | ๐ณ The tree | ๐ฒ The committees |
|---|---|---|
| Every $GRAPHFUND trade pays a 2% fee. Half of it is claimed straight into the contract. | Four branches, fourteen Ethereum public goods. The money climbs down from the trunk to the leaves. | At every fork, five Keepers drawn at random set the split. Every six hours the money moves. |
- Enlist. Lock at least 100,000 $GRAPHFUND. Your chance of being drawn is your share of everything locked.
- Drawn. The hash of a future block picks five Keepers for every fork. Nobody knows who in advance.
- Vote. Each Keeper proposes how the money below their fork should split. The median wins, so one bad vote moves nothing, and no share moves more than 5 points per epoch, so no single committee can hijack a fork. Voting mints a soulbound Keeper badge.
- Flow. Every six hours the epoch closes and the money climbs down the tree. Keepers who voted on a fork share 2% of what flowed through it.
One epoch, as the contracts see it
flowchart LR
D["draw()<br/>five Keepers per fork,<br/>weighted by stake"] --> V["vote()<br/>each Keeper sends a split<br/>and gets a soulbound badge"]
V --> A["advance()<br/>median per fork (max 5 pts a move),<br/>money moves down, 2% to the voters,<br/>next draw requested"]
A -- "6 hours later" --> D
classDef step fill:#f3ebdd,stroke:#2b59c3,stroke-width:2px,color:#2b59c3
classDef hot fill:#ff6b1a,stroke:#ff6b1a,color:#ffffff
class D,V step
class A hot
draw() and advance() can be called by anyone; a small bot calls them on time. Recipients pull their money with
payout(address).
$GRAPHFUND trades on Stockereum with a 2% fee: 1% goes to the platform, 1% waits in the
creator wallet's escrow. The creator wallet claims it with FeeEscrow.claim(WETH, GraphFund), so it goes from the
escrow straight into this contract. Every claim is public on Etherscan. Anyone can also send ETH to the contract.
The starting weights, before any committee has voted. From the first epoch on, the committees decide, 5 points per epoch at most.
| Branch | Recipient | Inside the branch | Of every ETHยน |
|---|---|---|---|
| ๐ ๏ธ Core protocol 40% of the tree | Protocol Guild | 55% | 22% |
| Lighthouse | 15% | 6% | |
| Nimbus | 15% | 6% | |
| Lodestar | 15% | 6% | |
| ๐ถ๏ธ Privacy 20% of the tree | Tor Project | 34% | 6.8% |
| Web3Privacy Now | 33% | 6.6% | |
| Whonix | 33% | 6.6% | |
| ๐ก๏ธ Security 20% of the tree | Revoke.cash | 34% | 6.8% |
| SEAL 911 | 33% | 6.6% | |
| DeFiHackLabs | 33% | 6.6% | |
| ๐ Open tooling & data 20% of the tree | L2BEAT | 25% | 5% |
| growthepie | 25% | 5% | |
| Otterscan | 25% | 5% | |
| rotki | 25% | 5% |
ยน At genesis. Once Keepers vote, each fork they voted on keeps 2% for them. Each name links to its address on Etherscan.
Important
Recipients, not partners. None of these projects has endorsed Graph Funding. Each address was read from the project's own donation page and checked on-chain: see docs/recipients.md. The tree itself lives in contracts/script/genesis.json.
New projects can join. Anyone can propose a project under a branch with a deposit of 1,000,000 $GRAPHFUND. It enters at 0%, gains at most 5 points per epoch, and only gets money if a committee gives it weight; the deposit comes back the first time it does.
| Can | Cannot | |
|---|---|---|
| Keepers | Lock $GRAPHFUND, vote on the fork they were drawn for, leave the draw and unlock | Unlock while sitting on a committee |
| Anyone | Call draw() and advance(), send ETH, propose a project, trigger payout for a recipient |
Choose who gets drawn |
| Owner (until renounced) | Edit the tree and the starting weights, change parameters within fixed bounds, reject spam proposals | Touch anyone's stake, touch money owed to a project, choose who gets drawn |
The owner renounces after 28 epochs (7 days) with committees drawn and no emergency changes.
| Contract | What it does |
|---|---|
GraphFund |
The tree, the epochs (draw โ vote โ advance), the payouts (ETH, or WETH to contracts that refuse ETH) and the proposals |
KeeperStaking |
Lock $GRAPHFUND (minimum 100,000) to enter the draw. Stakes can't change while a draw is pending (minutes; if nobody draws, anyone can end it with draw()), and stay locked while you sit on a committee. To exit: leave() takes you out of every future draw, then unstake as soon as your seat ends |
KeeperBadge |
One soulbound token per epoch you voted in |
| $GRAPHFUND | 1,000,000,000 fixed supply, launched on Stockereum |
Addresses go here, and on the site, the moment they are deployed.
- โ๏ธ Stake buys seats. Seats are drawn in proportion to what is locked: whoever locks most of the supply wins most seats. The median protects a fork's split only while no one holds three of its five seats, and even a captured committee moves each share at most 5 points per epoch. Every seat and every vote is public.
- ๐ฒ Randomness is a future blockhash. Whoever builds that block (a role that can be bought for a single slot) can grind its hash and pick a committee. The 5-point cap is the answer: capturing one committee pays little, and honest committees undo it at the same speed. Verifiable randomness (e.g. a VRF) would close it for good.
- ๐ The fee claim depends on the creator wallet. Claims into the contract are public, but someone has to make them.
- โฝ One transaction draws every committee. Parameters are bounded (
committeeSize ร maxNodes/2 โค 120) so the worst case stays well under Ethereum's per-transaction gas cap. - ๐งช Not audited yet. The code is open source and tested.
- Contracts: staking, the tree, epochs, payouts, proposals, badges
- Unit and fuzz tests, plus a worst-case gas test
- Site live at graphfunding.app
- Mainnet-fork test against the real Stockereum (launch โ trades โ fees โ leaves)
- Deploy and genesis scripts, the keeper bot and CI
- Deploy the contracts and launch $GRAPHFUND
- First epoch, then one every six hours
- Owner renounces after 28 clean epochs
contracts/src/ GraphFund, KeeperStaking, KeeperBadge
contracts/test/ unit, fuzz, worst-case gas and mainnet-fork tests
contracts/script/ Deploy, Genesis and genesis.json: the starting tree
ops/keeper/ the keeper bot: calls draw() and advance() on time
.github/workflows/ contract tests on every push + the keeper, every 15 minutes
web/ graphfunding.app (Vite + TypeScript + viem)
brand/ the X kit, the README header and the image pipeline
docs/recipients.md where every recipient address comes from
cd contracts
forge test # unit + fuzz
FOUNDRY_PROFILE=gas forge test --match-contract GraphFundFixesTest -vv # worst-case gas, isolated
MAINNET_RPC_URL=<rpc> forge test --match-contract StockereumForkTest -vv # the real Stockereum, on a fork
cd ../web
npm install && npm run dev # the siteNobody has to be trusted to move the money: draw() and advance() are open to anyone. This repo runs a small bot
on GitHub Actions every 15 minutes (ops/keeper); its wallet only pays gas. Anyone can run
another one:
cd ops/keeper && npm install
RPC_URL=<rpc> GRAPHFUND_ADDRESS=<GraphFund> DRY_RUN=1 node keeper.mjs # prints what it would do; drop DRY_RUN and
# set KEEPER_PRIVATE_KEY to send itThe illustrations are risograph prints generated from the book's world; every letter on top of them is HTML with real fonts. Snowmoon's license asks derivative works to publish their pipeline, so the prompts and curation scripts are in brand/pipeline.
GPL-3.0, like the book.



