CLOB (OpshunsClob)
Each options market is an OpshunsClob clone: an ERC-6909 book for a fixed token0 / token1 / premium triple. The mothership OrdersFacet is the user-facing entry for posting, claiming, exercising, and settling shorts. RFQ fills also settle into the same clone via bilateral fillMatched.
For RFQ fill modes (leg-by-leg, FixedPackage, Dutch, Authority), see On-chain fill modes. Building your own matching stack? Call the CLOB directly or Settle matched intents with your own RFQ. Contract helpers: TypeScript SDK (opshunsMothership, orderBuy / orderSell).
What the book is
| Concept | Role |
|---|---|
| Pair / CLOB address | Factory-deployed clone for one underlying pair + premium token |
| PairKey | Option terms packed into a bijective ERC-6909 id (premiumTick, strikeWad, exercise window, min notional) |
| Long inventory | Fungible buyId for the series (filled inventory clears premium; see below) |
| Short inventory | 0xF2… short-lot NFTs (fungible sellId supply stays 0; sellId is terms only) |
| Resting queues | Per-tick FIFO bids (premium) and asks (underlying); remainder enqueues as order NFTs (0xF0… buy / 0xF1… sell) |
| Ladder | Tick bitmap keyed by optionKey (PairKey with premium cleared) for cross-premium discovery |
Ids are a fixed bit layout (not a hash): same terms → same pool ids; decode recovers terms bit-for-bit. Full prefixes and counters: ERC-6909 token id namespaces. Premium encoding: Premium ratio.
Posting orders (mothership)
Typical flow:
Wallet → OrdersFacet.orderBuy / orderSell (+ optional Permit2)
→ clone orderBuy(Referral) / orderSell(Referral)
→ optional WouldTake / postOnly check
→ cross resting opposite side (hinted tick or ladder walk)
→ enqueue remainder (buy order NFT 0xF0… / sell order NFT 0xF1…)
→ matched sell size mints short-lot NFT (0xF2…)
- Buy posts premium against the book.
- Sell posts underlying.
- Args include
postOnly(revert withWouldTakeif the order would immediately cross) andLadderHint(prevTick/nextTick) to seed bitmap insertion / matching. - Min-notional floors apply on CLOB posts (
BelowMinNotionalif too small). RFQfillMatchedskips that gate. - Trailing
referreronorderBuy/orderSellis chosen by the caller. RFQ and FixedPackage bind it insidetakerAddressHashinstead. See Fees.
The trading app’s Post to book path for a single call/put talks to this stack. REST helpers: Orders & exclusive fills.
Matching vs RFQ
Two different ways liquidity clears into the same 6909 inventory:
Resting book
Makers (or any wallet) leave standing bids/asks at a discrete premiumTick. Crosses happen when a counterparty posts. The clone walks the tick bitmap ladder (optionally seeded by LadderHint) to find opposing liquidity across ticks.
Bilateral fillMatched
RFQ / package settlement after the mothership has already pulled ERC-20 premium + underlying:
Settle RFQ
fillMatchedafter mothership has pulled premium + underlying into this core… No ERC-20 pulls. mint + pool accounting only.
- Does not advance live queue cursors (bilateral mint; no claim queue).
- Inventory RFQ, FixedPackage, and Dutch all
fillMatchedwithpremiumTick = 0. Cash premium, when there is one, is the package amount settled first. Premium-tick math is for the resting book: Premium ratio.
Filled inventory shares one bucket
Resting order ids keep the full premium tick (each level is its own FIFO queue). Filled longs and short-lot terms clear premium → one series id per strike / window / type. A zero-premium fill and a premium fill of the same strike therefore land in the same buyId / filledStates bucket. Details: token ids.
RFQ does not take the book
Inventory executeIntent and package / Dutch legs settle with bilateral fillMatched at premiumTick = 0. There is no per-leg option premium and no ClobOffer slice that lifts resting bids or asks. Resting liquidity is taken only when someone posts orderBuy / orderSell on the premium book.
FixedPackage and Dutch pull an absolute package premium first, then the same zero-premium fillMatched.
Lifecycle after mint
Once you hold 6909 inventory you can:
- Claim / manage queued order NFTs (
0xF0…/0xF1…) - Exercise longs (
buyId): American anytime before expiry whenstartExerciseTimestamp == 0; European-style when start equals expiry - Settle shorts via
settleShort(lotId)on the short-lot NFT (0xF2…): early full-assignment strike, or post-expiry strike + unassigned underlying (burn-settle)
Exact selectors are on OrdersFacet / IOpshunsClob. Prefer mothership entrypoints so approvals and fees stay consistent. Id prefixes: token id namespaces.
Fees
CLOB, RFQ, and package fills share one set of treasury powers. A resting order pays maker-post on the size that queues (kept on cancel). The fill cuts a protocol fee out of the posted amount: taker rate on an immediate cross, half that rate when the resting maker is filled. Default rates, the same-currency cap, and who sets referrer: Fees.
Integrator tips
- Resolve the pair address from the factory / networks registry (
opshuns6909_contractin quote intents). - Predict ids with mothership
resolvePairKey/ clone helpers so off-chain books match on-chain packing (min-notional sentinels are materialized before packing). - Approve the mothership for ERC-20 pulls (or use Permit2 witnesses), not only the clone.
- Standard ERC-20 only. no fee-on-transfer or rebasing tokens.
- Index portfolio by series (
optionKey), not by resting premium tick: fills collapse premium.
Related
- ERC-6909 token id namespaces. pool vs
0xF0/0xF1/0xF2ephemeral ids - Premium ratio: tick math and WAD settlement
- TypeScript SDK:
@opshuns/sdk(opshunsMothership, native router) - Call the CLOB directly. post
orderBuy/orderSellfrom your own system - Settle matched intents with your own RFQ. bilateral FillMatched after your RFQ match
- On-chain fill modes. FillMatched, Dutch, Authority
- Fill options RFQ quotes. API RFQ lifecycle
- Orders & exclusive fills: REST order recording / exclusive fill bonds
- Option spreads. multi-leg strategy shapes