Markets & series
How Phasis organizes tradeable instruments — one market per (underlying, expiry), one series per (strike, call/put), each backed by its own embedded DeepBook orderbook.
Phasis organizes tradeable instruments in a two-level hierarchy: markets and series.
Markets
A market represents a single expiry event for one underlying asset. It is identified by the pair (underlying_asset, expiry_timestamp).
Market = (BTC, 2026-06-27 16:00 UTC)
Market = (ETH, 2026-06-27 16:00 UTC)
Market = (SUI, 2026-07-25 16:00 UTC)A market is a Sui shared object with the following lifecycle states:
| State | Meaning |
|---|---|
Listed | Market is live; new orders accepted. |
Halted | Trading stopped; halt window before expiry. No new orders. |
Settling | Settle price published; cranker iterating over positions. |
Closed | All positions settled; market archived. |
The halt window (typically 60 minutes before expiry) gives the settle-price oracle time to publish before positions are evaluated.
Series
A series is one tradeable strike-and-side combination within a market. It is identified by (strike, is_call).
Series = (BTC × 2026-06-27 16:00 UTC, $70 000 call)
Series = (BTC × 2026-06-27 16:00 UTC, $70 000 put)
Series = (BTC × 2026-06-27 16:00 UTC, $65 000 call)Each series embeds its own DeepBook v3 orderbook (a Book<SlotCoin, USDC> pool in book-only mode). The orderbook is stored directly inside the Market shared object, avoiding any cross-package dependency for matching. Bids and asks in different series never interact — each series is an isolated, continuous double-auction market.
Key fields on each SeriesRow:
| Field | Type | Description |
|---|---|---|
strike | u64 (UD30×9) | Strike price in protocol fixed-point. |
is_call | bool | true = call, false = put. |
series_id | ID | Unique identifier for this series. |
open_interest | u64 | Sum of absolute net position magnitudes across all accounts. |
fair_price | u64 (UD30×9) | Mid-market price from the latest stress snapshot. |
intrinsic_value | u64 (UD30×9) | Set to the settle price payout at expiry; zero while trading. |
Typical market breadth
The MVP testnet deployment targets:
- 3 underlyings: BTC, ETH, SUI
- 2 expiries per underlying: next weekly Friday + next monthly Friday
- 5 strikes per expiry: ATM and ±1σ, ±2σ around spot
- 2 sides: call + put
This yields 60 concurrent series on a single deployment, each with its own independent orderbook.
Listing a new market
Listing is a two-step admin operation.
Step 1 — list the market:
auth_entry::list_market(registry, asset, expiry_ts, halt_window_ms)This allocates the Market shared object and sets its state to Listed.
Step 2 — list each series:
auth_entry::list_series_v2(registry, market, strike, is_call, slot_id)This pops a free slot coin from the registry's slot pool, initializes the embedded DeepBook pool, and inserts a SeriesRow into the market.
Reading markets from the SDK
const market = await getMarket(client, marketId);
// market.series: SeriesView[] = [
// { strike, isCall, expiryTs, fairPrice, intrinsicValue, seriesId, oi },
// ...
// ]The SeriesView list is ordered by strike ascending, calls before puts. Frontend components iterate this list to render the option chain. See Addresses & object IDs for the canonical market object IDs on testnet.
Architecture overview
How Phasis is structured — on-chain Move core, Rust keeper layer, TypeScript SDK, and Next.js frontend, and how they interact.
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.