> For the complete documentation index, see [llms.txt](https://gitbook.hashpower.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.hashpower.io/perpetuals/options_design.md).

# OPTIONS\_DESIGN

Yes. A workable design is a **fully onchain order book for option contracts whose underlying is a perp mark/index**, with margin, risk, matching, and settlement all enforced onchain. The key is to keep the market model simple and deterministic: options are separate listed instruments, the underlying is the protocol’s perp reference price, and collateral is managed through a portfolio margin engine that understands option Greeks and perp hedges.

### Architecture

The cleanest layout is a modular protocol with five contracts:

| Module            | Role                                                                          |
| ----------------- | ----------------------------------------------------------------------------- |
| MarketRegistry    | Defines option series, tick sizes, expiries, exercise style, quote asset      |
| MarginEngine      | Holds collateral, computes IM/MM, tracks portfolio Greeks and health          |
| OrderBook         | Stores price levels, queues, order ids, and enforces price-time priority      |
| MatchingEngine    | Executes taker orders against resting orders and calls settlement             |
| Oracle/RiskOracle | Supplies perp mark, index, funding-adjusted reference, IV surface/risk params |

Each listed option is a market like `BTC-PERP-CALL-120000-2026-06-26`, but the underlying reference is the perp mark or index chosen in `MarketRegistry`. That avoids spot custody assumptions and makes hedging natural for market makers already trading the perp.

### Instruments

I would list **European cash-settled options on the perp reference** rather than physical delivery into a perp position. Cash settlement is much simpler and avoids creating a second risk jump at expiry. The payoff uses the final settlement reference $$S\_T$$, derived from a TWAP/TWMP over the perp index or mark, and pays in quote collateral.

Suggested market definition:

```solidity
struct OptionSeries {
    uint64 seriesId;
    bytes32 underlyingId;      // BTC-PERP
    uint64 expiryTs;
    uint64 strikeE8;           // strike in 1e8
    bool isCall;
    uint32 tickSizeE8;
    uint32 lotSize;
    uint16 marginModelId;
    SettlementStyle settlementStyle; // CASH
    ExerciseStyle exerciseStyle;     // EUROPEAN
    bool active;
}
```

Perps remain a separate hedge market inside the same margin engine. That is important, because a user short calls and long perp hedge should receive margin relief.

### Matching

The onchain book is standard price-time priority. Every option series has two books, bid and ask, each implemented as price levels with FIFO queues. A monotonically increasing sequence number gives deterministic sub-block priority.

Core storage:

```solidity
struct Order {
    uint64 orderId;
    uint64 seriesId;
    address trader;
    bool isBuy;
    uint64 priceTicks;
    uint128 size;
    uint128 remaining;
    uint64 seq;
    uint64 prev;
    uint64 next;
    bool reduceOnly;
    bool postOnly;
    bool active;
}

struct PriceLevel {
    uint64 head;
    uint64 tail;
    uint128 totalRemaining;
    bool exists;
}
```

For each series you maintain:

* best bid / best ask
* mapping(priceTick => PriceLevel) for bids and asks
* order id mapping
* bitmap or sorted price index for fast next-level lookup

The matching path is:

1. Pre-check portfolio margin for the taker’s worst-case post-trade state.
2. Walk opposing book from best level outward.
3. For each maker fill:
   * decrement maker remaining
   * decrement taker remaining
   * update positions
   * update realized cash / premium transfers
   * recompute account risk deltas incrementally
4. If leftover remains and order is limit, insert resting order if post-trade margin still passes.

### Margin engine

This is the heart of the protocol. Since you asked to skip MM-churn reduction, this is where the real complexity lives.

The margin engine should support:

* cash collateral balances
* option positions by series
* perp position by underlying
* portfolio net Greeks
* initial margin and maintenance margin
* liquidation price / health factor

A good account model:

```solidity
struct AccountState {
    int256 cashBalance;
    mapping(uint64 => int128) optionPosition;   // +long / -short contracts
    mapping(bytes32 => int128) perpBasePos;     // hedge positions
    int256 netDeltaE18;
    int256 netGammaE18;
    int256 netVegaE18;
    uint256 initialMargin;
    uint256 maintenanceMargin;
}
```

#### Risk model

For options on perps, I would not use naive SPAN-style static shock only. I would use a hybrid:

* **Per-series Greeks/PV** from a deterministic Black-76 style model using perp forward/reference price.
* **Stress shocks** over spot/perp move and vol move.
* Margin = max of scenario losses + concentration add-ons.

Because the underlying is a perp, Black-76 is a more natural first model than plain Black-Scholes. Inputs:

* forward/reference $$F$$ from perp index/mark
* strike $$K$$
* time to expiry $$T$$
* implied vol $$\sigma$$
* discount factor $$D$$ (can be simplified if quote stablecoin)
* option type

Onchain you do not need a full calibrated smile engine. You need:

* a trusted risk surface input
* deterministic interpolation
* cheap Greeks/PV routines

Risk oracle state per underlying:

```solidity
struct RiskSurface {
    uint64 updatedAt;
    uint64 refPriceE8;          // perp reference
    uint64 atmVolE6;
    int32 skewE6;
    int32 termSlopeE6;
    uint32 maxPriceMoveBps;
    uint32 maxVolMoveBps;
}
```

A practical simplification is:

* onchain stores ATM vol + skew/term parameters or strike bucket vols
* margin engine derives per-series vol by interpolation
* Greeks/PV are recomputed only for touched series during fills and periodic maintenance

#### Margin formula

For each account:

1. Compute mark-to-model PV of all option legs.
2. Compute perp unrealized PnL from reference price.
3. Compute net Greeks.
4. Run stress scenarios such as:
   * underlying $$\pm 5%, \pm 10%, \pm 15%$$
   * vol $$\pm 20%, \pm 40%$$
   * expiry decay shock near maturity
5. IM = worst scenario loss + liquidity buffer + short option floor.
6. MM = lower multiple of the same framework.

This is much better than raw Greeks-only margin, because short gamma/short vega books can look tame locally and still blow up under jumps.

### Premium, PnL, and settlement

When an option trade occurs:

* buyer pays premium immediately
* seller receives premium immediately
* positions update immediately
* margin is recomputed immediately

At expiry:

* freeze final settlement reference using a TWAP/TWMP window on the perp index/mark
* compute intrinsic value
* cash settle long/short holders
* close series permanently

For a call:

$$
\text{payoff} = \max(S\_T - K, 0)
$$

For a put:

$$
\text{payoff} = \max(K - S\_T, 0)
$$

No exercise messages are needed for European cash-settled options; settlement is automatic.

### Liquidation

Liquidation must be portfolio-aware, not order-aware.

A robust path:

* anyone can call `liquidate(account, payload)`
* contract checks health < MM
* protocol liquidates in small chunks:
  * first reduce perp hedge if it worsens risk asymmetrically
  * then buy back short convexity / sell long options depending on scenario improvement
  * optionally use a liquidation auction if book depth is thin
* liquidator receives fee
* insurance fund backstops residual bad debt

Do not rely on full account closeouts only. Options portfolios often require partial liquidation to avoid unnecessary slippage.

### Contracts

I would split implementation into these contracts/libraries:

#### 1. MarketRegistry

Responsibilities:

* create/list option series
* set tick sizes, lot sizes, expiry rules
* bind underlying perp market id
* freeze/close series at expiry

Key functions:

* `createSeries(...)`
* `activateSeries(seriesId)`
* `expireSeries(seriesId, settlementPrice)`

#### 2. CollateralVault

Responsibilities:

* custody stable collateral
* deposit/withdraw
* reserved margin accounting
* insurance fund hook

Key functions:

* `deposit(asset, amount)`
* `withdraw(amount)`
* `transferPremium(buyer, seller, amount)`

#### 3. RiskOracle

Responsibilities:

* publish perp reference
* publish IV/risk surface params
* stale-data checks
* settlement price finalization

Key functions:

* `updateSurface(underlyingId, params)`
* `getSeriesVol(seriesId)`
* `getSettlementPrice(seriesId)`

#### 4. MarginEngine

Responsibilities:

* account positions
* risk/PV/Greeks computation
* IM/MM checks before and after trades
* liquidation health checks

Key functions:

* `checkOrderMargin(account, proposedTrade)`
* `applyFill(taker, maker, fill)`
* `health(account)`
* `liquidationPlan(account)`

#### 5. OrderBook

Responsibilities:

* price levels and queues
* insert/cancel/replace
* best-price tracking

Key functions:

* `placeLimit(...)`
* `cancel(orderId)`
* `matchIncoming(...)`

#### 6. MatchingRouter

Responsibilities:

* orchestrate pre-trade checks, book traversal, settlement, and event emission
* support IOC/FOK/post-only

Key functions:

* `placeAndMatch(orderParams)`
* `marketOrder(seriesId, side, size, limitPrice)`
* `cancelReplace(...)`

### Solidity implementation plan

#### Phase 1: Core primitives

Build and test:

* fixed-point math library
* safe cast library
* bitmap or tick tree
* linked-list queue library
* global sequence generator
* events schema

Deliverables:

* `FixedPointMath.sol`
* `TickBitmap.sol`
* `OrderQueueLib.sol`
* `SequenceLib.sol`

#### Phase 2: Static order book

Implement:

* single-series bid/ask book
* place/cancel/match with price-time priority
* no margin yet, mock balances only

Tests:

* FIFO within price level
* correct best bid/ask updates
* partial fills across multiple makers
* cancel head/middle/tail nodes
* sub-block priority via sequence

#### Phase 3: Multi-series registry

Implement:

* series listing
* expiries
* tick and lot validation
* market status flags

Tests:

* invalid series params
* delisted/expired placement rejection
* independent books per series

#### Phase 4: Collateral vault

Implement:

* collateral balances
* premium transfers
* margin reservation
* withdrawals blocked if health would fail

Tests:

* deposit/withdraw
* premium settlement on fill
* blocked undercollateralized withdrawal

#### Phase 5: Risk engine v1

Implement a first deterministic model:

* Black-76 pricing
* delta/gamma/vega approximations
* per-account Greek aggregation
* scenario margin engine

Tests:

* per-leg PV sanity
* portfolio netting with perp hedge
* short option IM > long option IM
* scenario monotonicity under larger shocks

#### Phase 6: Trade-integrated margin

Implement:

* pre-trade worst-case check
* post-fill recalculation
* resting order reservation model

Important choice: how to margin resting orders.\
For a full onchain CLOB, you need to reserve collateral for the **worst executable subset** of resting sell options and aggressive buy perps. The simplest policy is:

* each resting order reserves standalone IM
* portfolio offsets apply only to filled positions, not open orders

That is conservative but much easier. Later you can add order-aware offsets.

#### Phase 7: Expiry and settlement

Implement:

* settlement window
* final reference fixing
* automatic cash settlement
* series closeout

Tests:

* ITM/OTM/ATM behavior
* settlement only once
* no post-expiry new orders
* full account PnL reconciliation

#### Phase 8: Liquidation

Implement:

* health checks
* partial liquidation
* protocol fee and insurance fund logic
* liquidator permissions

Tests:

* under-MM detection
* liquidation restores health
* liquidator fee bounded
* bad debt path hits insurance fund

### Order lifecycle details

#### Place order

1. Validate series active, tick, lot, side, flags.
2. Ask margin engine for worst-case reserved IM after adding this order.
3. If health passes, reserve IM.
4. Try immediate match.
5. If residual and not IOC/FOK, insert on book.

#### Fill order

1. Compute premium cash flow.
2. Update option positions.
3. Update perp hedge positions only if the trade is in perp market.
4. Recompute touched account Greeks/PV.
5. Recompute IM/MM.
6. Revert entire transaction if either side ends below required post-trade health unless the trade itself is a liquidation action.

#### Cancel order

1. Remove from queue.
2. Release reserved IM.
3. Emit event.

### Data/indexing layer

Even with a full onchain book, you still need an indexer. The chain is source of truth, but UI reconstruction from raw storage is poor. Build:

* order book indexer
* fills/trades feed
* account portfolio view
* Greeks and health snapshots
* settlement calendar

Events to emit:

* `OrderPlaced`
* `OrderCanceled`
* `OrderFilled`
* `PriceLevelUpdated`
* `RiskSurfaceUpdated`
* `AccountHealthUpdated`
* `SeriesExpired`

### Gas strategy

A full onchain options CLOB is gas-heavy. The main controls are:

* discrete tick sizes and lot sizes
* one global sequence counter
* compact integer structs
* avoid full-portfolio recompute on every fill, use incremental updates
* use cached per-account net Greeks and only recalc touched series
* store strike/expiry metadata once in registry
* prefer cash settlement to delivery settlement

Even then, L1 is likely impractical for active trading. This design belongs on a fast L2 or appchain.

### Suggested milestones

| Milestone | Scope                                          | Duration  |
| --------- | ---------------------------------------------- | --------- |
| M1        | Single-series book + mock balances             | 2–3 weeks |
| M2        | Registry + vault + multi-series                | 2 weeks   |
| M3        | Risk engine v1 + Black-76 PV/Greeks            | 3–4 weeks |
| M4        | Trade-integrated margin + expiry settlement    | 3 weeks   |
| M5        | Liquidation + insurance fund + audits prep     | 3 weeks   |
| M6        | Indexer, UI API, testnet, invariant/fuzz suite | 3–4 weeks |

### Risks

The hardest parts are not matching but:

* correct reservation of margin for resting short-option orders
* deterministic and manipulation-resistant settlement reference
* incremental portfolio risk updates without mismatch bugs
* partial liquidation logic for mixed perp + option portfolios
* gas blowups on multi-fill orders across many maker accounts

### Recommended v1 scope

For v1, I would deliberately constrain:

* European cash-settled options only
* quote collateral in one stablecoin
* Black-76 with oracle-fed vol buckets
* conservative reservation for resting orders
* partial liquidation but no complex liquidation auctions
* no cross-asset portfolio offsets beyond same underlying perp + options family

That gets you a protocol that is hard but buildable.

A good next step is to turn this into:

1. contract-by-contract interfaces,
2. storage layout, and
3. a full margin formula spec with examples for short call, short strangle, and covered hedge.
