> ## Documentation Index
> Fetch the complete documentation index at: https://inflexion.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Addresses, decimals & units

> Import every contract address from the registry — never hardcode. The symbol → address → role map, the decimal conventions (dUSDC 6, dWETH 18, feeds 8, WAD 1e18), and the sqrtPriceX96 ⇄ price ⇄ a/b conversions the SDK ships.

Two things will silently break an integration if you get them wrong: a **hardcoded address** that drifts from the live registry, and a **decimal mistake** that turns `$8.93` into `$8,930,000` (or back). This page nails both. Every address comes from the on-chain address registry via `@inflexion/sdk`, and every premium, MaxIL, and payout you read is a **6-decimal raw `bigint`** — not a float.

<Note>
  The SDK **hardcodes nothing**. It loads the registry and re-exports typed groups; `createInflexionSdk` never takes an address argument. Import from the package and you inherit the live deployment automatically. See also [Addresses & deployments](/reference/deployments) and [Decimals & units](/reference/decimals-units).
</Note>

## Import addresses — never hardcode

The SDK exports the registry as **typed groups**, plus the chain id constant. Import what you need; do not paste a `0x…` literal into application code (mirrored in [the guardrails](/sdk/guardrails)).

```ts title="import the registry groups" theme={null}
import {
  core,        // InflexionCore, ConvexityVault, UnderwriterVault, OracleManager, volOracle, ilMath
  stylus,      // fairValueOracle (the Φ-sum pricer)
  libs,        // tickMath, cvammPricing, swapMath, quoteVerification (delegatecall-only)
  tokens,      // demoUsdc (numéraire), demoWeth
  demo,        // marketId_fee500_7d, lpPositionTokenId, lifecycle market id
  chainlink,   // ethUsd, btcUsd, arbUsd, usdcUsd (8-dec feeds)
  uniswap,     // factory, swapRouter, quoter
  npm,         // NonfungiblePositionManager
  CHAIN_ID,    // 421614 (Arbitrum Sepolia)
} from '@inflexion/sdk'
```

`CHAIN_ID === 421614` is the default EIP-712 chain id for [quote signing](/integrate/quote-signing).

<Warning>
  **Limit:** these addresses are **Arbitrum Sepolia testnet** values, not Arbitrum One. **Why:** the protocol is live on Sepolia (chainId 421614) — a [fresh full redeploy on 2026-06-05](/reference/deployments). **Mitigation:** never copy a Sepolia address into a mainnet config. When the protocol ships to Arbitrum One, the registry file changes and your imports follow it for free — that is exactly why you import the symbol, not the literal. The mainnet reference feeds are migration references only, never the live deployment.
</Warning>

## The symbol → address → role map

These are the addresses the SDK resolves. The canonical, always-current table lives in [the deployments reference](/reference/deployments); it is reproduced here so you can match an exported symbol to its on-chain role at a glance.

**Network:** Arbitrum Sepolia · **chainId** `421614` · **deploy block** `274081134` (subgraph startBlock) · **deployed** 2026-06-05

## Core protocol

| Contract | Address | Role |
| - | - | - |
| InflexionCore | `0xC19865cF8403F59B8Eca835833aFEe3Aa8DA4848` | Main entry point — quotes, createSwap, settlement |
| ILVault | `0x9f7615Aca943832977CEf3ac1862fD48B87b7664` | Holds LP premiums and protocol IL accounting |
| UnderwriterVault | `0x4Fb459F3393D206c2b7faD7f0fC9C35a78348D64` | Market-maker (Path B) collateral deposits |
| ConvexityVault | `0xDE2fFeBA2E6A18f3A53D43EC0fCCD299158eC30d` | Pooled cvAMM (Path A) underwriter collateral |
| Treasury | `0x96455C9b00D530BD0629b71B674298440328b1Dd` | Protocol fee recipient (also deployer) |

## Stylus & libraries

| Contract | Address | Role |
| - | - | - |
| FairValueOracle (Stylus) | `0x98a6aa75108b70fc0794bc3b87efe0ae99d5d52c` | Rust/WASM fair-premium pricing (set-once init to live VolOracle) |
| ILMath | `0x7e90362bc6Df9cb5faA13952e07853ab16c77bd2` | Core impermanent-loss math |
| TickMath (library) | `0xbf02bbc82e0fb1a4b9828bb90fc9dd9e97578965` | Tick ↔ sqrtPrice conversions (delegatecall) |
| CvammPricing (library) | `0x4a053d29a55a64172140f9ebbc27c321c0ba2b53` | Path-A pool pricing components (delegatecall) |
| SwapMath (library) | `0xf7be9745b6768d06a18c386c6db5c8cb065ba314` | Swap math helpers (delegatecall) |
| QuoteVerification (library) | `0x74819eed322f3e1a2dc10bb0d3cae50078d90807` | EIP-712 quote signature verification (delegatecall) |

## Oracles

| Contract | Address | Role |
| - | - | - |
| OracleManager | `0x2c18147B6ec75dcb330d9A48B6B96a4d1a8b529b` | Chainlink feed router, staleness & sequencer checks |
| VolOracle | `0xfdEafBB381192FC5337499d041eaead04d565Ed9` | Realized-volatility reference (sigma\_ref) |

## Uniswap

| Contract | Address | Role |
| - | - | - |
| UniswapV3Factory | `0x248AB79Bbb9bC29bB72f7Cd42F17e054Fc40188e` | v3 pool factory |
| NonfungiblePositionManager | `0x6b2937Bde17889EDCf8fbD8dE31C3C2a70Bc4d65` | LP position NFTs |
| SwapRouter02 | `0x101F443B4d1b059569D643917553c771E1b9663E` | Swap routing |
| QuoterV2 | `0x2779a0CC1c3e0E44D2542EC3e79e3864Ae93Ef0B` | Off-chain swap quoting |

## Chainlink feeds

| Contract | Address | Role |
| - | - | - |
| ETH / USD | `0xd30e2101a97dcbAeBCBC04F14C3f624E67A35165` | Price feed (8 dec, \~120s heartbeat) |
| BTC / USD | `0x56a43EB56Da12C0dc1D972ACb089c06a5dEF8e69` | Price feed (8 dec, \~120s heartbeat) |
| ARB / USD | `0xD1092a65338d049DB68D7Be6bD89d17a0929945e` | Price feed (8 dec, 86400s heartbeat) |
| USDC / USD | `0x0153002d20B96532C639313c2d54c3dA09109309` | Price feed (8 dec, 86400s heartbeat) |

## Demo tokens / pool / LP

| Contract | Address | Role |
| - | - | - |
| WETH9 | `0x980B62Da83eFf3D4576C647993b0c1D7faf17c73` | Canonical Arbitrum Sepolia WETH (18 dec) |
| USDC (Circle) | `0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d` | Circle native testnet USDC (6 dec) |
| dWETH (demo) | `0xA8C07E1B245B346c5D1910c5055Efe67bF9E7D1D` | Mock WETH, oracle-priced via Chainlink ETH/USD (18 dec) |
| dUSDC (demo) | `0xB89630Dc6e020ae2A84aE72b7d9EEDBDfb2C544d` | Mock USDC numeraire (6 dec) |
| Demo pool (dWETH/dUSDC, fee 500) | `0xfE1Eb4D5796a350B13852F822B3E6a9fDbb858a5` | Seeded v3 pool, tokenId 3218 \~\$100k unprotected LP |

## Lifecycle swaps

| Contract | Address | Role |
| - | - | - |
| Market maker (demo signer) | `0xe632B215120dD43A719458487bA3e03638fec953` | Path-B underwriter; deposited 5,000 dUSDC, own collateral paid settlement |

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.

### Which SDK symbol maps to which row

| Exported symbol | Registry entry | Role in the SDK |
| - | - | - |
| `core.inflexionCore` | InflexionCore | State machine; the **EIP-712 `verifyingContract`** for signed quotes; default spender for `lp.buyProtection` |
| `core.convexityVault` | ConvexityVault | Path-A pooled underwriter; default spender for `depositor.deposit`; equals `swap.mm` on a Path-A swap |
| `core.underwriterVault` | UnderwriterVault | Per-MM Path-B collateral home (`deposited`/`locked`/`available`) |
| `core.oracleManager` | OracleManager | Live entry/settlement price; **reverts** on stale feed / sequencer down |
| `core.volOracle` | VolOracle | σ\_ref EWMA; `sigmaRef` reverts if uninitialised |
| `core.ilMath` | ILMath | Settle-path IL math (`computeIL`/`computeMaxIL`/`getAmountsForLiquidity`) |
| `stylus.fairValueOracle` | FairValueOracle (Stylus) | The exact closed-form [Φ-sum pricer](/math/fair-value-phi-sum) — **never reimplemented off-chain** |
| `libs.tickMath` | TickMath | tick → sqrtPriceX96 (**delegatecall-only**) |
| `libs.cvammPricing` | CvammPricing | The [load stack](/math/load-stack) (**delegatecall-only** — see below) |
| `tokens.demoUsdc` | dUSDC | **Numéraire, 6 decimals** — all premiums/collateral/payouts |
| `tokens.demoWeth` | dWETH | Demo volatile token, **18 decimals**; oracle-priced via real Chainlink ETH/USD |
| `npm` | NonfungiblePositionManager | `positions(tokenId)`, ownership enumeration |
| `chainlink.ethUsd` | ETH/USD feed | Real 8-dec feed the demo prices dWETH against |
| `demo.marketId_fee500_7d` | demo market id | The fee-500 / 7-day demo market |
| `demo.lpPositionTokenId` | `3218` | Seeded \~\$100k unprotected LP NFT for previews |

<Warning>
  **Limit:** the deployed Solidity libraries — `libs.cvammPricing`, `libs.tickMath`, `libs.swapMath`, `libs.quoteVerification` — **revert on a direct `eth_call`**. **Why:** Solidity guards deployed library functions against being called outside a `delegatecall` context; the library image runs only inside `InflexionCore`'s delegatecall during pricing (confirmed on the 2026-06-05 deploy). **Mitigation:** the SDK never reads `CvammPricing` directly. It keeps a parity-locked TypeScript mirror of the load math — the [`cvamm` namespace](/sdk/cvamm-port) — that is byte-equal to the deployed Solidity. The [Φ-sum](/math/fair-value-phi-sum), by contrast, is **read on-chain** from the Stylus FairValueOracle and never duplicated.
</Warning>

## Decimals & units — the load-bearing conventions

Get this table into your head before you write a single read or amount. The single rule: **a field named `*Wad` is 1e18-scaled; a USDC amount is a 6-decimal raw `bigint`; a price is feed-decimal raw unless the field name says `Wad`**.

| Quantity | Scale | What carries it |
| - | - | - |
| **dUSDC** (numéraire) | **6 decimals** | every `maxPremium`, `amount`, `V0`, `maxIL`, `premium`, `payout`, collateral figure — `1 dUSDC = 1_000_000n` |
| **dWETH** (volatile token0) | **18 decimals** | token amounts (`amount0Entry`) |
| **Chainlink price feeds** | **8 decimals** | all four USD feeds |
| **WAD** | **1e18** (= 1.0) | σ\_ref, `fairRateWad`, load components, `aWad`/`bWad` ratios, regime bands |
| **BPS\_TO\_WAD** | **1e14** | one basis point in WAD |
| **sqrtPriceX96** | Uniswap **Q64.96** | the position's sqrt price |
| **SECONDS\_PER\_YEAR** | **31,536,000** | 365-day year, matches the quant model |

<Warning>
  **The single most common integration bug:** treating a 6-decimal premium as dollars. `preview.best === 8_930_000n` means **\$8.93**, not \$8,930,000. **Why:** dUSDC is the 6-decimal numéraire and the SDK returns raw on-chain integers — it never silently converts to a float, because float rounding would corrupt the on-chain `maxPremium` slippage guard. **Mitigation:** format only at the display edge — `Number(premium) / 1e6` for a label, and keep the raw `bigint` for any value you send back on-chain (e.g. `maxPremium`).
</Warning>

### Reading a premium safely

```ts title="6-dec dUSDC: raw bigint in, label out" theme={null}
import { createInflexionSdk, demo } from '@inflexion/sdk'

const sdk = createInflexionSdk({ publicClient })
const preview = await sdk.lp.previewPremium(demo.lpPositionTokenId, demo.marketId_fee500_7d)
if (!preview.priceable) throw new Error(preview.reason)

// preview.best is a 6-dec raw bigint, e.g. 8_930_000n
const usd = Number(preview.best) / 1e6           // 8.93 — DISPLAY ONLY
const label = usd.toLocaleString('en-US', { style: 'currency', currency: 'USD' }) // "$8.93"

// Slippage guard stays in raw bigint arithmetic — never round-trip through a float.
const maxPremium = (preview.best * 10_100n) / 10_000n + 1n   // +1% slippage, round up
```

### WAD ratios and basis points

Loads and rates come back in WAD. To present a load as a percentage, divide by `1e18`; to convert WAD → basis points the SDK exports `wadToBps`:

$$
\text{bps} = \left\lfloor \frac{\text{wad} \cdot 10000}{10^{18}} \right\rfloor
\qquad\qquad
1\ \text{bps} = 10^{14}\ \text{wad}\ (\texttt{BPS\_TO\_WAD})
$$

```ts title="WAD → %, WAD → bps" theme={null}
import { wadToBps } from '@inflexion/sdk'

const totalLoadWad = 1_200_000_000_000_000_000n   // 1.2 in WAD → 120% load
const loadPct = Number(totalLoadWad) / 1e18        // 1.2  (display)
const loadBps = wadToBps(totalLoadWad)             // 12000n
```

<Info>
  Internally the on-chain [Φ-sum](/math/fair-value-phi-sum) lifts WAD to **1e24** for transcendental precision and rounds back to WAD half-up at the ABI boundary. You never see 1e24 — every value the SDK hands you is already at the WAD (1e18) or 6-dec scale.
</Info>

## sqrtPriceX96 conversions

Uniswap v3 stores prices as a Q64.96 fixed-point square root, `\sqrt{P}\cdot 2^{96}`. The SDK gives you both directions you need: **sqrt → human price** and **sqrt bounds → the `a`/`b` ratios** the pricer consumes.

### sqrtPriceX96 → price (WAD)

`sqrtToPriceWad(sqrtPX96)` returns the price of token0 in token1, WAD-scaled:

$$
P_{\text{wad}} \;=\; \left(\frac{\text{sqrtP}_{X96}}{2^{96}}\right)^{2}\cdot 10^{18}
$$

### sqrtPriceX96 bounds → `a`, `b` (the pricer inputs)

The [fair-value oracle](/concepts/fair-value) and the [load stack](/math/load-stack) are **L-independent**: they depend only on the geometry ratios $a = P_a/P_0$ and $b = P_b/P_0$, σ\_ref, and duration. `cvamm.abFromSqrt(sqrtP0, sqrtPa, sqrtPb)` derives them from the position's three sqrt prices:

$$
a \;=\; \left(\frac{\text{sqrtP}_a}{\text{sqrtP}_0}\right)^{2}\!,
\qquad
b \;=\; \left(\frac{\text{sqrtP}_b}{\text{sqrtP}_0}\right)^{2}
$$

Both returned in WAD as `{ aWad, bWad }`. Note the cancellation of the $2^{96}$ factor — `abFromSqrt` is a pure ratio, so it is unit-clean regardless of the Q64.96 scale.

```ts title="sqrt → price, sqrt bounds → a/b" theme={null}
import { cvamm } from '@inflexion/sdk'

// From a resolved LpGeometry (lp.resolveGeometry) you already hold the three sqrt prices.
const { sqrtP0X96, sqrtPaX96, sqrtPbX96 } = geometry

// a = (Pa/P0), b = (Pb/P0), both WAD — the FairValueOracle / load-stack inputs.
const { aWad, bWad } = cvamm.abFromSqrt(sqrtP0X96, sqrtPaX96, sqrtPbX96)

// In-range gate (the createSwap entry condition): Pa ≤ P0 ≤ Pb.
const inRange = sqrtP0X96 >= sqrtPaX96 && sqrtP0X96 <= sqrtPbX96
```

<Tip>
  You rarely call `abFromSqrt` by hand. `lp.resolveGeometry` (and `mm.getPositionGeometry`) already compute `aWad`/`bWad` and the `inRange` flag for you from `NPM.positions(tokenId)` + `TickMath`. The standalone helper is there for when you have raw sqrt prices and want the ratios without a position read — see the [cvAMM port](/sdk/cvamm-port).
</Tip>

### The in-range gate, in price terms

The same condition the SDK derives is the on-chain `createSwap` entry gate — this is what makes it an [in-range convexity hedge, not "IL insurance"](/concepts/in-range-convexity-hedge):

$$
P_a \;\le\; P_0 \;\le\; P_b
\quad\Longleftrightarrow\quad
\text{sqrtP}_a \;\le\; \text{sqrtP}_0 \;\le\; \text{sqrtP}_b
$$

An out-of-range entry is rejected at creation. [MaxIL](/concepts/maxil) — the cap and the unit of risk — is then pure geometry over $a$, $b$, $L$, $P_0$, frozen at creation.

## marketId — derived, not read

A `marketId` is not an address you import; it is **deterministically derived** from the pair, fee, and duration, identical on-chain and in the SDK. The standalone helper is `computeMarketId`:

$$
\text{marketId} \;=\; \texttt{keccak256}\big(\texttt{abi.encodePacked}(\text{token0},\ \text{token1},\ \text{fee},\ \text{durationSeconds})\big)
$$

with `token0 = dWETH`, `token1 = dUSDC` (token0 \< token1 by address), types `(address, address, uint24, uint32)`.

```ts title="derive a marketId (matches InflexionCore.registerMarket exactly)" theme={null}
import { computeMarketId, tokens } from '@inflexion/sdk'

const SEVEN_DAYS = 604_800
const marketId = computeMarketId(tokens.demoWeth, tokens.demoUsdc, 500, SEVEN_DAYS)
// === demo.marketId_fee500_7d for the fee-500 / 7d demo market
```

Because duration is baked into the id, the **same geometry yields a different marketId — and a different price — per duration** (the cvAMM publishes three prices for one MaxIL). The [9-market grid](/reference/markets-grid) is `3 fee tiers × 3 durations`. For the full parity story between on-chain `registerMarket` and the SDK, see [marketId parity](/integrate/marketid-parity).

<Note>
  A `SwapRecord` carries **no marketId** on-chain (it is compact). `resolveMarket(client, swap)` recovers it by reproducing the same `keccak256(...)` from `NPM.positions(tokenId)`. You only need this when scanning historical swaps; live pricing flows already have the marketId in hand.
</Note>

## Quick reference

<CardGroup cols={2}>
  <Card title="Full deployments registry" icon="book" href="/reference/deployments">
    Every live address with its role — the canonical table this page draws from.
  </Card>

  <Card title="Decimals & units reference" icon="ruler" href="/reference/decimals-units">
    The numéraire conventions, WAD/bps constants, and Q64.96 internals in one reference page.
  </Card>

  <Card title="The cvAMM math port" icon="calculator" href="/sdk/cvamm-port">
    `abFromSqrt`, the load stack, and why the off-chain mirror is parity-locked to the delegatecall-only library.
  </Card>

  <Card title="Getting started" icon="rocket" href="/sdk/getting-started">
    Wire `createInflexionSdk` for the browser (wagmi) or a server (key-based) and read your first premium.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.