The naming rule is mechanical: a field whose name ends in
Wad is 1e18-scaled
fixed point (1e18 = 1.0). A USDC amount is a 6-decimal raw bigint. A
price is a feed-decimal raw integer unless the field name says Wad.The numéraire conventions table
Why three different worlds (6 / 18 / 8) coexist
These are not arbitrary — each scale is fixed by an external system Inflexion does not control:6 — the token's own decimals
dUSDC mirrors Circle’s native USDC, which is a 6-decimal ERC-20. The numéraire
must match the token contract or transfers would be off by 12 orders of
magnitude.
18 — the token's own decimals
dWETH mirrors WETH, an 18-decimal ERC-20. token0 < token1 by address, so
token0 = dWETH and token1 = dUSDC (see the markets grid).8 — Chainlink's convention
Every Chainlink USD aggregator on Arbitrum reports an 8-decimal
answer. This is
their convention, not ours; the OracleManager consumes it
as-is.a = Pa/P0 /
b = Pb/P0 ratios are all dimensionless rates, so they live in WAD where
1e18 = 1.0. This is why a *Wad suffix is load-bearing: it tells you the value
has already been normalised out of token-decimal space.
WAD, basis points, and the rate stack
Every rate Inflexion publishes —fairRate, each load component, σ_ref — is a WAD
value. The conversion BPS_TO_WAD = 1e14 bridges the on-chain basis-point inputs
(an MM signs a loadBps; the I10 cap is a maxLoadBps) into the WAD math:
The constants are exported directly from the SDK’s parity-locked load-stack port:
loadBps = 1000, the value on the live Path-B swap — see
lifecycle) converts to WAD as
1000 × 1e14 = 1e17 = 0.10 in WAD. The load stack then computes:
loadBps and maxLoadBps are the basis-point twins of the WAD load values —
the same quantity in two units. The on-chain I10 cap is expressed in bps
(maxLoadBps) and as a rate (maxLoad); see the load stack
and the invariants.sqrtPriceX96 and the Q64.96 fixed-point world
Uniswap v3 stores price as asqrtPriceX96 — the square root of the price of
token0 in token1, scaled by :
This is a uint160 carrying a 96-bit fractional part — the “Q64.96” format (64
integer bits, 96 fractional bits). Inflexion’s settle-path IL math
(ILMath) runs entirely in Q64.96 so it never touches
floating point: computeMaxIL, computeIL, and getAmountsForLiquidity are pure
Q64.96.
The FairValueOracle 1e24 scale
The Stylus FairValueOracle speaks WAD on its ABI but computes internally in 1e24. Stylus bans WASM floating point at activation, so every transcendental in the Φ-sum (erf/Φ, exp, ln, sqrt) is integer fixed point; the contract lifts its WAD inputs to 1e24 for headroom and rounds the result back to WAD half-up.You never see 1e24 from the outside. The FVO takes WAD inputs (
a, b, σ_ref via
STATICCALL) and returns a WAD fairRate / a numéraire-scaled FairPremium. The
1e24 lift is an internal precision device that keeps the Φ-sum machine-precise to
≤ 1e-12 — it is not part of any ABI you call. Treat the FVO as a WAD black box and
read the Φ-sum page for the math.SECONDS_PER_YEAR and time
σ_ref and the time-to-expiry are both annualised over a 365-day year: This value is shared by the on-chain VolOracle and the Stylus FVO, and it matches the Python quant model — so the annualisation is identical across the off-chain research notebook, the vol oracle, and the pricer. The market durations feed into as raw seconds:7d = 604,800, 30d = 2,592,000,
90d = 7,776,000 (see the markets grid).
Durations are stored as raw seconds and are part of the
marketId preimage
(uint32 durationSeconds). The fairRate S-curve is a function of ,
so the same geometry produces a different price per duration — which is exactly why
the 9 markets exist. See MaxIL and
the markets grid.Practical conversions
Worked, copy-pasteable conversions for the four scales you actually touch.- USDC (6-dec) ⇄ dollars
- WAD (1e18) ⇄ rate
- Chainlink (8-dec) → numéraire
- sqrtPriceX96 → human price
dUSDC, MaxIL, premiums, V0, and payouts are 6-decimal raw
bigints. The live
Path-A swap (swapId 1) had V0 = 270,531.28 and MaxIL = 1,669.24 (see
lifecycle). On the wire those are:Common pitfalls
Treating a *Wad field as a USDC amount (or vice-versa)
Treating a *Wad field as a USDC amount (or vice-versa)
A
fairRateWad of 847000000000000000n is 0.847, not “847 quadrillion USDC.”
Check the field name: *Wad ⇒ divide by 1e18; a plain dollar amount ⇒ divide by
1e6. The SDK encodes this in its type comments.Forgetting the 18-vs-6 decimal gap in prices
Forgetting the 18-vs-6 decimal gap in prices
A price derived from
sqrtPriceX96 or from raw token reserves is in raw token
units and is off by 10^(18−6) = 10^12 from a human ETH/USD figure. Always
apply the decimal-gap adjustment for display.Assuming Chainlink is 18-decimal
Assuming Chainlink is 18-decimal
Chainlink USD feeds on Arbitrum are 8-decimal, not 18. The
OracleManager consumes the 8-dec answer directly.
Using a 360-day year
Using a 360-day year
σ_ref and annualise over 365 days (
SECONDS_PER_YEAR = 31,536,000). A
360-day convention would silently mis-scale every fairRate. The on-chain VolOracle,
the Stylus FVO, and the Python model all agree on 365.See also
Deployments
The live Arbitrum Sepolia registry — token addresses with their decimals.
Markets grid
The 9 markets, fee tiers, and the duration-in-seconds values.
SDK addresses & units
How the SDK exposes these constants and loads the on-chain address registry.
The Φ-sum
Where the WAD → 1e24 lift and the half-up rounding live.