Path A — the cvAMM
A pooled, always-on, signature-free on-chain underwriter.
createSwapPathA. The floor of liquidity — there is always a code-capped price.Path B — the MM rail
A market maker posting a firm EIP-712 signed quote (no last-look).
createSwap. The ceiling of price — an MM wins only by beating the pool.One settlement core, two upstream rails
Every difference between Path A and Path B lives increateSwap pricing and
locking — strictly upstream of settle. The settlement core (settle, the
min(IL, MaxIL) cap, the MaxIL formula, and invariants
I1–I9) is identical regardless of which rail opened the swap.
The shipped
SwapRecord does not carry a path field. settle infers the rail
purely from the stored counterparty — s.mm == address(convexityVault) means it was
Path A, anything else means Path B. The settlement math
does not branch on the rail; only the vault dispatch does (pool vs MM collateral).FairPremium — computed once per create:
The router pokes the VolOracle once and prices both rails
off the same FairPremium — there is exactly one fair
value per position, and the rails only differ in the load applied on top of it.
Path A — the cvAMM rail (createSwapPathA)
Path A is the pooled passive underwriter: the dual-tranche ConvexityVault. It
is always quoting, signature-free at the point of sale, and entirely on-chain.
- Counterparty: the
ConvexityVault(pooled, dual-tranche SENIOR/JUNIOR — see tranches). - Pricing: the on-chain load stack, hard-capped by invariant I10, then additionally capped at MaxIL.
- No keeper, no signed quote, no validity clock, no relayer. Execution
(
_executePathA) locks collateral from the pool, pulls the premium, takes the NFT into theILVault, and splits the premium 99% into the pool (across tranches) and 1% to the treasury.
FairPremium is computed mechanically from the pool’s
own state:
The min(..., maxLoad) is the I10 clamp: the pool cannot overcharge beyond
FairPremium · (1 + maxLoad) — by construction in code, not by trust. None of these
load primitives are hardcoded; they come from the calibrated risk-parameter set.
Path B — the MM rail (createSwap)
Path B is the firm signed-quote rail. A market maker streams an EIP-712 (or
EIP-1271 contract-signed) quote and posts collateral in its own UnderwriterVault.
- Counterparty: a single MM, collateralized in the per-MM
UnderwriterVault. - The quote is PER-MARKET, never per-NFT. The
SignedQuotecarries amarketId, aloadBps, a MaxIL-ratio band, and capacity — but notokenId. This is the direct mechanical consequence of MaxIL being the fungible unit of risk: an MM expresses “I write positions whose MaxIL is 2%–7% of V0” once, and any LP position in that market fills against it. - Pricing: the contract derives
,
capped at MaxIL, and requires
loadBps ≤ maxLoadBps(I10 on Path B).
1
Oracle-anchored price band (I9 / Fork 2)
At fill,
require absBps(P_live, quote.quotePrice) ≤ priceBandBps reusing the
same on-chain price read. This kills the dominant
gap-on-stale-quote pickoff. See price pinning.2
Short validity window
validUntil must be [5s, 15s] ahead (default 8s) — bounds the leakage interval.3
Selective bitmap nonce
Permit2-style bitmap (word
<< 8 | bit): cancel one quote by flipping one bit,
never cancel-all (cancelNonces)._executePathB) is the only place
Path-B state mutates: it increments consumedNotional[quoteId] (capacity authority,
I7), consumes the nonce, locks the MM’s collateral, writes the record, pulls the
premium, takes the NFT, and splits the premium 99% to the MM, 1% to the treasury
(no tranche split on Path B).
createSwapRouted — the cheaper of {pool, MM}
The third entry point, createSwapRouted, is how an
LP gets the best of both rails in a single transaction. It prices both rails off
the same FairPremium (single poke) and routes to whichever is cheaper.
1
Pool must be wired
The market must be
cvammEnabled — the always-on floor must exist as a fallback,
else there is nothing to fall back to and the call reverts.2
Price both rails, once
premiumA = _pricePathAFromFair and
(usableB, premiumB) = _quoteUsableAndPremiumB off the same FairPremium.3
Route — strict-beat, ties to Path A
useB = usableB && premiumB < premiumA. An MM wins only if it strictly beats
the pool; a tie resolves to Path A — the dependency-free always-on rail. An MM
cannot divert flow merely by matching the pool.4
Execute only the chosen rail
Only the executed path mutates state, then
emit
SwapRouted(swapId, pathB, premiumA, premiumB) so the cheapest-wins routing
is auditable on-chain.The non-reverting mirror — why a bad MM quote never hurts the LP
The router does not call the reverting Path-B gate. It calls_quoteUsableAndPremiumB, a view mirror of every
Path-B check that returns (false, 0) instead of reverting. It reads only —
isNonceUsed, consumedNotional, availableBalance, and the signature via
STATICCALL — and never mutates a nonce, capacity, or lock, so an unchosen quote
leaves zero trace (I7 preserved).
This is what makes the floor/ceiling framing concrete: the MM rail is a pure
price-improvement layer. Nothing about correctness, solvency, or liveness depends
on it; it can only ever undercut the pool, never degrade the guarantee the LP already
has from the pool.
Side-by-side
Proven live on both rails
The 2026-06-05 redeploy ran a real create→settle on both rails against one 300s market:- Path A (swap #1): V0 $270,531.28, MaxIL $1,669.24, premium $9.70 (0.58% of
MaxIL), realized IL $148.64, payout $148.64 — settled from the
ConvexityVault. - Routed → Path B (swap #2):
createSwapRoutedsawpremiumA_cvamm $13.80vspremiumB_mm $8.93(MMloadBps1000) and chose the MM because it strictly beat the pool. MaxIL $3,215.65 was locked from the MM’s own collateral, realized IL $245.66, payout $245.66 — settled fromUnderwriterVault.
The two separate claims
The two rails do not change which guarantees apply. The settlement core enforces the LP-facing guarantee identically for both: And the capital-at-risk disclosure applies to whoever underwrites — the pool’s depositors on Path A, the market maker on Path B:Where to go next
Routing in depth
The full
createSwapRouted decision and the non-reverting mirror, step by step.The pricing stack
How FairPremium, the load stack, and the I10 cap compose into a premium.
MaxIL — the unit of risk
Why MaxIL fungibility is what makes an MM quote per-market, not per-NFT.
The full lifecycle
Create → active → settle, from
registerMarket to NFT return.