What a price actually did
Every volatility figure in this market is somebody's publication. This one is a computation — done by the contract, from the chain's own record. We built it, then spent longer trying to break it than building it. These are the numbers that came back.
Everyone trades it. Everyone takes someone's word for it.
Realized volatility is not unmeasured. Volmex has published EVRV and BVRV since 2023, recomputed every minute from one-minute squared log returns. Deribit runs DVOL. CME lists a Bitcoin variance index. The number exists, in several versions, from several vendors.
Every one of them arrives the same way: a party computes it off chain and publishes the result. To use any of them in a contract you have to accept the publisher's arithmetic, their data, their uptime and their continued willingness to publish. That is a reasonable trade in many places. It is a strange one here, because the underlying data is already on the chain, in public, waiting.
The gap is not measurement. The gap is that no measurement is a computation — every volatility number on chain today got there by being asserted.
Every Uniswap pool keeps a running integral of its own price, updated on every trade, reaching back hours. What a price did is sitting in public storage. Reading it means reconstructing a series, and reconstructing a series was assumed to mean a keeper, a feed, or a logarithm. It does not.
A Uniswap tick is a logarithm. Prices are stored as
1.0001^tick, so a log return is an integer subtraction. The measurement needs
no logarithm, no keeper and nobody's word — only arithmetic on numbers already written.
That is the whole technical premise. What follows is what happened when we ran it against the real thing.
What we measure, precisely
Annualised realized variance over a window, from a series of time-weighted average prices sampled on a fixed grid:
RV = (SECONDS_PER_YEAR / window) · Σ [ ln(P_i / P_{i-1}) ]²
Read at settlement in a single call, from observations the pool wrote anyway. Nobody records anything while the contract is alive; there is no scheduled write to pay for and no moment where choosing when to observe is worth money.
Gas measured against the live WETH/USDC 0.05% pool on Base at block 49 000 000 — docs/measurements/gas_profile.md. The same settlement on Ethereum at 20 gwei costs $149, which is why this is an L2 protocol and not a preference.
The missing third
Here is the finding we did not want. Sampling a time-weighted average rather than the spot price does not measure the same quantity — it measures a systematically smaller one.
Each grid point is an average over its step, and averaging inside a step cancels whatever moved within it. We measured how much, against spot prices at the same instants:
| Window | TWAP ÷ spot | Range across grids |
|---|---|---|
| 6 hours, active pool | 67% | 45–80% |
| 1 hour, active pool | 64% | 50–82% |
| 6 hours, thin pool | 112% | 95–121% |
For a Brownian path the theoretical ratio is exactly two thirds. We measured 67% and 64% on live ETH. Theory and data agree, which is reassuring and inconvenient in equal measure.
There is a second finding buried in that table, and it overturned our own assumption. We expected the bias to come from interpolation — Uniswap fills gaps between recordings linearly, so a quiet pool should look artificially smooth. It does not. On the busy pool, where a genuine observation lands every 23 seconds and there is almost nothing to interpolate, the effect is largest. On the thin pool it vanishes. The mechanism is averaging, not interpolation, and the two only coincide where nobody trades.
The reference that lied
Our first reference series was every swap in order — the finest record the chain offers. It said the grid inflated variance threefold, the opposite of the truth. The reason: on that pool 85% of swaps do not move the tick at all. A tick is one basis point and most trades are smaller than that, so summing over that series measures the resolution of the tick grid rather than the movement of the price.
What it costs to lie
A long position gains when realized variance settles high, and variance is a sum of squared returns — so an attacker needs no direction, only movement. That is the cheapest attack available, so it is the one we priced, by carrying it out against the real pool with real swaps.
| Attack | Spend | Effect on the settled number |
|---|---|---|
| $1M pushed and reversed in one block | $986 in fees | 0 bps |
| $1M pushed and held five minutes | $1M committed | 15.7× |
A million dollars moved the deepest ETH pool on Base by 6.4% and changed the settled figure by nothing, because two seconds of excursion inside a fifteen-minute average is nothing. That is the design working.
Holding the price is a different story. Keep the dislocation for a third of one grid step and settled variance goes up nearly sixteen-fold, paying for itself against any position above roughly $1.5M.
A time-weighted average is not manipulation-proof. It is manipulation-priced. The useful question is not whether an attack exists but what it costs, and against what.
So the defence is a ratio, because the break-even is a ratio: a series may not write more notional than moving its source one percent would cost — about $254k on this pool.
And that $1.5M is the floor, not the price. It was measured on a fork, where a dislocated price simply stays dislocated. On a live chain, holding ETH 6% away from every other venue for five minutes means buying everything the arbitrageurs sell you for five minutes — a bill of a different order, and one that lands on the attacker rather than on the protocol.
Does anyone make money
We replayed the instrument over 226 390 real swaps — forty consecutive six-hour windows, eleven and a half days of Base — pricing each strike from a trailing estimate that uses no information from the window it prices:
| Strike | Long wins | Long mean | Long median |
|---|---|---|---|
| fair (1.0×) | 35% | −1.0% | −36.1% |
| 1.2× | 32% | −14.8% | −46.7% |
| 1.5× | 22% | −29.4% | −57.4% |
Lose small often, win large rarely, roughly flat at a fair price. That is what buying volatility is, and a median of −36% against a mean of −1% is the asymmetry in two numbers. The premium a seller earns above that is what gives a market maker a reason to quote at all.
Who buys volatility at a fair price
If the average buyer is flat at best, the obvious question is who buys at all. Not someone seeking a return — someone already holding the position and paying for it without having chosen to.
Loss-versus-rebalancing, the cost an automated market maker pays to arbitrageurs, is proportional to variance. Every AMM liquidity provider is structurally short exactly this quantity, and pays the bill whether or not they hedge it. Published estimates put it at 5–11% a year on a major ETH pair, the upper end reached when volatility does.
For them the mean is not the relevant figure. What matters is that the instrument pays most in precisely the weeks the bill is largest — which is what a hedge is, and why the buyer of realized variance is not a speculator but the person on the other side of the same pool.
Volatility has been the one number in this market that everybody trades and nobody checks. It is checkable. It has been sitting in public storage the whole time.
Every figure regenerates from the repository with one command — the bias from
make bias, gas and attack cost from the fork suite, the backtest from
make backtest. If a number here and its file disagree, the file is right.