Pricing & Oracles
This page explains how Paragon prices assets across swaps, farms, stXPGN, and the upcoming index tokens (P10). Our goals are: fair execution, manipulation-resistance.
What we price (and why it matters)
Swaps & Routing — routers/solvers need reliable quotes to set
minOut
, detect bad routes, and compute surplus for rebates.Pool UI & APRs — TVL/APR/earned stats use reference USD prices.
stXPGN Vault — uses price guards on deposits/withdraws if the underlying is volatile.
Index Tokens (P10/P50/P100/L1-10) — mint/redeem at NAV derived from a basket of oracle prices; reweights/reconstitutions require consistent feeds.
Source of truth (three layers)
External Oracles (Primary)
Chainlink (OCR v3 style) — majors & stables.
Pyth/Redstone (Secondary) — faster cadence; used if Chainlink is stale or missing.
Rules:
Liveness: heartbeat not older than
Tmax
(majors: 60m; stables: 10m; long-tail: 6h).Deviation: ignore updates that jump more than
Dmax
from last accepted (majors: 3–5%; long-tail: 10–20%) unless corroborated by ≥2 sources.
On-chain TWAP (Safety Net)
For pairs traded on Paragon, we maintain a v2 cumulative TWAP (e.g., 10–30 minutes window).
Used when external feed is unavailable or as a sanity cross-check (reject quotes if oracle vs TWAP deviates by >
X%
).
Spot (Never alone for settlement)
Raw AMM spot is used only for quoting and path-search inside a block. It is not a settlement reference without TWAP/oracle guards.
Invariant: any price used for value transfer (e.g., index mint/redeem, vault safeguards) must pass: freshness + deviation + cross-check.
Guards & Circuit Breakers
Freshness check — feed must be newer than
Tmax
.Deviation check — abs(oracle − last_accepted)/last_accepted ≤
Dmax
.Cross-check — if TWAP exists: abs(oracle − TWAP)/TWAP ≤
X%
(majors: 5–8%).Stablecoin depeg guard — if a “stable” deviates > 2–3% from $1 for
N
consecutive checks, mark degraded and widen slippage/quoting bands or disable mint/redeem that depends on it.Global sentinel — if >
K
feeds go stale or fail checks, contracts enter protect mode (halts sensitive ops like index mint/redeem; swaps still work with wider slippage, no oracle settlement).
How routing uses prices
Intent settlement: solvers compute best route using pool math + gas; external oracles are used only to:
Detect pathological routes (e.g., price 20% away from reference).
Bound
minOut
for Proof-of-Best-Execution (PoBE) and surplus calculation.
Surplus accounting uses executed outputs vs user minOut; reference oracles cap abuse (e.g., artificially low minOut from a stale quote).
Index tokens: P10 / P50 / P100 / L1-10
Goal: mint/redeem at on-chain NAV from a basket of prices.
Basket specification
Universe: e.g., Top-10/50/100 by free-float market cap; L1-10 by curated list.
Weights: market-cap-weighted (cap with per-asset max 25%) or equal-weight (safer to start).
Reconstitution: weekly (testnet) / monthly (mainnet), based on a snapshot block + off-chain list signed by governance (or an on-chain registry fed by a keeper).
NAV calculation (on-chain)
Per asset i:
p_i
(medianized oracle),w_i
(weight),dec_i
.Index NAV (1e18):
NAV = Σ_i ( w_i * p_i_normalized )
, whereΣ w_i = 1
.Mint price =
NAV * (1 + mintFeeBps)
subject to slippage & guard rails.Redeem price =
NAV * (1 − redeemFeeBps)
.
Mint/Redeem mechanics (two launch paths)
A) Basket-backed (purist ETF)
User deposits underlying tokens (any subset). Router zaps missing ones via DEX, then mints P10 at NAV.
Redeem burns P10 and returns the proportional basket (with optional “all USDT” zap).
Pros: full backing, no tracking error. Cons: more on-chain swaps; needs deep liquidity for long-tail constituents.
B) Synthetic with Backing-Range (fast to ship)
Treasury (or a set of permissionless keepers) maintains a Backing Vault that holds a basket within ±
ε
of target weights.Mint/redeem at NAV within caps; if vault drifts beyond
ε
, arbitrage/keepers rebalance using on-chain trades.Pros: efficient gas, simpler UX; still decentralized if keepers are open & incentivized. Cons: small tracking error between rebalances.
Testnet recommendation: ship (B) now. Add (A) as an opt-in path per asset where deep liquidity exists.
Oracle set for indices
Primary Chainlink; Secondary Pyth/Redstone; TWAP cross-check on our pairs.
Aggregation: median of available sources after removing outliers by MAD or deviation threshold.
Staleness gates: if any constituent is stale, reduce mint cap or disable mint until refreshed; redemptions remain open (safety first).
Contract architecture (concise)
OracleHub
Registry of feeds per asset.
Functions:
latestPrice(asset)
,isHealthy(asset)
,twap(pair, window)
.Medianizes external sources, applies guards, exposes 1e8 or 1e18-scaled prices.
FlowSettlement
(swaps)Uses
OracleHub
for guardrails only; not a price-setter.Surplus computed from execution, not oracle.
IndexRegistry
Stores current basket, weights, caps, and reconstitution schedule.
IndexOracle
Combines
(OracleHub, IndexRegistry)
to compute NAV.Emits
NavUpdated
for off-chain mirrors.
P10Token
(ERC-20)mint(recip, amountIn, tokenIn, minP10Out)
via zap, price-checked byIndexOracle
.redeem(amountP10, outToken)
w/ guardrails.Caps per tx/block, pausability via sentinel.
Manipulation resistance
Flashloan-safe: TWAP windows (≥10m for majors, ≥30m for thin pairs) + external oracle cross-check.
Back-running protection: intents + batch auctions (Paragon Flow) reduce sandwich risk.
Circuit breakers: freeze mint when deviation > threshold or feeds stale; always allow redeem (graceful unwind).
Developer notes
Decimals & scaling: normalize all prices to 1e18 internally; store feed decimals to avoid rounding drift.
Fee accounting: index mint/redeem fees in bps; send a slice to Treasury + stXPGN lockers.
Upgrades: oracles/weights are updatable via timelocked governance; emergency sentinel is isolated & rate-limited.
Testnet plan (next 3–4 weeks)
Stand up OracleHub with:
Mock Chainlink/Pyth feeds (configurable heartbeat & deviation).
TWAP library for Paragon v2 pairs.
Ship P10 (synthetic) with equal weights across 10 majors; weekly reconstitution by keeper.
Caps: daily mint cap, per-tx cap; disable on stale feed; always-on redeem.
UI: show NAV, slippage guard, oracle status badges (Fresh / Stale / Degraded).
Auditable events:
PriceUsed
,NavComputed
,MintExecuted
,RedeemExecuted
,OracleDegraded
.
What users see
On the swap: “Best execution + oracle-guarded” and a savings (surplus) badge.
On P10: Live NAV, Constituents, Rebalance in Xd, Oracle status.
On Pools: APRs sourced from the same normalized price map.
TL;DR
Primary: Chainlink; Secondary: Pyth/Redstone; Fallback: Paragon TWAP.
Guards: freshness, deviation, cross-check, stable depeg sentinels.
Indices: mint/redeem at oracle-guarded NAV, with reconstitution & caps.
Testnet: ship synthetic P10 + robust oracle guards now; expand to basket-backed where liquidity supports it.
Last updated