documentation
Every fee opens a tab.
The tab is settled while you hold.
This is the whole mechanism, the whole reading path, and every number that can be changed. If something on the site is not explained here, that is a bug in this page.
The idea
A holder-rewards distribution usually reads everyone’s balance at one moment and splits a pot by what it saw. That asks people to be holding at an instant, which makes the optimal play buy-just-before and sell-just-after, and the reader cannot tell a month of holding from thirty seconds of it.
This measures something the reader already has and nobody uses: what you spent. Every trade pays a fee. That fee opens a tab in your name. The distribution pays your tab back down while you keep holding, and stops while you don’t.
The consequence worth stating plainly: a wallet can never draw out more than it has paid in. Not as a rule anyone enforces — as the shape of the thing. That single fact removes almost every attack on a distribution before it needs a rule.
The three numbers
| paid | Every fee this wallet has spent on this token, in wei. Monotone — it only goes up. It is the ceiling on everything that can ever come back. |
|---|---|
| drawn | How much of that has already been returned, summed from every
published epoch. Never exceeds paid; the code refuses to write a draw
that would. |
| open | paid − drawn. The tab. When it reaches zero the tab is
closed and takes nothing further until the wallet trades again. |
And one ratio that decides how fast a tab is drawn down:
held = min(1, balance_now / tokens_ever_bought)
Hold everything you bought and you draw at full weight. Sell half, draw at half. Sell it all and you draw nothing — but the tab stays open, because you did pay those fees and they are still yours if you come back.
Tokens that arrive by plain transfer count toward balance but not toward
bought, and held is capped at 1, so sending yourself tokens
cannot push you past full and cannot open a tab. No fee, no tab.
Weight and ceiling
Two separate things, deliberately kept apart.
weight = open × held // how big your share of the pot is ceiling = open × DRAW_RATE // the most you can be handed this epoch
DRAW_RATE is 2500 basis points — a quarter. So a tab takes at least four
epochs of continuous holding to settle in full, and stops the moment the holding does.
Without that, a holder gets the whole fee back the week they buy and then has no reason
left to be here: a rebate, but not a reason to hold.
The ceiling is deliberately not scaled by retention. That is what makes the waterfall do real work — a wallet holding everything weighs the most against its own ceiling, so it fills first, and what it cannot take runs sideways.
Weight is linear in both terms. Two wallets holding half a bag each weigh precisely what one wallet holding the whole bag weighs. Splitting across addresses gains nothing, so nothing here goes looking for people who have — and no innocent wallet gets caught by a heuristic that guesses wrong.
The waterfall
One round would be a division. The ceilings make it a cascade:
- Divide what is left in proportion to weight, across everyone still under their ceiling.
- Anyone whose share would reach their ceiling takes exactly their ceiling and drops out.
- If anyone dropped out, go again with what remains and whoever is left.
- When a round caps nobody, that division stands and the epoch is done.
It always terminates: every round that caps somebody removes at least one wallet. If the pot outlasts every ceiling, what is left rolls into the next epoch rather than being forced on anyone.
The animation on the front page is this routine, run in the browser at a hundred pot sizes over the live standing. It is not a drawing of the algorithm; it is the algorithm.
Remainders and dust
Everything is integer wei. Nothing in the path touches a float — at eighteen decimals a float64 stops being able to count individual units somewhere above 0.009 of a token, and being wrong in the ninth decimal place is how you end up in somebody’s screenshot.
Integer division leaves a remainder. It is handed out by largest remainder, with the address as a deterministic tiebreak, so two people running this get byte-identical files.
Some payments come out smaller than the gas needed to send them. Those are not paid and not kept: they are named in the ledger and roll into the next pot, with the tab left open, so a small holder accumulates instead of getting nothing forever.
paid + rollover === pot
Asserted before anything is published, and over four hundred randomly generated epochs in the test suite. An epoch that does not balance to the wei refuses to publish at all.
What it survives
| wash trading | Every round trip costs two full fees and returns a fraction of one, and it leaves the wallet holding nothing, which sets its weight to zero. The return rate is printed on the front page, computed from the epoch, and is always under one. |
|---|---|
| splitting across wallets | Weight is linear. Two halves weigh what one whole weighs. Nothing gained, so nothing policed. |
| buying just before close | Works, and is fine. You paid the fee; you get part of that fee back, bounded by what you spent. There is no snapshot to stand on because the reward is not a share of a prize — it is a discount on your own bill. |
| airdrops in | No fee was paid, so no tab opens. held is capped
at 1, so topping a wallet up cannot push it past full. |
| shuffling between your own wallets | Keeps a tab’s retention alive, and gains nothing: the cap is on fees paid, not on wallets, and the tokens had to be bought by somebody who paid a fee to get them. |
What it reads, and what it can’t
Balances are rebuilt from Transfer logs, which are deltas, not
balances. Miss one log and the number is wrong forever and nothing inside the
reconstruction would ever notice.
So every wallet is checked against a live balanceOf before anyone is paid.
A wallet whose reconstruction disagrees with the chain is held back — named in the
ledger, paid nothing that epoch — rather than paid on a number nobody can stand behind.
A transfer with the pool on one side is a trade. A transfer between two ordinary wallets is not, and opens no tab.
What a Transfer log does not carry is the price. The cost of a trade is the
other side of the same transaction — the fee asset moving in or out of the pool — so the
reader groups those by transaction hash to get each trade’s ETH leg. The rate that turns
a leg into a fee is FEE_BPS, a stated setting, printed on the page as a
setting. Nothing pretends to have read it off the venue.
Where the pot comes from
The pot is whatever has actually arrived at the treasury address. Every claim counted is
a transaction that was looked up, with its to checked against the treasury.
A claim that does not land at that address is not counted, whoever says otherwise.
Outgoing payments are never counted — only what arrives.
| fee asset transfers | Fees paid in WETH or another token: Transfer
logs into the treasury. Exact, cheap and complete. The good case. |
|---|---|
| native transfers | A block scan for transactions paying the treasury. Value forwarded inside a contract call does not appear in a block’s transaction list, so this mode reports itself as incomplete rather than quietly under-counting. |
| claim list | A curated list of claim hashes, each verified on chain: exists, did not revert, pays the treasury, moves value. The fallback that always works. |
It is not money from new buyers. There is nothing to stake, nothing to lock, nothing to bond, and no contract that holds anyone’s tokens. A mechanism that pays existing holders out of incoming buyers’ money is a Ponzi regardless of how elegant the weighting is.
The ledger
State is not a database. It is the stack of closed epochs, and the running total of what each wallet has drawn is recomputed from them on every boot. An epoch is published once; a correction is a new epoch with a note, not a quiet edit to an old one.
The ledger goes up before the money moves, so anyone who saved a copy can hold it against the payment transactions afterwards. Every wallet that was considered is in it, including the ones paid nothing, and why:
| tab settled in full | everything that wallet paid has come back |
|---|---|
| reached this epoch ceiling | took its quarter; more is available next epoch |
| sold out, tab open but drawing nothing | holds none of what it bought |
| under the send floor, rolled forward | smaller than the gas to send it |
| held back: balance disagreed with chain | reconstruction failed the check |
Settings
| RPC_URL | JSON-RPC endpoint. Read from the environment at boot. No request can influence it — an endpoint that fetches a URL somebody handed it is an SSRF with better manners, and there is no flag to turn the guard off. |
|---|---|
| TOKEN | the coin |
| POOL | the pair it trades against |
| TREASURY | the address creator fees are claimed to |
| FEE_ASSET | the asset fees are paid in, or the word native |
| FEE_BPS | the venue’s swap fee in basis points. Stated, not read. |
| FROM_BLOCK | the block the token was created in |
| CLAIM_TXS | optional comma-separated claim hashes, each verified on chain |
| LEDGER_DIR | where closed epochs live. Default ./ledgers |
| EPOCH_DAYS | how often an epoch closes. Default 7 |
| MIN_PAY | the send floor in wei. Below it, a payment rolls instead |
| TRUST_PROXY | 1 only behind a proxy you control |
And two constants in the source rather than the environment, because changing them
changes what the mechanism is and that should be a commit, not a deploy flag:
DRAW_RATE = 2500 and the linear weighting.
The API
GET only. A POST gets a 405 and nothing else. Amounts travel as exact decimal strings alongside their raw wei, never as JSON numbers.
| /api/epoch | the open epoch: pot, source, every claim transaction, the full standing, the waterfall’s round count, and whether it balances |
|---|---|
| /api/tab?addr= | one wallet: fees paid, already back, open tab, ceiling, retention, what this epoch pays it, and its rank |
| /api/token | market figures, labelled as read from a public venue; fees claimed, distributed and rolling |
| /api/ledger.csv | the ledger as a file |
| /healthz | ok |
No lookup is written to disk. There is no route that takes free text and returns generated text, and none that can be made to fetch something on a caller’s behalf.
Running it
node test-tab.mjs # the book and the waterfall node test-http.mjs # the routes, and the promises the source has to keep node dev.js # local preview, invented history, real engine RPC_URL=… TOKEN=… POOL=… TREASURY=… FEE_ASSET=… FEE_BPS=… FROM_BLOCK=… \ node live.js # the deployment node close.js 2026-09-05 → ledgers/2026-09-05.json replayed by the next epoch → out/…-ledger.csv the human-readable record → out/…-pay.csv address, amount — for your own wallet
Zero dependencies. Node’s standard library and nothing else. The page loads no font and no script from anybody else, because a page that says it is not tracking you and then calls a CDN has broken that promise before it finishes rendering.
What it holds
Nothing.
No keys. No signing. No connect-wallet button, no account, no record of who looked up what. There is no route in this codebase that can spend anything, and the test suite greps its own source for private keys, seed phrases and signing calls and fails the build if it finds one.
close.js writes a file. A person sends the payments from their own wallet,
on their own machine. That is deliberately unglamorous: every custody disaster in this
category started with something that did it for them.
Known edges
- The fee rate is a setting. Per-trade cost is the ETH leg times
FEE_BPS. If that rate is wrong, every tab is wrong by the same factor — relative shares are unaffected, but the ceilings are not. Check it against a real swap before the first epoch closes. - Native pairs cannot be attributed without a trace API. See above.
- A native fee scan is incomplete where a contract forwards value mid-call. Use a claim list when that applies.
- Sells are charged to the seller. A fee paid on the way out opens a tab like any other. That is intentional: it is still money that wallet spent.
- A wallet that sells everything keeps its tab open forever. It draws nothing while it holds nothing, and resumes if it buys back. There is no expiry, and that is a choice — an expiry would be a rule people would have to trust rather than read.
- Pool and treasury addresses are excluded from the standing. They are configured, not detected.
Rewards depend on fees earned. Nothing here is financial advice.