Settlement & the Pyth oracle
How Phasis halts trading at expiry, reads the Pyth EMA price on-chain, and distributes intrinsic-value payouts to all accounts.
Settlement converts open positions into USDC payouts. It is fully on-chain and driven by the cranker keeper — no user action is required to receive a payout.
The settlement price
At expiry, the protocol needs one authoritative price for the underlying asset. Phasis reads the Pyth Lazer EMA price via the on-chain function:
pyth::get_ema_price_no_older_than(state, feed_id, max_age, clock)| Parameter | Value |
|---|---|
state | Pyth Lazer state shared object (see Addresses). |
feed_id | Integer feed ID: BTC = 1, ETH = 2, SUI = 11. |
max_age | Maximum staleness in milliseconds (e.g., 3_600_000 for 1 hour). Aborts if the latest price is older. |
clock | Sui shared clock (0x6). |
The function returns a Price { price, conf, exponent }. The human-readable price is price × 10^exponent. For example, { price: 6_500_000, exponent: -2 } represents $65,000.
If the Pyth price is stale or unavailable, the cranker first attempts to read a settle price from the DeepBook Predict oracle (an on-chain SVI surface seeded from external IV data). The admin holds an emergency escape hatch to force-publish a settle price if both oracles are unavailable, but this path requires multi-sig authorization.
The seven-step crank sequence
Settlement proceeds in a fixed state-machine sequence. Each step is a separate on-chain transaction submitted by the cranker.
Step 1 — halt
Condition: now ≥ expiry_ts − halt_window_ms
Transition: Market.state: Listed → Halted
Effect: No new orders accepted for any series in this market.The halt window is set at market creation (typically 60 minutes before expiry). This gives the oracle time to reach finality before positions are evaluated.
Step 2 — publish settle price
Condition: Market.state = Halted
Transition: Market.state: Halted → Settling
Effect: Market.settle_price = Pyth EMA price (or Predict oracle price)The cranker calls auth_entry::cranker_settle_price (Pyth fallback) or auth_entry::cranker_settle_price_from_predict (primary path). Once the settle price is on-chain, it is immutable.
Step 3 — mark series settling
For each series in the market:
Effect: SeriesRow.state: Active → RetiredAwaitingSettle
SeriesRow.intrinsic_value = max(0, settle_price − strike) [call]
= max(0, strike − settle_price) [put]Intrinsic value is computed once and stored on-chain. Subsequent steps read this stored value; the oracle is not consulted again.
Step 4 — settle each user position
For each (account, series) pair with an open position:
For longs: credit = position_qty × intrinsic_value
For shorts: debit = position_qty × intrinsic_value
Applied to: Account.balance_quoteIf an account's balance goes negative after the debit (undercollateralized), the protocol's fee pool covers the shortfall as bad debt. The position is removed from the account regardless.
Step 5 — retire series
Once SeriesRow.open_interest == 0 (all positions settled):
Effect: Slot coin freed; slot returned to registry.free_slots for reuse.
SeriesRow removed from Market.series_rows.Step 6 — retire market
Once all series in the market are retired:
Transition: Market.state: Settling → Closed
Effect: Market archived; new market for the next expiry can be listed.Typical weekly timeline
For a BTC weekly market expiring Friday at 4:00 pm UTC:
| Time (UTC) | Event |
|---|---|
| Friday 3:00 pm | Cranker calls cranker_halt — market halted. |
| Friday 3:05 pm | Settle price published (Predict or Pyth EMA). |
| Friday 3:05–3:30 pm | Cranker iterates all (account, series) pairs and settles positions. |
| Friday ~3:30 pm | All series retired, market closed. |
| Saturday | New market listed for the following Friday expiry. |
No user action required
Settled USDC lands directly in Account.balance_quote. Users can withdraw at any time after their positions are settled. The cranker handles the full sequence autonomously; users do not need to submit any transaction to receive their payout.
For the oracle feed IDs and shared object addresses used on testnet, see Addresses & object IDs.
Portfolio margin: the N-point stress grid
How Phasis computes margin requirements — worst-case PnL across N Black–Scholes price scenarios, with no per-leg isolation and zero lock for long-only and debit-spread portfolios.
Liquidation & keepers
How Phasis liquidates undercollateralized accounts — whitelisted keeper bots, the on-chain underwater check, and the IOC market-order close flow.