

Two estimator pipelines, one launch-scaled index.
Push oracle
The index is fed by a push oracle. The market’s price feed, a signed relayer service that reads the collectible’s real prices from marketplaces and filters manipulation (see Oracle Architecture), submits it with thepush_index instruction, signed by the oracle authority key stored in the global config. No other signer can push.
Each push carries a single price_lamports value for the whole unit, already launch-scaled by the feed. The first push at launch is 625_000_000 (0.625 SOL); for a collectible that has since doubled, the push is 1_250_000_000.
Four gates apply before a push is absorbed:
- Not frozen: a frozen market refuses pushes entirely, so the index cannot be walked during a freeze. See Circuit Breaker.
- Non-zero:
price_lamports > 0, otherwise the push is rejected. - Rate limit: at least
min_push_interval_secsmust have elapsed since the previous push. The first push for a market is exempt. - Circuit breaker: the push is compared against the current TWAP. If it deviates by more than
breaker_bps, the market freezes instead of absorbing the value.
TWAP smoothing
Accepted pushes do not overwrite the index directly. The market stores two values:index_last_raw: the most recent accepted observation, kept for transparencyindex_twap: the smoothed index every risk check actually uses
The very first push for a market seeds
index_twap directly with the observed price. There is no history to average against yet, and most instructions refuse to run until an index exists.What consumes the index
The index is the valuation leg for every solvency computation. Token amounts are converted to lamport value with:Staleness guard
An index is only as good as its freshness. Every market recordsindex_last_ts, the time of the last accepted push, and when max_index_age_secs is set (non-zero), index-priced operations refuse to run against an index older than that:
open_shortwithdraw_collateralwhen the position still has debtaccrue_fundingliquidate
IndexStale until the next accepted push, at which point everything resumes with no reset needed. Trading (curve and AMM), repay_burn, and add_collateral stay available throughout, so nobody is trapped: shorts can still de-risk, and holders can still exit through the pool.
This bounds the damage of a dead relayer: prices stop being trusted after the configured age instead of being trusted forever. Set max_index_age_secs comfortably above the relayer’s push cadence (see Parameters); 0 disables the guard, which is only appropriate for testing.
Instruction and event surface
- Instruction:
push_index(price_lamports), oracle authority only, see Instructions - Emits
IndexPushed { market, raw, twap }on absorption, orBreakerTripped { market, observed, twap }on a breaker hit, see Events - State fields:
index_twap,index_last_raw,index_last_tson the Market account
push_mark, smoothed the same way over mark_window_secs. The mark only steers funding; it never enters collateral or liquidation math, which always use the index documented here.
