max(...) and the floor are not engineering convenience. They are the conservative guard that keeps the pool from selling convexity too cheaply at exactly the worst moment. This page explains the construction, the EWMA mechanics, why the max is mandatory, why the floor sits above calm ETH realized vol on purpose — and, critically, the precise scope of what a wrong can and cannot break.
Where it lives. On-chain production:
VolOracle, live on Arbitrum Sepolia — see the deployment registry.The construction, term by term
is the pointwise maximum of three numbers: a fast EWMA, a slow EWMA, and a hard floor. On-chain this isVolOracle._sigmaRef.
annualized vol
A fast EWMA of Chainlink log-returns with a one-day halflife. It reacts quickly: it catches a vol spike within hours, but it also decays back to calm quickly once the move passes.
annualized vol
A slow EWMA of the same log-returns with a 30-day halflife. It has memory: a recent crash keeps it elevated for weeks, so it carries the lingering risk that the fast window has already forgotten.
constant
A hard lower bound of 0.50 (50% annualized). No matter how calm the realized series gets, the pool prices off at least 50% vol. This is the deliberate conservative anchor — see the floor section.
Calibrated values
These come from the calibrated risk-parameter set (the cvAMM block) — none are hardcoded in the contract. Hardcoding any vol primitive is the exact failure the external audit flagged.The EWMA mechanics
Both and are exponentially-weighted moving averages of log-returns taken from Chainlink price ticks, at two different horizons. Eachpoke of the on-chain oracle folds the newest price into a running per-second variance estimate, annualizes it, and takes the conservative max.
Log-returns
From a sequence of price observations , the log-returns are Working in log space is what makes the estimator multiplicative-noise-aware: it matches the GBM model the Phi-sum is integrated against, where price moves are lognormal.Exponential weighting
The EWMA variance assigns each squared return a weight that decays geometrically with its age. With decay factor and the most recent return at age : The decay factor is set from a halflife — the number of samples over which a weight halves: Soshort_halflife = 86,400 s means a return’s contribution halves after a day; long_halflife = 2,592,000 s means it halves after a month. The most recent return always carries the largest weight — the estimator is responsive to fresh data without throwing away history.
RiskMetrics convention —
demean = False. The variance is computed as , not — the sample mean is not subtracted. Over short horizons the drift term is negligible relative to the diffusion term (), and including a noisy mean estimate would only add variance to the estimator. This is the standard RiskMetrics EWMA.Annualization
The per-period variance is scaled to an annualized standard deviation by the square-root-of-time rule: On-chain, eachpoke folds the latest price into a per-second variance and annualizes against a 365-day year. The annualized number is what feeds inside the Phi-sum — see the fair-value page for how it enters the S-curve.
On-chain sampling guards
The on-chainpoke is permissionless and idempotent-when-too-soon, which is what lets it be folded directly into createSwap with no dedicated keeper:
1
poke is a no-op when dt is too small
If
dt < minSampleInterval, poke does nothing. This prevents micro-samples from blowing up the ratio — two ticks a fraction of a second apart would otherwise produce an enormous spurious variance.2
dt is clamped to a sane band
dt is clamped to [minSampleInterval, maxSampleInterval], so a single huge gap can neither divide by a tiny dt nor over-weight one stale sample.3
The first poke seeds at the floor
Both windows are seeded at the floor on the first observation, so early reads are conservative rather than zero. On the live deploy initialized to the
0.5e18 floor, which corresponds to at the reference geometry.createSwap pokes the oracle in _fairPremium so the vol estimate stays fresh on every fill without a separate cron — see the lifecycle.
Why the max(…) is mandatory
This is the core of the design, and it is worth stating sharply: you must never price off raw realized volatility. The reason is a structural property of realized vol: it understates risk right before a regime change. Volatility lags the jump. In the calm run-up to a crash, the realized series is, by definition, calm — the violent returns that justify a high vol estimate haven’t happened yet. A single fast EWMA would therefore collapse to a deceptively low number at exactly the moment a writer is about to be hit hardest. A pool pricing convexity off that number would sell coverage at its cheapest right before the path most likely to make it pay MaxIL. Themax over three sources is the conservative guard against every failure mode of a single estimator:
Why not just the fast EWMA (short window alone)?
Why not just the fast EWMA (short window alone)?
The fast window is responsive but forgetful. It catches a spike quickly, but it also decays back to calm within days. A crash three weeks ago — whose risk is far from resolved — has already washed out of the short window. Pricing off it alone would underprice coverage written in the unsettled aftermath of a shock.
Why not just the slow EWMA (long window alone)?
Why not just the slow EWMA (long window alone)?
The slow window has memory but is sluggish. It would not register a fresh, fast-developing spike until it had accumulated enough samples — too late for the coverage being written into that spike. Pricing off it alone would underprice coverage at the onset of a new regime.
Why the hard floor on top of both EWMAs?
Why the hard floor on top of both EWMAs?
Both EWMAs are backward-looking: in a genuinely quiet, extended calm they will both decay toward the low realized vol. Realized-vol estimators are structurally lagging at a regime boundary — neither window can see a jump that hasn’t printed. The floor is the model-free backstop that holds the price up regardless of what the realized series says. See the next section.
The floor sits above calm ETH vol
The floor is0.50 — and that is a deliberately conservative choice, not a casual default.
Observed calm ETH realized vol sits around ~0.45. The floor of 0.50 > ~0.45 is set above it on purpose. The consequence is structural and intentional: the pool overcharges in calm months. When realized vol is genuinely low, both EWMAs decay toward ~0.45, but is held up at 0.50, so the published FairPremium is a touch richer than the “true” calm-market fair value.
That over-charge is not a bug — it is a transfer to the depositor pool that compensates for the residual model risk the GBM, r = 0 assumption leaves on the table. The depositor heavy run measures the net effect directly:
Net-conservative to depositors. Across all months in the P1.13 heavy run, realized payout / premium = 0.654 — the pool collects meaningfully more premium than it pays in claims, in aggregate, precisely because the floor overcharges the ~27% of months that are calm. See the depositor disclosure for the full risk panel.
payout / premium = 1.14 at a stress onset. That residual is real, but it is a vol-risk premium that baseLoad must carry, not a no-bad-debt risk — which brings us to scope.
No on-chain implied volatility
A natural question: why not use implied vol — the market’s forward-looking expectation — instead of a backward-looking realized estimate? Because there is no deep on-chain options market to read it from. Deribit holds over 90% of ETH options off-chain, so any on-chain implied-vol feed would be a thin, manipulable, or oracle-dependent surface. Inflexion refuses to make any solvency path depend on one:- Deribit DVOL is an optional published enrichment only. It can be surfaced as context in the data layer, but no solvency path ever depends on it.
- The structural backward-looking bias of realized vol is instead corrected by the market itself: forward-looking MMs who price off implied vol will undercut the pool whenever it is too rich, and decline to write when it is too cheap — exporting the forward-vol view into the system through the routing rather than through a fragile oracle.
Load-bearing scope: solvency, never no-bad-debt
This is the single most important — and most often-confused — point about . It is load-bearing for one thing and structurally irrelevant to another, and the two must never be merged. (and the FairValueOracle that consumes it) is solvency-load-bearing for the I10 price cap and depositor solvency only.- What a wrong sigma_ref CAN break (solvency / I10)
- What a wrong sigma_ref CANNOT break (no-bad-debt / I1)
A wrong or too-low makes the pool under-charge load. The published premium is computed off too-calm a vol, so premium income stops covering payouts, and NAV compresses. The loss then hits the tranche waterfall junior-first: junior absorbs it, senior takes only the systemic tail.This is a real cost — it can cost depositors money. It is the I10 / depositor-solvency surface. It is exactly why
baseLoad exists as a structural over-fair-value charge: to carry the residual vol-risk premium a lagging estimate leaves behind.
The mental model: decides how richly the pool gets paid for the risk it takes (a depositor-economics question). It does not decide whether the LP gets paid (a structural-collateral question). The first is the load stack’s job; the second is the cap’s job, and the cap holds no matter what the vol oracle says.
Where sigma_ref sits in the pricing stack
is the one number that injects the stochastic world into an otherwise deterministic pricer:
The
baseLoad regime band is itself keyed off — calm < 0.60, normal 0.60–1.025, stressed ≥ 1.025 — so the vol oracle feeds the pricing stack twice: once through fairRate (the fair value) and once through baseLoad (the risk premium over it). See the load stack for the full breakdown and a worked example end to end.
Structures ship from day one; the full DYNAMICS (pool-vs-MM spread as a forward-vol signal) mature with multiple competing MMs and volume. The dataset begins at the single redeploy; the off-chain telemetry halves begin at the first interaction logged.What Inflexion offers today is the architecture and the first public view into the microstructure of the DeFi LP volatility-risk premium — not yet a mature dataset:
- Structures are present day-one. All five non-circular behavioral signals are defined and queryable from launch.
- Dynamics mature with volume. The richer signal — the pool-vs-MM spread read as a forward-vol indicator — only sharpens once multiple market makers compete and real flow accumulates.
- The dataset begins at the single redeploy, and the off-chain telemetry halves begin at the first interaction logged. History is served live from the subgraph via the API; if a backing (subgraph URL / RPC / telemetry) is absent, surfaces degrade to a typed
pendingstate — never an error.
See also
The Phi-sum
How enters the exact closed-form fairRate as .
The load stack
The -keyed baseLoad and the I10 price cap.
No-bad-debt math
Why I1 holds for any — the structural collateral proof.
The invariants
I1 (no-bad-debt) vs I10 (price cap) — the two never-merged guarantees.
Oracles
The VolOracle alongside the Chainlink entry/settlement price oracle.
Tranches
Who bears a undercharge: junior first, senior tail.