@inflexion/sdk
encodes structurally. If you are building on Inflexion, treat these five rules as
non-negotiable in your copy and your tooltips.
The framing rules are also captured in code as a self-contained guardrail block: the
no-bad-debt clause, claims A and B (exported verbatim as
LP_CLAIM_A / DEPOSITOR_CLAIM_B),
and the hedge caveat. When in doubt, quote the exported constant rather than paraphrasing.The five rules at a glance
1. In-range convexity hedge
Not “IL insurance”. Entry requires ; payout is capped at MaxIL. The cap is load-bearing.
2. Qualified no-bad-debt (Claim A)
Exact only under the full clause. Never stated unqualified. Lives on the LP surface only.
3. Capital is not guaranteed (Claim B)
Both tranches. Junior first-loss; senior protected from underwriting loss only. Never merged with Claim A.
4. Quotes are per-market
MaxIL is the unit of risk → positions are fungible. A
SignedQuote carries no tokenId.5. The Phi-sum is read, never reimplemented
FairValue is an on-chain closed form. Only the deterministic load stack is mirrored off-chain, parity-locked.
Rule 1 — In-range convexity hedge, not “IL insurance”
Inflexion lets an LP transfer the in-range impermanent-loss risk of a specific position. Two structural facts make this a convexity hedge rather than insurance, and the SDK enforces both:1
Entry requires Pa ≤ P0 ≤ Pb
Out-of-range positions are rejected at creation. The SDK computes
inRange = sqrtP0 >= sqrtPa && sqrtP0 <= sqrtPb in resolveGeometry
and surfaces it on every LpGeometry and EligiblePosition. This mirrors the on-chain
createSwap in-range gate — there is no way to protect a position that is already out
of range.2
Payout is min(realized_IL, MaxIL)
The settlement payoff is the capped IL, not the raw IL. The cap is applied in
getPayoffCurve and in ilToDate, where capHit = payout < il tells you whether the
cap bound.Priceable<...> envelope returns il and payout as unsigned bigint.
See the in-range convexity hedge and
the IL formula for the full derivation.
Rule 2 — Qualified no-bad-debt (Claim A)
The LP-facing claim is: LPs are always paid — no bad debt in FULL mode (invariant I1). The SDK carries this on the LP surface asnoBadDebtFull: true on ProtectionStatus and
exports the full sentence verbatim as LP_CLAIM_A.
But the claim is exact only under its full qualifying clause. State it any other way
and it is wrong.
The clause, spelled out — every term is load-bearing:
Claim A is about the LP being paid. It says nothing about depositor or MM capital —
that is a separate claim (Rule 3). The SDK
keeps them on separate surfaces precisely so they cannot be accidentally merged.
Rule 3 — Capital is not guaranteed (Claim B)
The underwriter-facing claim is the mirror image of Claim A, and it must never be softened. The SDK stampscapitalNotGuaranteed: true on every VaultState and
DepositorPosition result and exports the full sentence as DEPOSITOR_CLAIM_B. It is
structurally impossible to read vault state from the SDK without the flag attached.
Both tranches carry risk — differently
The protocol underwrites with a two-tranche waterfall. Neither tranche is risk-free:- Junior — first-loss
- Senior — protected, not risk-free
Junior is the first-loss buffer: it captures most of the premium and absorbs
underwriting losses first. The on-chain
withdraw enforces the JuniorBelowLocked
gate so junior cannot drain below the locked amount and break senior protection. A
junior withdrawal that would cross the locked floor reverts and surfaces as
WriteResult { status: 'error' }, not a silent partial.Rule 4 — An MM quote is per-MARKET, never per-NFT
This is the rule integrators most often get wrong, because intuition says “I’m pricing this position.” You are not. MaxIL is both the load-bearing payout cap and the unit of risk:- MaxIL is pure geometry — a function of , frozen at creation.
- It is L-independent in the fair-rate sense: the liquidity scales the dollar amount but not the fair rate.
SignedQuote struct carries no tokenId. Its fields are
mm, marketId, loadBps, minMaxILRatioBps, maxMaxILRatioBps, quotePrice,
priceBandBps, model, partialRatioBps, maxNotionalV0, validUntil, quoteId,
nonce — geometry-independent, every one.
The SDK leans into this: the first-class streamable signal is getPoolLoadToBeat /
streamPoolLoadToBeat — the pure pool load an MM must undercut, computed without any
position geometry:
Rule 5 — The Phi-sum is read on-chain, never reimplemented
FairValue is an exact closed-form -sum — the StylusFairValueOracle
(fairPremium / fairRate). It is the protocol’s single source of pricing truth, and the
SDK reads it; it never recomputes it off-chain.
The on-chain read, in the SDK’s hot path:
The one permitted duplication — and why it is permitted
There is exactly one piece of pricing math the SDK mirrors off-chain: the deterministic,pure load stack (baseLoad + utilSkew + dispSkew, clamped to
maxLoadBps). It lives in the cvamm namespace and is parity-locked byte-equal to the
deployed CvammPricing Solidity by a dedicated parity test.
Why mirror it at all? Because the deployed CvammPricing library is delegatecall-only:
a direct eth_call to libs.cvammPricing reverts (Solidity guards deployed libraries —
confirmed on the 2026-06-05 deploy). The library runs on-chain only via the core’s
delegatecall during pricing, so there is no callable on-chain entrypoint to read the load
from. The parity-locked TS port is the only way to preview the load without sending a
transaction.
The split is precise:
Inverting
fairRate to infer implied volatility is also a circular signal — it would
just recover the σ_ref the oracle was fed. It is deliberately excluded from the data-moat
signals for exactly that reason. See
circular vs behavioral.One more guardrail: the hedge caveat
If you surface the SDK’s read-only analytics (GreeksEngine / HedgeSuggester), there is
a sixth framing rule you must carry verbatim. Every HedgeSuggestion attaches
HEDGE_CAVEAT:
- The hedge is approximate relative to the fixed-maturity IL claim (mismatched expiry, funding, discretization).
- It is the MM’s own residual-risk choice, not a protocol requirement.
- It is not relied upon for pool solvency — invariant I1 (no bad debt, FULL) is structural and oracle-independent, fully collateralized at MaxIL regardless of whether the MM hedges at all.
executeOnPanoptic always returns executed: false — the SDK never submits a hedge tx.
It is analytics, not execution.
See greeks & hedge and the trust model.
Quick checklist for integrators
Copy that mentions LP protection
Copy that mentions LP protection
Say “in-range convexity hedge”, not “IL insurance”. State the payout as
and note the cap. Mention the entry gate
if there is room.
Copy that mentions no-bad-debt
Copy that mentions no-bad-debt
Always attach the full clause via
<ClaimA /> (FULL + capped payoff + solvent USDC +
oracle/settlement liveness + no rehypothecation breach). Never the bare phrase. This is
the LP claim — keep it off depositor surfaces.Copy that mentions depositors or MMs
Copy that mentions depositors or MMs
Render
<ClaimB />. Both tranches carry risk: junior first-loss, senior protected from
underwriting loss only and exposed to the systemic tail. Never “risk-free” or
“guaranteed”. Do not reuse Claim A’s no-bad-debt language here.Copy that mentions MM quotes
Copy that mentions MM quotes
A quote is per-market: load + MaxIL-ratio band + capacity. The
SignedQuote has no
tokenId. Never present a quote as pricing one specific NFT.Anything that shows history or aggregates
Anything that shows history or aggregates
History surfaces (load-surface history, quote competition, NAV, net gamma) are
subgraph-pending. The SDK returns a typed
ApiPending envelope naming the future
route — render the pending state, never an error, never fabricated numbers.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.
LP_CLAIM_A,
DEPOSITOR_CLAIM_B, and HEDGE_CAVEAT are all exported from @inflexion/sdk.