This page is the map, not the territory. Each box below links to a deep page. If you
read only one paragraph, read this one: an LP pays a small premium up front; an
underwriter locks exactly MaxIL of USDC; at expiry the contract pays the LP the lesser
of their actual IL and MaxIL, from that locked collateral, and returns the NFT.
Everything else is detail about how the underwriter is chosen and how the price is
formed.
The whole thing in four moves
1
Register the market (owner, once)
registerMarket defines a (token0, token1, fee, durationSeconds) tuple and its
marketId. For ETH/USDC that is 3 fee tiers × 3
durations = 9 marketIds, all backed by one ConvexityVault
with fungible capital.2
LP buys protection — Path A, Path B, or routed
The LP calls one of three entry points. The contract pins to Chainlink,
reads the position geometry, checks the entry is in range, computes
MaxIL and the FairPremium, applies a
load, pulls the premium, and takes the NFT into custody.
3
ACTIVE — collateral locked, NFT in custody
Exactly
MaxIL of the underwriter’s USDC is locked. The position is frozen in the
ILVault; the LP keeps fee accrual but cannot re-range or exit early. In FULL mode
no monitoring is needed — liquidation is mathematically impossible.4
SETTLE — anyone, at expiry
At
block.timestamp ≥ expiry, anyone calls settle. The contract pins the
Chainlink round at expiry, recomputes IL with the stored liquidity, pays the LP
from the underwriter’s collateral, returns
the residual collateral − payout to the underwriter, and returns the NFT to the
LP.The pipeline, in one diagram
The three entry points fan in to a single, untouched settlement core. The only thing that differs between them is how the underwriter and price are discovered — once the swap isACTIVE, the rail is irrelevant.
FairPremium — computed once per create:
fairRate carries all the volatility and time dependence (an S-curve in
); MaxIL carries none (it is pure geometry, frozen at creation). That
split is what makes a position fungible to an underwriter and is the
spine of the whole pricing stack.
The status machine
Each swap is oneSwapRecord that walks a tiny,
strictly forward state machine — there is no CANCELLED, no LIQUIDATED, no
unwind path. Once created, a swap is ACTIVE until it is SETTLED, full stop.
The shipped
SwapRecord stores tokenId, lp, mm (the counterparty — the
ConvexityVault on Path A, the MM on Path B), V0, maxIL, collateral
(== maxIL in FULL), premium, model, settlement, createdAt, expiry,
amount0Entry, amount1Entry, and liquidity (stored once, I6).
There is no path field — settle infers the rail from
s.mm == address(convexityVault); the routing path is
emitted in events for the data moat.
The three entry points at a glance
Path A — the cvAMM
createSwapPathA. Pooled, always-on, signature-free. On-chain load
stack, I10-clamped. The floor of liquidity — there is always a code-capped
price.Path B — the MM rail
createSwap. A firm EIP-712 / EIP-1271 signed quote, no last-look.
The ceiling of price — an MM wins only by beating the pool.Routed — cheaper of both
createSwapRouted. Prices both rails off one FairPremium, takes the
cheaper, and falls back to the pool without ever reverting on a bad MM quote.useB = usableB && premiumB < premiumA); a tie resolves to Path A. A bad MM quote —
absent, expired, stale, out-of-band, over-capacity, undercollateralized — is evaluated
through a read-only mirror (_quoteUsableAndPremiumB)
that returns (false, 0) instead of reverting, so the swap silently routes to the
always-on pool. Only protocol-level failures (market inactive, not the owner, out
of range, dust, slippage, pool unwired) revert. See the two rails
for the side-by-side.
What is locked, and what is paid
The number that matters is MaxIL, and it appears twice — as the collateral the underwriter posts and as the cap on what the LP can ever receive. That double role is the entire no-bad-debt argument: Becausepayout ≤ collateral holds by construction of the cap, FULL mode cannot
produce bad debt under any price path — the underwriter’s locked USDC always covers the
LP’s claim. This is invariant I1, and it is structural: it
does not depend on the volatility oracle being right, only on the cap and the
collateral being equal.
Worked numbers from the live deploy
The 2026-06-05 redeploy ran a real create→settle on both rails against one short 300s market, exercising the whole pipeline end to end:
In both cases the payout was the realized IL (below the cap), paid from the chosen
rail’s own collateral, and the underwriter kept the residual
MaxIL − payout. The
routed swap is the routing logic made concrete: the MM’s $8.93 strictly beat the pool’s
$13.80, so the swap executed on Path B and only Path-B state mutated.
Who can lose money
The LP-facing guarantee (no bad debt, FULL, qualified) is separate from the capital-at-risk of whoever underwrites. The underwriter is the pool’s depositors on Path A or the market maker on Path B, and their capital is not guaranteed:The live deployment
Where to go next
The full lifecycle, line by line
registerMarket → the shared read prologue → the three create paths → ACTIVE →
settle, with every check cited.The pricing stack
How MaxIL, FairPremium, the load stack, and the I10 cap compose into a premium.
The two rails, one core
Why a bad MM quote can never harm an LP, and why the settlement core never branches
on the rail.
MaxIL — the cap and the unit
Why MaxIL is both the load-bearing payout cap and the fungible unit of risk.
The invariants
The ten invariants I1–I10 and exactly where each is enforced in code.
The data moat
The five behavioral signals the per-fill clearing-price events expose.