Varve
A share price is assets over supply. The supply is in the log forever; the assets are in a storage slot this chain forgets in 10.2 minutes. Exactly one half of your own return survives — so Varve writes the other half down while it is still true.
What the chain can still tell you
49 live ERC-4626 vaults, 4.7 days of blocks
The problem
One number is in the log. The other one isn’t
A share price is totalAssets / totalSupply. Every change in the supply emits a
Transfer, so the denominator is reconstructible for ever from any node. The numerator moves
when income arrives, when a loss is taken, when a fee is charged — and ERC-4626 defines no event for
any of them.
Every other vault
A price you had to be watching
totalSupply: complete, from theTransferlog, at any past block.totalAssets: a storage slot, and this chain keeps storage for 10.2 minutes.- Nothing fires when the vault earns. Nothing fires when it loses.
- So the only prices in the record are the instants somebody happened to transact.
Varve
A record laid down as it happens
- Every mutation writes a
Layercarrying assets, supply and the kind of move. - Income and markdown are kinds of their own, so a reader can tell them apart.
chronology()is one word committing to the entire series, in order.- Replay the logs, recompute the word, compare. No archive node anywhere.
The measurement
Measured on Robinhood Chain, not argued
52 addresses emitted an ERC-4626 Deposit across 60
windows covering 2.07% of the chain. A topic match is a candidate, not an identity, so each was
asked for the whole interface: 49 answered and are counted, 3 did not and are not. Every
figure below is over one common 4.7-day window, the same one the control uses.
The control
Does any vault log its own mark?
“No vault logs its price” would be a flattering thing to find and a wrong one if any of them does, so every distinct topic each vault emits was read and matched against a dictionary of real vault events. 10 of 49 emit something of their own, across 30 distinct topics — and exactly 1 of them emits one that carries the mark.
One vault out of 49
It is aRHUSDG, and the event is MetaMorpho’s UpdateLastTotalAssets(uint256) — which carries exactly the number ERC-4626 has no event for.
And it bought almost nothing
That event adds 1 block of coverage on top of the 72 the vault already had from ordinary traffic. It is simply a busy vault. Saying the event is what made it legible would be the flattering version.
The standard is still the hole
The finding is not that implementations are careless. It is that 48 of 49 add no such event, because nothing asks them to — and 20 of those pin no price at all in 4.7 days.
The other control
The same chain, done right
A Uniswap V3 pool’s price changes only when it trades, and every trade logs the price it left behind. 598,889 swaps over 150,000 blocks in 2,659 pools, inside the same window — so a pool’s price history is complete for ever and a vault’s is not, on the same node, in the same blocks. That is why this is a finding about a standard rather than about a chain.
What Varve does
Three things, and one word that proves them
An ordinary ERC-4626 vault with no strategy, no upgrade path, no owner who can move the assets and no fee. What it adds is the record.
A layer per move
Deposit, withdraw, income and markdown each write one Layer carrying the vault’s assets and supply at that block. Those two numbers are the share price, exactly, with no division done by the writer.
- Four kinds, so income is distinguishable from a deposit
- A genesis layer, so the series has a start
- A no-op writes nothing
A word for the whole series
chronology() is a running commitment to every layer in order. Replay the logs, recompute it, compare. A missing layer, a reordered one or an invented one all give a different word.
- One storage slot audits an unbounded history
- Readable now, about a past the chain has dropped
- Executed as properties 3, 4 and 5
Nothing else to trust
Assets sit in the contract. Income arrives by transfer and anyone may book it. The one trusted entry point is disabled outright when the steward is the zero address, which is what the app deploys.
- Tracked accounting, so a donation is not a price move
- Reentrancy guard, tested with an attack that fires
- Credits what arrived, not what was asked for
Why a varve
A record that cannot be written afterwards
A varve is the couplet of sediment a lake lays down in one year: pale silt in the meltwater season, dark organic mud under the ice. Count them and you have a calendar. The Lake Suigetsu core is read back more than 50,000 years and calibrates radiocarbon dating for everyone, and it works for exactly one reason — every layer was laid down at the time. Nothing reconstructs a missing year.
That is the whole design. A vault that did not write its price down while the price was true cannot produce it later, however much anybody wants it.
The contract
Executed, not described
29 properties run on Robinhood Chain's own EVM through eth_call with no to —
no testnet, no fork, no funded account, no key. Then the contract is recompiled with one deliberate
defect at a time and each must be caught by a specific, related property.
Questions
The obvious objections
Does a Deposit event not already tell you the price?
Yes, and that is the honest version of the finding. Deposit(sender, owner, assets, shares)
pins the conversion rate at that instant, so a vault’s price is recoverable at the blocks where
somebody entered or left. What it cannot tell you is the price at any other moment — and those are the
moments you actually want, because they are the ones where you were holding and nobody transacted.
Measured: the median vault has a recoverable price on 0.0000% of the blocks in a common 4.7-day window.
Is this not just a pruned node? Run an archive one.
You can, and then the answer depends on who runs it. An event is part of the chain’s own record and every node that syncs carries it; a historical state read is a service somebody chooses to offer. The public endpoint for this chain does not offer it past about 10.2 minutes, which is what makes the difference visible rather than theoretical.
Why not just index the vault yourself?
Then the history exists as long as your indexer does, and a reader has to trust it. chronology()
is the difference: one word, in the contract, that any reader can compare their reconstruction against.
An indexer that dropped a layer is indistinguishable from an honest one until you have that word.
What is actually deployed?
Nothing, by this repository. /app deploys a vault from your wallet in one transaction; the site
holds no key and there is no canonical instance. The state page says which part of this is
which, one row at a time, rather than putting a blanket disclaimer at the bottom.