The flood
A basin collects for hours.
The gauge sees one pulse.
Rain falls over a whole catchment, quietly, everywhere at once. The gauge at the mouth records a flood some hours later. Nobody thinks the flood is when the rain fell.
A liquidity vault is the same shape and is read the other way round. Fee income accrues across
the pool continuously; the vault learns about it in one harvest transaction; and the share price —
the only number anybody reads — moves at the gauge rather than in the catchment.
Measured on Robinhood Chain
Income does not trickle in
Every Uniswap V3 Swap over a contiguous window of
30,000 blocks — about 0.84 hours at this
chain's 0.101-second blocks — read straight from the node with no key, no vendor and no proxy.
176,526 swaps across 1,209 pools.
Each swap's fee is computed from the amounts carried in the event itself and the pool's own fee tier. There are no prices anywhere in this measurement: income is measured per pool, in that pool's own input token, and every figure published is a share — a quantity a price cannot change. This chain has no oracle, and a dollar figure here would be the least reliable number on the page.
One number is missing on purpose. How long you must hold before your realised income is within 10% of the pool's own mean rate did not fit inside the window for any of the 40 pools measured. The honest report of a censored statistic is that it was censored, not the censoring bound printed as though it were the answer.
What it costs
One block of standing there
The sequence below is executed against the compiled contract on Robinhood Chain, twice: once with instant recognition, once with the unlock on. Nothing is arithmetic on paper. executed
The sequence
- A vault has been running and holds 1,000,000 units.
- A depositor arrives with an amount equal to the vault, one block before a harvest.
- A harvest of 1% of TVL lands.
- 1 block later, the depositor leaves.
It is run twice more, with and without the visitor, so what the standing holder loses is a real counterfactual on the same contract at the same blocks — not the visitor's gain asserted to be somebody's loss.
unlockBlocks is 36,000The two share prices
unlockBlocks set. Both end in exactly the same place — that is
P11 on the contract page, and it is checked on chain rather than drawn.Every row executed
| Harvest | Visitor | Instant (bps) | Unlocked (bps) | Ratio |
|---|---|---|---|---|
| 0.05% of TVL | 0.1x TVL | 4.55 | 0.000126 | 36,018× |
| 0.05% of TVL | 1x TVL | 2.50 | 0.000069 | 36,007× |
| 0.05% of TVL | 5x TVL | 0.83 | 0.000023 | 36,013× |
| 0.25% of TVL | 0.1x TVL | 22.73 | 0.000631 | 36,001× |
| 0.25% of TVL | 1x TVL | 12.50 | 0.000347 | 36,001× |
| 0.25% of TVL | 5x TVL | 4.17 | 0.000116 | 36,003× |
| 1% of TVL | 0.1x TVL | 90.91 | 0.002525 | 36,001× |
| 1% of TVL | 1x TVL | 50.00 | 0.001389 | 36,000× |
| 1% of TVL | 5x TVL | 16.67 | 0.000463 | 36,000× |
A smaller visitor takes more per unit of its own stake, because it dilutes the existing holders less on the way in. The largest single arrival is not the worst case for the arriver — it is the worst case for everyone else.
And the part that is not a fix
| Harvest | Dwell | Instant (bps) | Unlocked (bps) | Ratio |
|---|---|---|---|---|
| 1% of TVL | 1 block | 50.00 | 0.001389 | 36,000× |
| 1% of TVL | 600 blocks (~1 min) | 50.00 | 0.833333 | 60× |
| 1% of TVL | 3,600 blocks (~6 min) | 50.00 | 5.0000 | 10× |
| 1% of TVL | 36000 blocks (the whole unlock) | 50.00 | 50.0000 | 1× |
Where this comes from
Bond markets settled this in the seventeenth century
A bond quotes a clean price and settles at a dirty price: clean plus the interest accrued since the last coupon. The reason is exactly the one above. If it settled clean, whoever held the bond on the coupon date would take the entire coupon and everyone who sold the day before would get none of the interest they had genuinely earned — so the price would jump on the coupon date and the day before it would be worth trading.
An ERC-4626 vault quotes one price, and it is the clean one. totalAssets() counts what has landed.
Spate keeps the same single price and moves the accrual into the contract instead: harvested income is credited
over the interval rather than at the instant it arrives, so the number the vault publishes is already the dirty
one. dirtyPricePerShare() is a public view beside it, so the gap is visible rather than argued about.
This is not a new idea in DeFi either — a linear profit unlock is the standard fix and several vault frameworks ship one. What is unusual is publishing what it is worth, with the sequence executed, and admitting that the mechanism prices the capture by time rather than abolishing it.