Market-maker spline live surface#
This document describes the current canonical spline implementation. It is
derived from program/src/instruction.rs, program/src/state/spline.rs,
program/src/logic/spline/, and the spline processors. It intentionally does
not describe the retired per-market registry or region-based ABI.
Model#
A spline is one creator-owned, compiled quote account. It contains up to 16
bid and 16 ask CurveLevel entries. Each level stores an inclusive endpoint,
an integer price offset, and reserved bytes. The matching path evaluates the
compiled levels as discrete piecewise-constant tick liquidity; it does not
evaluate a polynomial or a shared market-wide spline registry.
The spline identity is:
["seesaw", "spline", feed_id, duration_seconds.to_le_bytes(), creator]
The vault identity is:
["seesaw", "spline_vault", spline]
There is no live SplineRegistry, no eight-maker registry tail, and no
permissionless auto-attach flag in the canonical surface. One spline can be
attached to at most one market at a time, and only its creator/quote authority
may mutate its shape or midpoint.
Account layout#
SplineAccount is exactly 896 bytes, version 1, with discriminator
SPLINE\0\0. Its fixed layout is defined by the compile-time assertions in
program/src/state/spline.rs.
Important fields are:
| Field | Meaning |
|---|---|
creator | Permanent creator and default authority |
quote_authority | Authority allowed to publish midpoint updates |
feed_id, duration_seconds | Series identity |
market, market_id, attached_at | Current attachment, or zero when detached |
sequence, generation | Replay and shape-generation protection |
mid_price_bps | Current midpoint |
max_quote_age_seconds, last_update_unix | Quote freshness policy |
bid_levels, ask_levels | Compiled curve levels |
consumed_bid_lots, consumed_ask_lots | Persistent fill counters |
committed_collateral, yes_inventory, no_inventory | Solvency and recovery accounting |
All decoders require exact size, discriminator, version, owner, PDA, bump, and
zero reserved bytes. The source-level TickRegion helpers retained in formal
and differential tests are legacy test oracles; the live order path loads
CurveLevel state and does not traverse those helpers.
Canonical instructions#
The discriminators and wire sizes are authoritative in
program/src/instruction.rs and spec/IX.md.
| Instruction | Discriminator | Payload | Purpose |
|---|---|---|---|
RecoverSpline | 0x30 | 0 bytes | Creator-only recovery of unresolved spline inventory |
InitSpline | 0x40 | 409 bytes | Create the creator-owned spline and vault |
UpdateSplineShape | 0x41 | 366 bytes | Replace compiled bid/ask levels and shape policy |
UpdateSplineMid | 0x42 | 23 bytes | Publish the next midpoint quote |
AttachSpline | 0x43 | 8 bytes | Attach to one compatible market and commit collateral |
SettleSpline | 0x44 | 0 bytes | Settle inventory and detach |
DepositSplineVault | 0x45 | 8 bytes | Deposit idle collateral |
WithdrawSplineVault | 0x46 | 8 bytes | Withdraw uncommitted collateral |
CloseSpline | 0x47 | 0 bytes | Close a detached, empty spline |
UpdateSplineMid is encoded as:
sequence:u64-le
expected_generation:u32-le
quote_origin_unix:i64-le
new_mid_price_bps:u16-le
active:bool:u8
The payload is exactly 23 bytes after the discriminator. sequence must be
the checked successor of the stored sequence; u64::MAX cannot wrap or be
reused. The expected generation, quote origin, freshness bound, midpoint
range, and bid/ask offset bounds are all checked before state mutation.
RecoverSpline is the sole canonical, creator-authorized manual recovery
instruction for unresolved native or external spline inventory. It validates
the creator, unresolved state, destination mints, and inventory before each
token CPI and rejects replay. It is not an automatic repair or publisher
action. If a later CPI fails, the complete instruction rolls back atomically.
Attachment and matching#
AttachSpline validates the feed, duration, market state, settlement mint,
creator authority, shape, and commitment bound before moving collateral. The
attachment stores the market identity and freezes the quote-grid parameters
needed by matching.
PlaceOrder consumes the spline accounts through the current canonical
account grammar. It validates each writable spline against the market and
series, rejects stale/inactive quotes, and applies persistent per-level lot
counters. Book liquidity and spline liquidity are merged deterministically;
equal-price ties follow the documented order priority. No off-chain crank is
required for a fill or settlement state transition.
The commitment calculation covers aggregate and fragmented per-lot execution
rounding. Inventory, market totals, vault balances, and fees are checked before
token movement. SettleSpline retires each side's inventory once, returns the
terminal payout and unused commitment, and clears attachment state. A repeated
settlement is an idempotent no-op. CloseSpline requires detached state and an
empty vault.
SDK and generated-surface parity#
The TypeScript, Rust, Python, and CLI builders use the same canonical names,
payload sizes, PDA seeds, account order, and optional recorder-tail grammar.
Generated IDL is validated against spec/launch/contract.json; the dedicated
IDL test also checks that UpdateSplineMid sums to the 23-byte Rust payload.
No SDK should expose SplineRegistry, eight-maker slots, region payloads, or
V2 instruction names. Historical audit files may mention those names, but
public SDK/reference documentation must not present them as supported.
Operational limits and remaining verification#
Before production signoff, release validation must still provide sustained publisher/load measurements, packet and account-size envelopes, restart-safe publisher replay/resynchronization, full cross-client package parity, and a green launch-contract/document-generation gate. Focused Rust/BPF, SDK, IDL, indexer, and spline-core tests are necessary but are not by themselves a production-readiness claim.