
Tremor
Two-sided continuous ETH realized-variance receipts hedging LVR on 1inch Aqua & SwapVM.
Demo
About
Tremor is a continuously priced market in ETH realized variance. It is a way to take a position on how violent the next week is, rather than which direction it goes. Volatility is one of the largest risks in crypto and almost nobody can trade it directly. You can bet on direction all day. But an LP bleeding to loss-versus-rebalancing, a desk short gamma, a treasury sizing its risk: none of them can take a clean position on variance itself without an options book and a counterparty to face. Tremor turns realized variance into an instrument. Each market is one observation window on the Chainlink ETH/USD feed carrying two complementary claims: LONG VARIANCE pays S × min(V / V_cap, 1) SHORT VARIANCE pays S − LONG where V is the annualized realized variance actually observed and S is the cap payout. The two sides always sum to exactly S, which is $1.00, to the integer, in every state, because SHORT is computed by subtraction from LONG rather than rounded independently. Buying the pair can never win; selling the pair can never win. Settlement is computed, not quoted. At expiry anyone calls finalize, and the contract replays Chainlink's own round history on chain to compute realized variance and fix both payouts in a single call. There is no oracle write, no price feed of our own, and no privileged actor. The same is true of checkpointing the observation window: permissionless, bounded per call, and cheap. Anyone who wants a quote can make the call, because a market that is behind refuses to price. Prices move continuously, and every price the UI presents as executable is executable. This is not an order book. The market quotes off projected variance, meaning what has actually been realized so far blended with a forward for the time remaining. That is displaced by inventory skew and sits inside a spread that tightens as the window closes and the outcome becomes less uncertain. A fill is priced as the integral over a rising ask, so size pays impact honestly. The number on screen is read from the on-chain lens for that exact size, not estimated by the frontend. The indicative mark is shown separately and labelled an estimate, never offered as a cashout value. Both sides share one pot of collateral. Every claim is fully collateralized before it is sold, and the writer cannot withdraw what backs a live claim. Because long and short cannot both pay out, the market locks ceil(max(long, short) × S) rather than long × S + short × S. The saving is min(long, short) / (long + short) — up to half the capital for the same open interest when the book is balanced — and the terminal shows the actual figure read off the contract rather than a headline. That is the 1inch Aqua contribution: one vault, one reserve, two instruments. A built-in hedging tool sizes the position for the most concrete buyer: an LP's expected LVR is proportional to realized variance (E[LVR] ≈ P·σ²·T/8, for pool value P), so pool value and horizon in gives units and premium out, priced through the same lens.
How it's made
Contracts: Solidity 0.8.30, Foundry. TremorPortfolioMarketV4 holds the accounting and the fill legs; TremorPortfolioLensV4 is a separate read model, split out because the combined contract exceeded the EIP-170 24,576-byte limit by 746 bytes. PortfolioPricing is the whole pricing change and deliberately owns no new arithmetic: every integral, spread and clamp is the v2 VariancePricing library already pinned to reference vectors at 60 decimal digits. The bridge that let two generations compose with no seam is deriving the cap payout S = floor(unitNotional × capVariance / 1e18), which makes v2's perUnitPrice(V) and v3's S × min(V/cap,1) the same function of V. 1inch Aqua + SwapVM is the execution layer, not a wrapper. Each market ships six strategies, issue, exit and settle for both sides, and each one is a SwapVM program built from stock instructions: Salt · Deadline · Extruction. They run on the unmodified official AquaSwapVMRouter; we forked no router and added no opcode, which means this deploys against real Aqua today with no new audit surface and nobody's permission. The interesting part is where the pricing lives: the Extruction instruction calls back into the market mid-swap, so the curve is evaluated inside the swap itself. That is what makes preview and execution provably the same number. The frontend re-quotes through router.quote, which is the exact code path router.swap runs, immediately before signing. The vault ships each strategy hash-pinned, and the market verifies the returned hash matches what it built, so a fill cannot execute against a program the market did not author. Collateral sits in the writer's own TremorMakerVault, which grants Aqua an allowance the writer does not control the code of; the router pulls against that allowance when a leg fills. It is an allowance model, not escrow — which is exactly why a capped payoff fits it and a perp would not. Maximum liability is fixed at issuance, so a position is fully reserved from t=0, there is no leverage, and there is nothing to liquidate by construction. That is also what lets one reserve back two instruments. Chainlink is used as a historical record, not a price feed. The accumulator walks AggregatorV3 round history phase-aware, absorbs samples on a fixed per-market grid (sampleInterval, floored at 300 seconds; the demo markets use ten minutes, because the grid must be coarse enough that repeated rounds do not bias realized variance downward), and stores progress so checkpointing is idempotent and bounded. A market refuses to price against a window with unstored samples, so a stale quote reverts CheckpointsStale rather than filling at a number the feed has already moved past. All arithmetic is integer. WAD for variance, 6-decimal for USDC, bigint end to end with no floats anywhere in the stack. Rounding direction is chosen deliberately in every operation to favour the collateralized maker: takers pay ceil and receive floor, and the complement inherits that direction because it subtracts a floored term from a ceiled one. Backend: Rust, axum, alloy, sqlx/SQLite. An indexer plus an exact replica of the Solidity pricing, which is what lets the API serve history and previews without a chain round trip per request. The replica is pinned against the contracts' own vectors — 144 portfolio cases for the Rust replica, 60 series cases for the web replica, all generated at 60 significant digits — so a divergence fails a test rather than reaching a user. The API reconstructs price history per sample, on the window's own clock rather than the keeper's transaction time, and reports the anchor drift against on-chain state in ppm. A subgraph (The Graph, tested with Matchstick) mirrors the events. Frontend: Next.js 16, wagmi v3 / viem, Recharts, Playwright. The terminal is the product: chart with the executable band, an on-chain activity tape, a ticket that prices your exact size, and a collateral panel showing the shared-reserve saving against the separate-cap equivalent. The rule the whole UI obeys is that the Lens is the authority and the backend is a replica. Chain state is merged over API state, never the reverse, and an estimate is never rendered where a user will read an executable price. An oversized order is presented as a partial fill — the ticket prices what the router will actually sell, not the size that was typed. Notable details. Inventory skew is stateless: rather than storing a decaying signed skew with a half-life and a last-updated timestamp, the forward is displaced by impact × (long − short) derived from outstanding inventory, so it cannot drift from the book and reverses exactly on an exit. The E2E suite drives a real fill against an anvil fork through an EIP-1193 shim that forwards to the node under --auto-impersonate, so transactions are genuinely signed and mined, and the test asserts on the buyer's own receipt balance on chain rather than on the DOM. It also covers a refused signature and a slow wallet, and asserts that a quote which moves between display and signing stops the flow and asks for consent rather than signing the new number. To stress the design we built a harness that funds 1,000 scripted accounts on a local fork, against an earlier deployment of the same contracts, and runs each through the same call sequence the trading panel uses; the P&L report is reconstructed entirely from chain state, from USDC transfer logs and receipt balances, not from the harness's own memory. Verification: 290 contract tests across 26 suites including two Base-fork E2Es, 86 backend tests, 85 web unit tests, and 34 fixture-driven browser tests plus a live-fill suite that connects a wallet, signs and mines against a fork. A dedicated test decodes the shipped program bytes and asserts the opcode set, so the "stock instructions only" claim is enforced by CI rather than by a README.