Skip to main content
Three operational facts shape Inflexion’s trust surface beyond the invariants and the two resolved forks:
  1. No upgradability. Every deployed contract is immutable. Wiring is a one-shot set → freeze and there is no admin path to redirect a vault’s core after the freeze.
  2. NFT custody is narrow. The LP’s Uniswap v3 position NFT is held by a dedicated vault for the swap’s life, accepts deposits only from the canonical position manager, and returns to the LP at settle.
  3. EIP-170 is satisfied. The deployed InflexionCore is 23,934 B, under the 24,576-byte contract-code-size limit. An earlier version briefly exceeded it; the resolution is described in full below.
Immutability and custody are part of why Claim A (no bad debt, FULL) holds with no trusted operator: settlement runs on-chain against the counterparty’s own collateral, with no upgrade key that could rewrite the settle path after the fact.
LPs are always paid with no bad debt in FULL mode — qualified: capped payoff + solvent USDC + oracle/settlement liveness.The no-bad-debt guarantee is exact only under the full clause:
  • FULL collateralization — the underwriter has posted exactly MaxIL per swap, locked for the life of the position.
  • Capped payoff — the payout is min(realized_IL, MaxIL). The cap is load-bearing: it is what makes payout ≤ collateral hold by construction.
  • Solvent USDC — the collateral numeraire (dUSDC) holds its peg and remains redeemable.
  • Oracle / settlement liveness — the price oracle stays live and settle() runs within the protocol’s settlement window.
  • No rehypothecation breach — locked collateral stays instantly liquid; it is never routed to utilization-gated venues.
Stated without these qualifiers, the guarantee is not correct.

No upgradability — the one-shot wiring pattern

There is no proxy, no upgrade beacon, no admin-redirectable logic address. The contracts deploy once and stay byte-for-byte fixed. The only privileged action is the initial wiring of vaults to the core state machine, and that action self-destructs after a single use. The pattern is a set... setter paired with a freeze... latch:
  • The deployer calls setCore on each vault to point it at InflexionCore, then calls freezeCore to permanently lock that pointer.
  • The same shape applies to the core’s own dependency wiring (setCvamm / freezeCvamm).
After the freeze, there is no admin path to redirect a vault’s core address — a re-wire attempt reverts. This closes the obvious “swap the logic out from under live swaps” attack: once a market is open, the code that will settle it is fixed.
Immutability is a deliberate trade against operational flexibility. The cost is that a bug cannot be hot-patched; the benefit is that the security model has no “trust the upgrade key” footnote. For a collateralized derivatives market where the payout is enforced by code rather than by an operator, a redirectable core would be a contradiction. Mitigation for the rigidity is the depth of pre-deploy review — see audits (multi-LLM spec audit + two Slither passes) and the Foundry-fuzzed invariant suite.

NFT custody — narrow by construction

During a swap the LP’s Uniswap v3 position NFT is held by the ILVault ERC-721 custody contract. Custody is intentionally narrow so the NFT can be neither hijacked on the way in nor mis-credited on the way out.
1

Take custody — canonical source only

ILVault.onERC721Received accepts an NFT only from the canonical NonfungiblePositionManager configured at deploy. A token arriving from any other ERC-721 contract is rejected, so a forged “position” NFT cannot be deposited to spoof a swap.
2

Fees during the swap — recipient is forced

While the position is custodied, claimFees routes accrued Uniswap fees to a forced recipient: the registered LP. The caller cannot redirect fee proceeds; custody never becomes a fee-siphon vector.
3

Liquidity is snapshotted, not re-read

The position’s liquidity L is stored once at creation and settlement uses that stored value — settle never re-reads positions(tokenId).liquidity. This is invariant I6: an external increaseLiquidity on the custodied NFT cannot inflate the computed IL above MaxIL. See price pinning for the companion geometry checks.
4

Return at settle

returnNFT hands the position back to the LP at settlement. Custody is for the swap’s duration only.
Why custody must take the NFT at all — settlement pays the LP from the counterparty’s collateral, and the protocol must guarantee the position’s geometry (Pa, Pb) and liquidity L are the ones priced. The risk if custody were loose: a forged NFT (wrong issuer) or a post-creation increaseLiquidity could distort the payout. The mitigation is exactly the narrowness above — issuer check on receive (canonical NPM only), forced fee recipient, and L snapshotted at creation (I6) — so neither the deposit nor the in-flight mutation can move the payout.

EIP-170 — the resolved size-pass

EIP-170 caps deployed contract bytecode at 24,576 bytes (0x6000). forge build and forge test run on revm, which does not enforce the limit — so a too-large contract compiles and passes its entire test suite while still being undeployable on a real chain. That gap is exactly the trap Inflexion hit and resolved.

The history

Limit (documentation lag, not a live blocker). Earlier documentation still reads as though InflexionCore is over the EIP-170 limit: adding the data-moat events SwapPriced / QuoteFilled pushed the contract +213 B over the 24,576-byte limit, to 24,789 B. Read in isolation, that note says the contract cannot be deployed.Why the note is stale. It describes the pre-redeploy state. forge build / test (revm) never flagged it because revm ignores EIP-170 — only an actual deploy would have failed. The note was written at the moment the blocker was discovered and was not rewritten after the fix landed.Mitigation — resolved at the 2026-06-05 redeploy. Two changes brought the contract under the limit:
  1. Lowered optimizer_runs to 1500 (trading a marginal amount of runtime gas for smaller deployed bytecode).
  2. Extracted public libraries — CvammPricing, QuoteVerification, SwapMath, and TickMath are deployed as separate delegatecall library code rather than inlined into the core.
The deployed InflexionCore is now 23,934 B — under the 24,576-byte limit. The on-chain address registry reflects the resolved deploy; the stale documentation note is flagged rather than papered over. See the running list at status & caveats.

The numbers

The fix bought roughly 855 B of headroom (24,789 → 23,934) — the contract now sits comfortably below the ceiling, with the public libraries carrying the extracted math as delegatecall code.
A side effect of the library extraction worth knowing for SDK / parity and audit purposes: CvammPricing, QuoteVerification, SwapMath, and TickMath are delegatecall-only libraries — they execute in the caller’s storage context and cannot be unit-tested as standalone deployed contracts via live calls. This is reflected in the test suite (a CvammPricing live-parity test was corrected to acknowledge libraries are delegatecall-only). It does not weaken any invariant: the extracted code is the same code, just relocated.

Why this matters for trust

The EIP-170 episode illustrates the project’s posture: a limit was hit, the build tooling (revm) did not surface it, it was caught before mainnet, fixed deterministically in code, and the one stale documentation note is flagged rather than hidden. No on-chain behaviour changed — the events, the invariants, and the settle path are identical; only the bytecode layout and optimizer setting moved.

Live, immutable deployment

These are the immutable contracts running on Arbitrum Sepolia (chainId 421614), redeployed fresh on 2026-06-05. Once wired and frozen, none of these addresses can be redirected. Network: Arbitrum Sepolia · chainId 421614 · deploy block 274081134 (subgraph startBlock) · deployed 2026-06-05

Core protocol

Stylus & libraries

Oracles

Uniswap

Demo tokens / pool / LP

Lifecycle swaps

Live create→settle lifecycle (2026-06-05, short 300s fee-500 market 0xb8bbd684f213d5833886ade7b531a6949d85522249881a2b5d46a5cc76e439c2):
  • Path A (cvAMM convexity) — swapId 1, LP tokenId 3220 · V0 $270,531.28 · MaxIL $1,669.24 · premium $9.70 (0.58% of MaxIL) · settled payout $148.64 from ConvexityVault.
  • Path B (MM routing) — swapId 2, LP tokenId 3221 · MM beat cvAMM ($8.93 vs $13.80) · MaxIL $3,215.65 · MM collateral locked $3,215.65 · settled payout $245.66 from MM collateral.
For the full registry, decimals, and per-contract roles, see deployments.

Invariants I1–I10

The ten Foundry-fuzzed invariants, including I6 (liquidity immutability) which underpins NFT custody safety.

Price pinning

On-chain Chainlink-derived entry/settlement prices and the LP-lies-about-geometry defenses that complement custody.

CEI & reentrancy

The four-phase create path and status-flip-first settle that keep custody and state transitions atomic.

Status & caveats

The running ledger of known limits — including the stale EIP-170 note — each with its why and mitigation.