> 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/the-task-is-to-to-implement-options-trading-on-evm.md).

# the task is to to implement options trading on evm

![](https://r2cdn.perplexity.ai/pplx-full-logo-primary-dark%402x.png)

## the task is to to implement options trading on evm blockchain, specifically options on futures. could you overview how options work? difference between spot options and futures options and how usually options are implemented onchain

Here is a comprehensive overview of options fundamentals, the spot-vs-futures distinction, and how they are implemented on-chain—relevant to your goal of building options on futures on EVM.

***

### Options Fundamentals

An option gives the buyer the **right, but not the obligation**, to buy (call) or sell (put) an underlying asset at a predetermined **strike price** on or before an **expiry date**. The buyer pays an upfront **premium** to the seller (writer), who takes on the obligation and open-ended risk.

Key option styles affecting exercise:

* **European** — exercised only at expiry; standard for most DeFi and crypto options[^1]
* **American** — exercised any time before expiry; more flexible but harder to price[^1]
* **Cash-settled** — PnL paid in stablecoins at expiry (most common on-chain)
* **Asset-settled** — physical delivery of the underlying

The price (premium) is driven by five factors: spot price, strike price, time to expiry, implied volatility, and interest rates — captured by the **Greeks**: Delta (Δ), Gamma (Γ), Vega (ν), and Theta (Θ).

| Greek         | Futures                    | Options                           |
| ------------- | -------------------------- | --------------------------------- |
| **Delta (Δ)** | ±1 per contract (constant) | 0 to ±1, changes with spot        |
| **Gamma (Γ)** | 0                          | Non-zero; accelerates Δ near ATM  |
| **Vega (ν)**  | 0                          | Sensitivity to implied volatility |
| **Theta (Θ)** | 0                          | Time decay, erodes premium daily  |

***

### Spot Options vs. Futures Options

The critical difference is what the option settles *into* upon exercise.

| Dimension             | Spot Options                                 | Futures Options                                           |
| --------------------- | -------------------------------------------- | --------------------------------------------------------- |
| **Underlying**        | The spot asset (e.g. ETH itself)             | A futures contract on ETH                                 |
| **Exercise outcome**  | Deliver/receive the asset or cash equivalent | Take a long/short position in the futures contract        |
| **Pricing reference** | Spot price                                   | Futures mark price (includes basis/carry)                 |
| **Leverage**          | Generally none (unless collateralized)       | Inherent leverage from the futures                        |
| **Expiry coupling**   | Independent of any other contract            | Option expiry must align with or precede futures expiry   |
| **Settlement**        | At spot price at expiry                      | At futures settlement price                               |
| **Margin behavior**   | Reg-T style (premium upfront)                | SPAN/portfolio-margin style — stress-tested positions[^2] |

With futures options, exercise produces a **futures position, not the asset**. A call exercised ITM gives the holder a long futures position at the strike price; they can then immediately close it at the prevailing futures mark price for profit. This also means a futures options system needs a **functioning futures margin engine underneath** — the option layer is literally a second derivative.

Additionally, different option expiries can map to *different* futures contract months. For example in crude oil, options expiring in March might settle into the April futures, while options expiring in June settle into the July futures. You need to explicitly model this expiry-to-underlying mapping.

***

### On-Chain Implementation Patterns

Four major architectural patterns exist in DeFi options today:

#### 1. Infrastructure / Settlement Layer

Protocols like **Opyn** and **Opium** create tokenized option contracts (ERC-20 oTokens) representing fully collateralized positions. Key mechanics:

* Writer locks collateral → mints option tokens
* Buyer purchases tokens; token = the option itself
* At expiry, a Chainlink or similar oracle reads the settlement price
* Buyer redeems tokens for payout; redemption is usually manual

This is the most common base layer pattern — it separates *creation* from *trading* (OTC/auction handles price discovery).

#### 2. AMM-Based Options (Pool-to-Peer)

Protocols like **Hegic**, **Lyra/Derive**, and **Premia** replace order books with liquidity pools:

* LPs deposit stablecoins as collateral into market maker vaults (MMVs)
* The AMM acts as sole counterparty for all buyers
* Pricing is either **rate-based** (Hegic — uses historical vol, simpler) or **Black-Scholes-style** with an on-chain implied volatility surface (Lyra)
* Lyra hedges LP delta exposure via perps (GMX/Synthetix) to stay delta-neutral[^3]

The problem: full Black-Scholes on-chain is expensive — `log`, `exp`, and the normal CDF cost 30–50k gas per strike. Most protocols **pre-compute weights off-chain and feed them via oracle or calldata**.

#### 3. Order Book + Off-Chain Matching

Protocols like **AEVO** and **Zeta** run matching engines off-chain (or on fast L2s) and use the chain only for settlement:

* Off-chain CLOB handles price discovery and matching
* On-chain contract handles collateral custody, margin, and final settlement
* Requires trust in the sequencer/matching engine, but achieves near-CEX UX

#### 4. AMM-Powered (Uniswap-Native)

**Panoptic** re-interprets Uniswap V3 LP positions as options, since concentrated liquidity has an options-like payoff. This elegantly reuses existing liquidity but offers a payoff structure closer to linear than a vanilla option.

***

### Key Smart Contract Architecture for Futures Options

For your specific case — **options on futures on EVM** — the core contract modules you'll need:

1. **Futures contract registry** — tracks open futures positions by account, mark price, funding, PnL
2. **Option contract** — stores `(strike, expiry, optionType, underlyingFuturesId, premium, writer, buyer, exercised)`; very similar to Chainlink's reference pattern[^4]
3. **Oracle module** — Chainlink feed (or TWAP) for both spot and futures mark price; used at exercise and for margin checks
4. **Margin / collateral engine** — writers must post collateral; for futures options this must be SPAN-style (stress-test spot × vol shocks) rather than simple premium collection[^2]
5. **Exercise / settlement logic** — on exercise, instead of delivering an asset, the contract opens a futures position in the futures registry for the option buyer at the strike price, then cash-settles the difference vs. mark price
6. **Greeks-aware liquidation** — because gamma can spike sharply near ATM and expiry, margin requirements must be dynamic, not static[^5]

The biggest on-chain challenge specific to futures options is that **your margin engine must track both the futures PnL and the options Greeks simultaneously** — a short call on a futures position can go deeply negative very fast if the futures price spikes, and a naive margin model will miss this.

The current state-of-the-art approach is to **compute full SPAN-style margin weights off-chain, commit them to the contract via a signed oracle update, and use on-chain lookup tables** — saving the 30–50k gas of on-chain Black-Scholes while maintaining acceptable precision.

⁂

***

## Can in be options on perps?

Yes — options on perps are a real and actively developed primitive, formally called **Everlasting Options** (or Perpetual Options / XPOs). They are to dated options what perpetual futures are to dated futures.

***

### The Core Concept

The **Everlasting Option** was formally introduced in a 2021 Paradigm paper by Dave White and Sam Bankman-Fried. The insight is elegant: instead of expiring, the option *rolls perpetually* using a **funding fee mechanism** borrowed from perps.

In a standard perp, funding = `mark − index` (keeps perp price anchored to spot). In an everlasting option, funding is:

$$
\text{Funding Fee}\_N = \frac{\text{mark} - \text{payoff}}{N}
$$

where `payoff` is the current intrinsic value of the option (e.g. `max(spot − strike, 0)` for a call) and `N` is the number of funding periods per day. This keeps the option price anchored to its fair Black-Scholes value rather than drifting. If the option is overpriced relative to payoff, buyers pay sellers; if underpriced, sellers pay buyers.

***

### How It Differs from Dated Options on Futures

| Dimension                  | Dated Option on Futures                      | Everlasting / Perp Option                                                 |
| -------------------------- | -------------------------------------------- | ------------------------------------------------------------------------- |
| **Expiry**                 | Fixed date, ties to a futures contract month | None — holds indefinitely                                                 |
| **Underlying**             | A specific futures contract                  | Perp mark price (or spot)                                                 |
| **Theta (time decay)**     | Exists; option bleeds to zero                | Does not exist — replaced by funding                                      |
| **Premium payment**        | Paid upfront in full                         | Paid continuously via funding each period                                 |
| **Effective tenor**        | Days to expiry                               | Roughly equivalent to a dated option expiring in 1 funding period (\~24h) |
| **Liquidity**              | Fragmented across strikes × expiries         | Consolidated — only strikes, no expiry dimension[^6]                      |
| **Rolling cost**           | Must manually close + re-open each expiry    | Zero — position holds automatically                                       |
| **Settlement on exercise** | Assigns a futures position at strike         | Cash-settles the intrinsic payoff                                         |

The liquidity consolidation point is significant for you as a builder: dated options scatter liquidity across a strike × expiry matrix (e.g. 20 strikes × 12 monthly expiries = 240 separate markets). Everlasting options collapse this to just the strike dimension, making AMM-based market making far more capital-efficient.

***

### Pricing: Replication via a Portfolio of Dated Options

The theoretical value of an everlasting option is a **weighted sum of dated options** with exponentially decaying weights:

$$
V\_{\text{everlasting}} = \sum\_{k=0}^{\infty} \frac{1}{2^{k+1}} \cdot V\_{\text{dated},, T\_k}
$$

The first dated option (expiring soonest) gets 50% weight, the next 25%, then 12.5%, etc.. In practice, only the first 4–6 terms matter, as the tail weights are negligible. This replication formula is what the **funding payment** enforces: at each funding interval, the contract pays out the value of the "top" expiring option and rolls into the next basket.

***

### Protocols Implementing This On-Chain

* **Panoptic** — reuses Uniswap V3 concentrated liquidity positions as perpetual options; no oracles, no expiry, premia stream every Ethereum block (\~12s)
* **Paradex** — implements perpetual options as an order-book hybrid; prices them as "a dated option expiring in one funding period" and charges funding continuously[^7]
* **Opyn/Squeeth** — power perpetuals: tracks ETH², a special case of an everlasting option with payoff = `spot²`; the first major on-chain perpetual derivative product[^8]

***

### Key Implementation Challenges for Perp Options on EVM

Since you're building this, the hardest parts relative to dated options are:

1. **Funding accrual per block** — you need an efficient per-position accumulator (similar to how Aave tracks interest with an index), not per-block iteration; use a global `fundingIndex` and snapshot it on position open[^9]
2. **Mark price for funding** — you must derive a reliable mark price for the option itself (not just the underlying), since funding = `mark − payoff`; this is harder than a perp where mark ≈ spot
3. **No natural delta hedge** — dated options protocols hedge delta via the futures they reference; perp options need a continuous hedge (e.g. against the underlying perp), requiring tight integration between both engines
4. **Margin under continuous funding** — a buyer who runs out of margin to pay funding gets liquidated even if their option is ITM; you must deduct funding from margin reserves on every interaction (or accumulate lazily with the index approach)

⁂

***

## Explain the mechanic of options trading for a beginner

Options trading gives you the right — but never the obligation — to buy or sell an asset at a fixed price before a set date. You pay a small upfront fee called a **premium** for this right, and your maximum loss as a buyer is always capped at that premium.

***

### The Two Types of Options

* **Call option** — the right to *buy* the asset at the strike price; you buy a call when you think the price will go *up*
* **Put option** — the right to *sell* the asset at the strike price; you buy a put when you think the price will go *down*

***

### The Key Terms

* **Strike price** — the fixed price you can buy/sell at, agreed when you open the contract[^10]
* **Expiry date** — the deadline by which you must exercise or let the option expire worthless[^11]
* **Premium** — the price you pay to buy the option contract[^12]
* **In the money (ITM)** — the option has real value (e.g. call with strike $40 when price is $50)
* **Out of the money (OTM)** — exercising would be unprofitable; the option will likely expire worthless[^10]

***

### A Concrete Example

Say ETH is at $2,000. You buy a **call option** with a strike price of $2,200, expiring in 30 days, for a premium of $100.

* **ETH rises to $2,500**: you exercise, effectively buying at $2,200 and immediately gaining $300, minus the $100 premium = **$200 profit**
* **ETH stays at $2,000**: you don't exercise (it would be cheaper to just buy at market). You lose only the **$100 premium**
* **ETH crashes to $1,500**: you still lose only the **$100 premium** — the option simply expires[^11]

This asymmetry is the core appeal: **limited downside, uncapped upside** for buyers.

***

### Buyers vs. Sellers (Writers)

The two sides of an option contract have very different risk profiles:

| Role                | Action           | Max Loss                            | Max Gain                              |
| ------------------- | ---------------- | ----------------------------------- | ------------------------------------- |
| **Buyer**           | Pays premium     | Premium paid                        | Unlimited (call) / Strike price (put) |
| **Seller (writer)** | Receives premium | Unlimited (call) / very large (put) | Premium received                      |

Sellers collect the premium upfront but take on the *obligation* to deliver if the buyer exercises. This is why selling naked (uncovered) options is the riskiest position in finance.

***

### What Moves Option Prices

Options don't just track the underlying price — several forces affect the premium:

* **How far the price is from the strike** — deeper ITM = more expensive
* **Time remaining** — more time = more expensive; this erodes daily (**time decay / Theta**)
* **Volatility** — higher expected price swings = more expensive option (**Vega**)
* **Direction of the underlying** — price movement changes the option's delta (**Delta**)

***

### Common Beginner Strategies

* **Long call** — buy a call, bet price goes up; simple, limited loss[^11]
* **Long put** — buy a put, bet price goes down or use it as insurance on holdings[^12]
* **Covered call** — you own the asset and sell a call on it to earn recurring premium income[^13]
* **Straddle** — buy both a call and a put at the same strike; profits if the price moves *a lot* in either direction; used before major events like protocol launches or economic data[^14]

The most important mental model: options are **not a bet on direction alone — they are a bet on direction + magnitude + timing**. A call option can lose value even if the price goes up slightly, if time decay erodes more than the price gain delivers.

⁂

***

## Do one sells options?

Yes — selling options (also called **writing** options) is a very active and popular strategy, often more common among professional traders than buying options.

### Who Sells Options and Why

When you sell an option, you flip the trade around: instead of paying a premium, you **collect it upfront**. Your goal is simple — you want the option to expire worthless so you keep that premium as pure profit. Statistically, the majority of options do expire worthless, which is why many professional traders prefer the seller's side.

The tradeoff is that your risk profile inverts completely:

* **Buyer** — limited loss (just the premium), unlimited upside
* **Seller** — immediate income (the premium), but potentially unlimited loss if the market moves sharply against you

### The Two Things You Can Sell

* **Sell a call** — you believe the price will *not* rise above the strike; you collect premium and profit if it stays below[^15]
* **Sell a put** — you believe the price will *not* fall below the strike; you collect premium and profit if it stays above[^15]

### Common Selling Strategies (From Safest to Riskiest)

* **Covered call** — you already own the asset and sell a call on it; if the buyer exercises, you simply hand over your asset at the strike price; very safe[^16]
* **Cash-secured put** — you sell a put and hold enough cash to buy the asset if assigned; worst case is you buy at a price you were already comfortable with[^17]
* **Credit spread** — sell one option and simultaneously buy a further OTM option as protection; caps your maximum loss[^15]
* **Naked option** — sell without owning the asset or holding hedging collateral; highest risk, as losses are theoretically unlimited on a naked call[^17]

### A Concrete Example

ETH is at $2,000. You sell a call with a $2,500 strike expiring in 30 days and collect $80 premium.

* **ETH stays below $2,500**: option expires worthless — you keep the full **$80 profit**
* **ETH rises to $2,700**: buyer exercises — you must sell ETH at $2,500 when it's worth $2,700, losing **$200 minus the $80 premium = $120 net loss**
* **ETH skyrockets to $5,000**: your loss is **$2,500 minus $80 premium** — this is why naked selling is dangerous[^11]

### Why Sellers Have a Statistical Edge

Option sellers benefit from **time decay (Theta)** working *in their favor* — every day that passes without a big price move erodes the option's value, putting money in the seller's pocket. This is the opposite of the buyer's experience. Sellers also profit in **sideways or low-volatility markets** where buyers keep losing premium. For this reason, many systematic and institutional traders are net option sellers, using defined-risk spreads to cap the downside.

⁂

***

## How the smart contract should work

Given your goal of building **options on futures/perps on EVM**, here is a complete breakdown of how the smart contracts should be structured — from data model to lifecycle flow.

***

### Core Data Model

Every option position is stored as a struct on-chain. At minimum it needs:

```solidity
struct Option {
    address writer;        // seller who posted collateral
    address buyer;         // current owner of the option
    uint256 strikePrice;   // fixed price at which option can be exercised
    uint256 expiry;        // block.timestamp deadline
    uint256 amount;        // size of the position
    uint256 premium;       // price paid by buyer
    OptionType optionType; // CALL or PUT
    bool exercised;
    bool cancelled;
}

enum OptionType { CALL, PUT }
mapping(uint256 => Option) public options;
uint256 public nextOptionId;
```

For futures/perps options, you add a reference to the underlying futures position ID and the futures contract address.

***

### Contract Modules

The system should be split into at least four separate contracts:

* **OptionsFactory** — creates and stores option contracts, manages the ID registry
* **CollateralVault** — holds locked collateral from writers and premium from buyers; never mixed
* **Oracle** — reads Chainlink price feed (or perp mark price) for settlement; must validate for staleness[^18]
* **SettlementEngine** — handles exercise, expiry, and liquidation logic

This separation matters for security: the vault should have no pricing logic, and the oracle module should be upgradeable independently.

***

### The Full Option Lifecycle

Each state transition maps to a function call:

#### 1. Write (Sell)

The writer calls `writeOption()`, specifying strike, expiry, amount, and option type. The contract immediately pulls collateral from the writer into the vault:

* **Naked call**: lock the underlying asset (e.g. ETH or perp position)
* **Cash-secured put**: lock `strike × amount` in stablecoins
* **Futures option**: lock margin equivalent to max potential loss under stress

```solidity
function writeOption(uint strike, uint expiry, uint amount, OptionType t) 
    external returns (uint optionId) {
    _collectCollateral(msg.sender, strike, amount, t); // pull from writer
    options[nextOptionId] = Option(msg.sender, address(0), strike, expiry, amount, 0, t, false, false);
    return nextOptionId++;
}
```

#### 2. Buy

The buyer calls `buyOption(optionId)` and pays the premium. The contract transfers option ownership and routes premium to the writer:

```solidity
function buyOption(uint id) external payable {
    Option storage opt = options[id];
    require(opt.buyer == address(0), "Already sold");
    require(msg.value == opt.premium, "Wrong premium");
    opt.buyer = msg.sender;
    payable(opt.writer).transfer(msg.value); // premium to writer immediately
}
```

#### 3. Exercise

The buyer calls `exercise(optionId)` before expiry. The contract checks the oracle price, validates profitability (ITM check), and pays out the difference:

```solidity
function exercise(uint id) external {
    Option storage opt = options[id];
    require(msg.sender == opt.buyer, "Not owner");
    require(!opt.exercised, "Already exercised");
    require(block.timestamp < opt.expiry, "Expired");

    uint markPrice = oracle.getPrice(); // Chainlink or perp mark price
    uint payout = _calcPayout(opt, markPrice); // max(markPrice - strike, 0) × amount
    require(payout > 0, "Out of the money");

    opt.exercised = true;
    vault.releaseTo(opt.buyer, payout);         // pay buyer from collateral
    vault.releaseTo(opt.writer, remaining);     // return leftover collateral
}
```

For **futures options**, instead of a direct payout, `exercise()` opens a futures position in your futures engine at the strike price, then immediately cash-settles the PnL — or just does full cash settlement directly.

#### 4. Expire Worthless

After `block.timestamp >= expiry` and `exercised == false`, anyone (or a keeper bot) calls `retrieveExpiredCollateral(optionId)`, which releases all locked collateral back to the writer:

```solidity
function retrieveExpiredCollateral(uint id) external {
    Option storage opt = options[id];
    require(block.timestamp >= opt.expiry, "Not expired");
    require(!opt.exercised, "Was exercised");
    vault.releaseTo(opt.writer, opt.collateral);
}
```

***

### Collateral Logic (Critical for Futures Options)

Standard spot options use **full collateralization** — the writer locks 100% of the worst-case payout, making the system safe but capital-inefficient. For futures options you typically want **margin-based collateral**, where the writer posts a percentage computed from volatility and position size:

| Collateral Model     | How It Works                    | Risk                                           |
| -------------------- | ------------------------------- | ---------------------------------------------- |
| **Full collateral**  | Lock entire strike × amount     | Zero insolvency risk, very capital-inefficient |
| **Margin-based**     | Lock a % based on vol and delta | Capital-efficient, requires liquidation engine |
| **Portfolio margin** | Offset correlated positions     | Most efficient, hardest to implement on-chain  |

For margin models, you need a **liquidation function** that can be called by keepers when the writer's margin falls below the maintenance threshold — identical in concept to a perp liquidation.

***

### Oracle Integration

The oracle is the most critical security surface. Every pricing call should:

```solidity
(uint80 roundId, int price,, uint updatedAt,) = priceFeed.latestRoundData();
require(price > 0, "Invalid price");
require(block.timestamp - updatedAt < MAX_STALENESS, "Stale oracle"); // e.g. 60s
```

For perp options specifically, you need **two price feeds**: the spot/index price (for reference) and the perp mark price (for actual settlement), since the option is written on the perp, not the spot.

***

### Events (Essential for Off-Chain Indexing)

Every state change should emit an event so your frontend/indexer tracks positions without expensive on-chain reads:

```solidity
event OptionWritten(uint indexed id, address writer, uint strike, uint expiry);
event OptionBought(uint indexed id, address buyer, uint premium);
event OptionExercised(uint indexed id, uint payout, uint markPrice);
event OptionExpired(uint indexed id);
event CollateralReturned(uint indexed id, address writer, uint amount);
```

⁂

***

## How orders match?

In the context of your options on EVM system, "order matching" means connecting a **writer** (seller) who created an option with a **buyer** who wants to purchase it. There are three fundamentally different architectures to choose from, each with major tradeoffs.

***

### Architecture 1: Peer-to-Peer (Simple, No Matching Engine)

The simplest model — a writer creates an option on-chain and publishes it, and any buyer can claim it directly. There is no price negotiation; the premium is set unilaterally by the writer.

**Flow:**

1. Writer calls `writeOption(strike, expiry, premium, amount)` → contract locks collateral, records the offer
2. Buyer browses open offers on-chain/frontend, calls `buyOption(id)` → pays premium, receives option
3. No matching engine needed — it's a take-it-or-leave-it marketplace

**Best for:** simple bootstrapping, OTC-style desks, early-stage protocols. Bad for price discovery.

***

### Architecture 2: On-Chain Order Book (CLOB)

Buyers and sellers both post orders at their desired prices; a matching engine pairs them when prices cross. This is how traditional exchanges work.

**The on-chain problem:** continuously scanning all orders for matches is prohibitively expensive in gas — every order placement, cancellation, and match requires a transaction. A pure on-chain CLOB is currently not viable on EVM mainnet.

**The hybrid solution** used by AEVO, dYdX, and Derive:

```
[User] → submit order (signed message, off-chain)
                ↓
[Off-chain Matching Engine] → finds price/time priority matches
                ↓
[Smart Contract] → verifies signatures, settles, moves collateral
```

* Orders live off-chain (or in fast L2 sequencer memory)
* The smart contract only touches funds at settlement
* An off-chain matcher listens to events, identifies compatible buy/sell pairs, and calls `executeMatch(orderA, orderB)` on-chain[^19]

**Matching priority rule** (standard): **price-time priority** — the best-priced order wins; among equal prices, the oldest order wins.

***

### Architecture 3: AMM / Pool-to-Peer

No orders at all — liquidity providers deposit collateral into a pool, and the pool acts as the sole counterparty for every buyer. Price is determined by a formula, not bids and asks.

**Flow:**

1. LPs deposit stablecoins into a vault (the "pool writer")
2. Buyer calls `buyOption(strike, expiry, amount)` — the AMM prices it via Black-Scholes or a simplified vol model and charges a premium
3. The pool is automatically the writer on all contracts
4. At expiry, profitable options are settled from the pool; LPs collect leftover premium

Used by **Hegic** (rate-based pricing) and **Lyra/Derive** (Black-Scholes with IV surface).

***

### Comparing All Three

| Dimension           | Peer-to-Peer          | Hybrid CLOB                       | AMM Pool                     |
| ------------------- | --------------------- | --------------------------------- | ---------------------------- |
| **Matching**        | Manual / first-come   | Off-chain engine, on-chain settle | No matching, formula pricing |
| **Price discovery** | Poor (writer decides) | Excellent                         | Moderate (formula-driven)    |
| **Gas cost**        | Low                   | Settlement only                   | Medium (per trade)           |
| **Liquidity**       | Thin, fragmented      | Deep if MMs participate           | Always available             |
| **Trust**           | Fully on-chain        | Sequencer/matcher trust           | Smart contract trust         |
| **Complexity**      | Low                   | High                              | Medium                       |
| **Best for**        | MVP / OTC             | Institutional, high volume        | Retail, bootstrapping        |

***

### Recommended Flow for Your Futures/Perps Options System

Given that you're already building a futures engine, the **hybrid CLOB** approach fits naturally:

1. **Writer signs an off-chain order** (`strike, expiry, collateralType, premium, nonce, signature`) — no gas until matched
2. **Buyer signs a matching order** at the same or better price
3. **Off-chain matcher** (your backend/keeper) pairs them and submits both signed orders to the contract
4. **Smart contract** verifies both signatures (EIP-712), pulls collateral from writer, pulls premium from buyer, opens the option position — all in one atomic transaction[^19]
5. On exercise or expiry, settlement runs entirely on-chain against your futures engine

The key Solidity primitive for this is `ecrecover` with EIP-712 typed structured data hashing — the same pattern used by Uniswap's `permit` and every off-chain order book in DeFi:

```solidity
bytes32 orderHash = _hashOrder(order);         // EIP-712 typed hash
address signer   = ECDSA.recover(orderHash, signature);
require(signer == order.writer, "Bad signature");
```

This lets you achieve near-CEX UX (fast matching, no gas on order placement) while keeping collateral and settlement fully non-custodial on-chain.

⁂

***

## Is it the same limit order book?

Yes and no — the **mechanics are the same**, but the **structure is fundamentally more complex**. A limit order book for options is significantly harder to operate than one for spot or futures.

***

### Where It's Identical

A standard CLOB (Central Limit Order Book) works the same regardless of the asset:

* Buyers post **bids** (max price willing to pay)
* Sellers post **asks** (min price willing to accept)
* When a bid ≥ ask, the engine **matches** them and executes the trade
* Priority rule: **best price first**, then **oldest order first** (price-time priority)

This logic applies identically to options. A buyer posting "I'll pay 0.05 ETH premium for a $2,500 call expiring June 30" is just a limit order — it sits in the book until a writer posts a matching ask.

***

### Where Options Are Fundamentally Different

The critical difference is **dimensionality**. A spot or perp market has exactly **one order book** per asset:

```
ETH/USDC order book
Bids: 2,010 / 2,005 / 2,000...
Asks: 2,011 / 2,015 / 2,020...
```

An options market needs a **separate order book for every combination of strike × expiry × type**:

```
ETH $2,000 CALL June 27  →  its own order book
ETH $2,000 PUT  June 27  →  its own order book
ETH $2,500 CALL June 27  →  its own order book
ETH $2,500 CALL Sept 27  →  its own order book
... (potentially thousands)
```

In 2023, roughly **1.45 million individual options series** traded on US markets alone. This fragmentation means each individual book is thin and often has wide bid-ask spreads, making pure CLOB impractical for anything but the most liquid strikes.

***

### What This Means for Your Smart Contract

Your matching contract needs an extra layer of routing — every order must be tagged with its full instrument identifier:

```solidity
struct OptionsOrder {
    address maker;
    uint256 strikePrice;
    uint256 expiry;
    OptionType optionType;   // CALL or PUT
    uint256 size;
    uint256 limitPremium;    // the "limit price"
    OrderSide side;          // BUY or SELL
    uint256 nonce;
    bytes signature;         // EIP-712
}
```

The off-chain matcher groups orders by `(strike, expiry, type)` into separate mini-books, then applies standard price-time priority matching within each one. When a match is found, a single `executeMatch(orderA, orderB)` call settles on-chain.

***

### The Liquidity Problem & Solutions

Because each strike/expiry pair has its own book, most of them will be empty most of the time. Three approaches exist to handle this:

| Approach                    | How it solves fragmentation                                                                   |
| --------------------------- | --------------------------------------------------------------------------------------------- |
| **RFQ (Request for Quote)** | Buyer requests a quote; market makers respond bilaterally; no public book needed              |
| **AMM pool as backstop**    | An LP pool quotes any strike at any time using a formula; CLOB is primary, AMM fills the gaps |
| **Liquidity concentration** | Only list a small set of standard strikes (e.g. 5 strikes per expiry); focus all liquidity    |

AEVO and Derive use **RFQ + CLOB hybrid**: institutional market makers respond to RFQs off-chain, and the CLOB captures retail flow. For a perp options system where expiry doesn't exist, this problem largely disappears — you only fragment by **strike**, not strike × expiry, which is exactly why everlasting/perpetual options are so much more capital- and liquidity-efficient.

⁂

***

## You fragment by strike, but what about price? What is strike?

Great question — the strike and the premium (market price of the option) are two completely different things, and beginners often confuse them. Here's the distinction clearly.

***

### Strike Price vs. Premium (Market Price)

Think of it this way: you're buying a **voucher** to purchase ETH at a fixed price in the future.

* The **strike price** is the fixed price written on the voucher — e.g. "buy ETH at $2,500". It never changes for the life of that contract.
* The **premium** is what you pay *today* to buy that voucher — e.g. $80. This is what fluctuates constantly like any market price.

The strike is not traded. The **premium is the thing that's traded** on the order book.

***

### A Concrete Example

ETH is trading at $2,000 right now.

| Contract          | Strike            | Premium (market price) |
| ----------------- | ----------------- | ---------------------- |
| ETH Call, June 27 | $2,000 (ATM)      | $200                   |
| ETH Call, June 27 | $2,500 (OTM)      | $80                    |
| ETH Call, June 27 | $3,000 (deep OTM) | $20                    |

All three have **different fixed strikes**. What traders bid and ask on the order book is the **premium** of each. Each strike has its own separate order book where buyers and sellers post limit orders for the premium price.

***

### Why Strikes Are Discrete (Not Continuous)

Strikes are not arbitrary — they are offered at **standardized intervals** set by the exchange or protocol:

* In traditional markets: increments of $2.50, $5, or $10 depending on asset price and volume[^20]
* In DeFi: the protocol chooses — common choices are round numbers (e.g. $1,000 / $1,500 / $2,000 / $2,500) or percentage-based intervals (e.g. every 10% from spot)

This discreteness is what creates the fragmentation problem mentioned earlier: **each fixed strike needs its own order book**, and you're trading the premium price *within* that book.

***

### So What Goes in the Order Book?

To summarize the full picture of an options order:

```
BUY  1 ETH  CALL  strike=$2,500  expiry=Jun27  @ premium ≤ $85
SELL 1 ETH  CALL  strike=$2,500  expiry=Jun27  @ premium ≥ $80
```

The **strike and expiry are the instrument identifier** — they define *which* order book you're in. The **premium is the price** — that's what bids and asks compete on, exactly like a spot limit order book. When a buyer's max premium ≥ a seller's min premium, the engine matches them and the trade executes at that premium.

⁂

***

## Why cant you do matching onchain?

There are three separate but compounding reasons why full on-chain matching doesn't work well on EVM. It's not just one problem.

***

### Problem 1: Every Order Is a Transaction

On a CEX like Binance, placing, cancelling, or modifying an order is a free in-memory operation — it costs nothing and takes microseconds. On EVM, **every single state change is a transaction** that must be included in a block, validated by the entire network, and paid for in gas:

* Place a limit order → transaction (\~50k gas)
* Cancel it → another transaction (\~30k gas)
* Modify it → cancel + replace → two transactions

A market maker updating quotes 10 times per second would spend thousands of dollars per hour just in gas, making it economically impossible to provide tight liquidity.

***

### Problem 2: Matching Scales Linearly with Gas

This is the most fundamental technical problem. When a large market order matches against multiple resting limit orders, the smart contract must loop through each one and settle it:

```
Taker buys 50 ETH → matches against 50 separate sell orders of 1 ETH each
→ contract loops 50 times → 50 × storage reads/writes → gas scales linearly
```

The more orders a single match touches, the more gas it consumes. In the extreme case, the gas cost exceeds the **block gas limit** (\~30M on Ethereum mainnet), making the transaction literally impossible to execute. There is no such ceiling on a CEX.

***

### Problem 3: Latency (12 Seconds vs. Microseconds)

Options trading demands fast price updates because option premiums change continuously as the underlying moves. On Ethereum mainnet, a block confirms every **\~12 seconds** — meaning even if you submit an order instantly, you wait up to 12 seconds for it to land. By that time:

* The underlying perp price has moved
* Your quoted premium is stale
* You could be arbitraged on the spread

Professional market makers require sub-millisecond latency. L2s help (Arbitrum \~250ms, OP Stack \~2s) but they still can't match CEX speed.

***

### The Numbers in Practice

| Environment                       | Gas per limit order | Latency      | Viable for MM?         |
| --------------------------------- | ------------------- | ------------ | ---------------------- |
| **Ethereum L1**                   | $10–50[^21]         | \~12 sec     | No                     |
| **EVM L2 (Arbitrum/OP)**          | $0.10–0.50[^21]     | \~0.25–2 sec | Barely                 |
| **Fast EVM (Monad, Hyperliquid)** | <$0.01[^21]         | \~0.5 sec    | Yes, with optimization |
| **Off-chain matching**            | $0                  | <1 ms        | Yes                    |

***

### What People Do Instead

Three pragmatic approaches have emerged:

1. **Hybrid CLOB (dYdX, AEVO, Derive)** — match off-chain for speed and zero-gas UX, settle on-chain for custody guarantees. The tradeoff is the operator can theoretically censor orders[^22]
2. **Optimized on-chain data structures** — projects like **Clober** on Monad use a segment tree (LOBSTER) to find the best price level in O(log n) instead of O(n), dramatically cutting gas per match. Still not CEX-speed, but viable on fast chains[^23]
3. **AMM as backstop** — skip the order book entirely; a formula always quotes a price, liquidity is always available, and there's no matching step at all[^24]

For your perp options system specifically, the hybrid approach is the most practical path: **EIP-712 signed orders off-chain, atomic settlement on-chain**. It gives you fast UX, non-custodial settlement, and avoids the gas wall entirely.

⁂

***

## how can you provide transparency for off-chain matching engine?

You can’t make an off‑chain matching engine *as* transparent as a fully on‑chain CLOB, but you can design it so that **any rational participant can independently verify that you’re not cheating** — that’s the practical definition of transparency here. There are three main levers: **data**, **logic**, and **governance**.

***

### 1. Keep the Dataset Verifiable

The minimal transparency guarantee is: everyone can *see* the full order book state and every trade. Common patterns:

* **Public orderbook gateway** Run a WebSocket / gRPC endpoint that exposes:
  * current orderbook (bids/asks per strike–expiry–type)
  * every order insert/delete/modify
  * every trade matched and settled This is exactly how AEVO, dYdX, and Bluefin expose their off‑chain orderbooks.
* **On‑chain state commitments** Periodically post a **Merkle root** or **state commitment** of the orderbook on‑chain:

```solidity
function commitState(bytes32 root) external onlyOperator {
    stateRoots[now] = root;
}
```

Users can locally reconstruct the same orderbook and verify that the on‑chain root matches what the sequencer claims. This defends against *data hiding*, but not unfair logic.

***

### 2. Make the Matching Logic Verifiable

The sequencer can still be malicious by changing the matching rules (e.g. priority, fee capture, MEV‑like behavior). To limit that:

* **Open‑source the engine** Publish the full matching code under an auditable license. This doesn’t *prove* you run it as written, but it enables community audits and becomes socially hard to backdoor.
* **Cryptographic proofs of correct execution** Advanced architectures use **ZK or fraud proofs** so that *any* off‑chain computation can be verified on‑chain:
  * sequencer submits a ZK‑proof that “order X was matched at price Y according to the published rules”
  * contract verifies the proof in a single call, without re‑running the full book
  * if the proof fails, the sequencer is slashed (see roll‑up‑style designs like LayerN, Monad‑style orderbooks)
* **Deterministic matching logs** Store signed, sequential logs of:
  * `block_i: order X inserted`
  * `block_i: matched orders (A,B,C) → trades (a,b,c)` Anyone can replay the engine from genesis and prove that the sequencer deviated if the replay mismatches the public logs.

***

### 3. Governance and Operations Design

Transparency is not just technical; it’s also about **incentive alignment** and **exit paths**:

* **Permissionless on‑chain trading** Design your smart contracts so that users can always trade **directly peer‑to‑peer on‑chain** (EIP‑1271‑like orders, or a simple `directTrade()` function) as a fallback if the off‑chain book is suspicious.
* **Decentralized sequencer set** Instead of a single operator, run the matching engine on a **validator set** chosen by governance:
  * elected nodes maintain the orderbook
  * matching decisions are aggregated and signed collectively
  * slashing conditions if nodes deviate Bluefin, LayerN‑style designs, and similar protocols are moving this way.
* **Regulatory/compliance‑style reporting**
  * Daily on‑chain **settlement snapshots** (total volume, open interest, liquidation stats)
  * Quarterly audits of the sequencer by an independent firm
  * Public MEV‑like fee‑capture disclosures (e.g. “sequencer captured X% of total slippage”)

***

### 4. Trust‑Minimized Architectural Pattern for You

For your perp/options system, a practical transparent stack looks like this:

1. **On‑chain**
   * Non‑custodial collateral vault
   * `executeMatch(EIP‑712 orders, signature, stateRoot)`
   * `commitState(bytes32 root)` for book snapshots[^25]
2. **Off‑chain**
   * Open‑source matching engine implementing pure price‑time priority
   * Public WebSocket exposing full book + trades
   * Daily state‑root submitted by the sequencer, with a challenge window for proofs[^26]
3. **User guarantees**
   * **You never lose custody** (funds are on‑chain only)
   * **You can replay and verify** (open‑source code + verifiable state)
   * **You can always fall back** (on‑chain fallback trading path)

***

If you tell me whether you’re targeting a **fully self‑hosted** single operator or a **decentralized sequencer set**, I can sketch the exact contract‑level flow and data layout for your case.

⁂

***

## what about following commit-reveal approach for offchain order matching engine:

* user call matching engine with an intent to place order
* engine returns the hash of the state
* user stores the hash
* user calls engine revealing the order

this way engine theoretically can prove it included user order

Yes — a commit-reveal layer can help, but **not in the way you phrased it**. It can prove that the engine *saw* an order before some later time, but by itself it does **not** prove fair inclusion, fair ordering, or best execution.

### What your scheme proves

In a commit-reveal scheme, the commitment phase proves that some data was known at a given time without disclosing the data, and the reveal phase proves the revealed data matches the earlier commitment hash. So if the engine returns a state hash after receiving a user's hidden order, that can help prove the order existed before that committed state.

That is an **inclusion witness**, not a fairness proof. It helps against the engine later claiming “we never received your order,” but it does not stop the engine from delaying reveal processing, reordering revealed orders, selectively omitting them from matching, or matching them at a worse price while still including them somewhere in the committed history.

### The core weakness

A state hash is only meaningful if it commits to an **ordered dataset** and users can later obtain a proof that their exact order was included in that dataset. If the engine just returns “hash of state,” but users cannot inspect the underlying committed order queue or get a Merkle inclusion proof, then the hash is mostly a receipt with weak audit value.

Even if inclusion is provable, the hard question is still: **was your order processed according to the published matching rules?** Commit-reveal does not answer that by itself, because matching correctness is a statement about the entire book evolution and execution path, not just about one order being present.

### What a stronger design looks like

A better version is:

1. User sends `commit = H(order || salt || userNonce)` to the engine and optionally anchors the commitment on-chain or in a public append-only log.
2. Engine assigns a **sequence number** and publishes a commitment to the ordered intake log, typically via a Merkle root or append-only transparency log root.
3. On reveal, the user submits `(order, salt)` and the engine must produce a **Merkle proof** showing the earlier commitment was included at a specific position in the ordered intake log.
4. After matching, the engine publishes a new state root plus either a verifiable replay log or a proof that the resulting trades followed the matching policy.

This gives you three properties: receipt of submission, ordering in the intake queue, and an auditable post-match state transition. Without the sequence number or ordered log, you only have “I saw something sometime.”

### What it still does not solve

Commit-reveal adds latency and cost because it is a two-step flow, and that tradeoff is well-known in derivatives contexts. It also does not solve censorship by itself: the engine can accept the commit, then refuse to reveal, refuse to match, or keep the order in the queue until it is economically irrelevant unless there is a timeout/challenge mechanism or fallback path.

It also does not solve best execution on its own. To claim best execution, you need either deterministic replayable matching logs, fraud proofs, or zk proofs that the engine applied price-time priority or whatever rule you published.

### Practical recommendation

So the answer is: **good idea as one layer, insufficient as the full transparency model**. For your system, I would use commit-reveal only for **order intake fairness / anti-front-running**, then pair it with:

* an append-only ordered log with sequence numbers[^27]
* Merkle inclusion proofs for each accepted order[^28]
* public replay logs for all matches[^29]
* on-chain state root commitments per batch[^29]
* a challenge window or fallback direct settlement path if an accepted order is censored[^30]

A clean mental model is: **commit-reveal proves “my order existed,” transparency logs prove “where it sat in line,” and execution proofs prove “it was matched correctly.”**

Would you like a concrete protocol sketch for this, with the exact hashes, Merkle trees, and Solidity interfaces?

⁂

***

## if all practical recomendations are implemented, this data can allow user prove the system to be unfair, but it cannot guarantee user that their order is always executed fairly, right?

Yes — that’s exactly right, and you’ve put your finger on the core limitation.

#### What the data *can* guarantee

With a full stack (commit‑reveal, ordered intake log, Merkle inclusion proofs, replayable matching logs, on‑chain state roots, and a challenge window), you can guarantee:

* **Receipt:** “My order was received by the engine at time `t`.”
* **Position:** “My order sat at position `k` in the intake queue right before the next matching batch.”
* **Visibility:** “The state root after that batch reflects a state that is consistent with that queue and my place in it.”
* **Challengeability:** “If the engine ran the matching logic incorrectly or censored my order, an honest observer can detect the inconsistency and raise a dispute.”

That is **reactive** fairness: you can prove retrospectively that the engine was unfair or buggy, and potentially trigger slashing, refunds, or governance action.

***

#### What it *cannot* guarantee in real time

No design like this can guarantee **proactive, real‑time fairness** in the way you describe:

> “My order will always be executed at the best available price with strict price‑time priority, every time, without delay or censorship.”

Reasons:

1. **Latency and timing races** Even with commit‑reveal, the engine can still:
   * Delay reveal
   * Batch‑delay your order until the next tick
   * Insert a proprietary or privileged order in front of yours, as long as the resulting batch state is *internally* consistent with the published rules This is the classic MEV / front‑running / priority‑censorship problem: the engine is still the **exclusive decision‑maker over when and how your order joins the matching pool**.
2. **Ordering within the batch** From the user’s perspective, “price‑time priority” means “whoever arrives first wins at the same price.” But the engine only has a **committed hash** of the state — the **actual ordering decision** still happens off‑chain, and you can’t force the engine to reveal that ordering in real time without recreating the latency and cost of a fully on‑chain CLOB.
3. **Censorship via de facto timeout** The engine can “accept” your order, return a state hash, but then:
   * Never match it, or
   * Match it too late to be economically meaningful As long as the final state root is consistent with the log, there’s no on‑chain enforcement of “you must match this order within X seconds.” Only the **challenge window** or fallback mechanism can penalize that behavior after the fact.
4. **Best‑execution discretion** Even if the rules are written as price‑time, small relaxations (e.g., “this is our best effort”) are always possible unless the engine is **proven to run the same deterministic matching code** every time, which currently requires either full on‑chain replay or ZK‑style proofs — and those are either expensive or still in the experimental phase.

***

#### The pragmatic conclusion

You can design a system such that **users can prove unfairness after the fact** with high confidence, but you cannot eliminate the engine’s **operational discretion** in real time. That trade‑off is fundamental:

* **On‑chain CLOB:**
  * You can prove fairness in real time (price‑time is enforced by code).
  * But you pay the gas and latency cost of on‑chain state changes for every order.
* **Off‑chain sequencer + commitment layer:**
  * You get low‑latency trading.
  * Users get **verifiable hindsight** and **contestability**, but not **real‑time guarantees** over execution.

So yes, your intuition is correct: the practical stack you described makes the system **detectably unfair** if it cheats, but it does not and **cannot** guarantee, in the moment, that your order is always executed fairly. That’s the trade‑off of outsourcing matching logic to an off‑chain engine.

⁂

***

## is there a more complex setup that guarantees that your order will be processed?

Yes — there are more complex setups that get *much closer* to a **real‑time guarantee** that your order will be processed fairly, but even they are still probabilistic or conditional guarantees, not “absolute, atomic fairness in every scenario.”

***

### 1. **Frequent Batch Auctions + Fair Sequencing**

Instead of a CEX‑style continuous matching engine, you batch orders and clear them at fixed intervals with a deterministic rule (price‑time, pro‑rata, or randomized tie‑breaking).

Typical setup:

* Orders land in a **mempool / intake queue** with timestamps.
* A **fair sequencer** (e.g., Fair Sequencing Service, FSS‑style) commits to a **randomized or time‑prioritized order** for the next batch, then executes it.
* At the end of the batch, a **zk‑ or fraud‑proof** is submitted to L1 that proves the matching was run exactly as specified.

What this guarantees:

* **Bounded inclusion time:** If your order is accepted by the mempool, the sequencer must include it in the next batch or a small number of batches, or be slashed.
* **Fair intra‑batch ordering:** all orders in the batch are treated under the same published rule (no front‑running within the batch).
* **Verifiable execution:** anyone can replay the batch and prove the engine deviated.

What it still does *not* guarantee:

* **Instant execution** — you still wait batch latency (e.g. 0.5–2 seconds).
* **No censorship by the sequencer** — if the sequencer ignores the mempool, you need a challenger or governance fallback.

***

### 2. **ZK Matching Engine (“zk‑DEX”)**

Projects like GRVT use a **hybrid model**: the off‑chain engine matches instantly, but then generates a **zero‑knowledge proof** over the entire matching run and submits it on‑chain.

Structure:

* User submits order to the off‑chain matching engine.
* Engine batches orders, runs matching, updates off‑chain state, and **generates a ZK proof** that “all trades were computed correctly according to the code.”
* L1 contract only accepts the new state if the proof is valid.

What this guarantees:

* **Correctness:** the engine *must* run the matching function as written in the circuit; it cannot cheat the logic without breaking the proof.
* **Non‑censorship (if mempool is on‑chain)** — if orders are submitted on‑chain (e.g. as rollup inputs), the sequencer cannot ignore them without being detected.

Limitations:

* **Still probabilistic:** ZK circuits are expensive and complex; if one fails, you fall back to fraud‑proof or governance.
* **Still batch‑oriented:** you are not executing in zero latency, and the circuit still has to define a concrete ordering rule.

***

### 3. **Rollup‑style Order‑book + Intents**

You can treat the entire order book as a **rollup** over your perp/options engine, where:

* User orders are **intents** (e.g. “I want to buy 1 call with strike X at premium ≤ Y”).
* A **sequencer** commits to a fixed order of intents.
* A **prover** then runs the matching logic and submits a proof of correct batch execution on L1.

This gives you:

* **Cryptographic enforcing of the matching logic** (via ZK) or **in‑bounded‑time enforcement** (via fraud‑proofs).
* **State‑finality governance:** if someone discovers a match was unfair, the fraud‑proof can roll back the disputed state.

Again, this is **not** “every order executes instantly and perfectly,” but it is **executable‑by‑rule‑with‑cryptographic‑finality**.

***

### 4. **The “Strongest” Practical Setup for You**

If you want the strongest possible *practical* guarantee that your order is processed:

1. **On‑chain order submission** User submits intent as an on‑chain transaction (or as a ZK‑rollup input) so inclusion is **censorship‑resistant**.
2. **Fair sequencing service** A sequencer commits to a **randomized or time‑based order** for the next batch; if it deviates, it can be slashed.
3. **Frequent batch‑ Clearing** Every batch (e.g. every block or 0.5s) uses a **fixed, deterministic matching rule** (price‑time, pro‑rata, random tie‑breaker).
4. **ZK‑ or fraud‑proof finality** The matching engine’s output is wrapped in a **proof** that it was computed correctly by the on‑chain circuit or contract logic.
5. **Fallback: direct on‑chain P2P** If the sequencer/batch system fails to match an order within a time window, the user can fall back to a **direct on‑chain P2P or AMM‑style** interaction, proving unfairness if the batch‑engine claims “we matched it” while the proof disagrees.

***

### What this still cannot guarantee

Even this stack cannot guarantee:

* **Instant execution in every market condition** — you still deal with batch latency.
* **No latency or MEV‑style exploitation at the mempool level** — you can minimize it, but not universally eliminate it.
* **No protocol‑level attacks** — if the code or the circuit has a bug, the proof only proves that the bug was followed consistently, not that it is correct.

So to answer your question precisely: **Yes, there are more complex setups** (fair‑sequencer + batch‑clearing + ZK/fraud‑proofs + on‑chain order submission) that **push you much closer to a hard guarantee that your order will be processed fairly**, but they are still **bounded, probabilistic, and latency‑aware** guarantees, not an unconditional, real‑time, “always‑exactly‑fair” atomic guarantee.

⁂

***

## i am optimising and considering offchain matching for market makers that make a lot of transactions when price is moving. What if we incorporate some onchain market-maker features, like submitting a parameters for orders like relative price level (to market) and quantity, and shift from market price and then just update these when market-maker decides instead of updating all orders

Yes — that direction is **very sensible**, and in practice it becomes a hybrid between a CLOB and an RFQ/JIT/pegged-order system. It can reduce maker churn **a lot** because the maker updates a compact quote policy instead of constantly canceling and reposting every individual order.

### The idea in plain terms

Instead of storing ten explicit limit orders like “bid at 99.5, 99.0, 98.5 …”, the maker posts a **quote template** such as “quote 5 bid levels and 5 ask levels at offsets from oracle/mid, with these sizes and protections”. Then the engine materializes executable orders from that template against the current reference price, so when the market moves the quotes move automatically without the maker resubmitting the whole ladder.

That is basically a **parameterized pegged quoting model**. Traditional market makers already think in those terms — spread, skew, inventory target, order levels, size curve — rather than in isolated static orders.

### Why it helps

The main benefit is that you compress many updates into one state object. A maker can submit:

* reference source: oracle, mark, midpoint, best bid/ask
* bid/ask spread offsets
* number of levels
* level spacing rule
* size per level or size curve
* inventory skew parameters
* kill-switch / max deviation guard

Then the engine recomputes the effective quotes when price changes, instead of forcing the maker to push a cancel/replace storm. This is especially attractive in options, where one MM may want to maintain dozens of quotes across strikes and expiries and where stale quotes are a major problem.

### The biggest design choice

The critical question is: **are these quotes firm executable orders, or just maker instructions that the engine may convert into orders?** That distinction matters a lot.

| Model                           | What it means                                                          | Pros                                     | Cons                                     |
| ------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| **Materialized resting orders** | Engine continuously derives actual book orders from the template       | Familiar CLOB UX, visible depth          | Still need deterministic repricing logic |
| **JIT / RFQ style**             | Template is just maker willingness; fill is created when taker arrives | Best maker freshness, less stale quoting | Less transparent book, more solver-like  |
| **AMM-like pool quoting**       | Template feeds a pricing function, not discrete orders                 | Very cheap operationally                 | Less exact maker control over fills      |

Drift’s JIT design is relevant here: makers compete to fill against the latest oracle rather than relying only on stale resting orders, specifically because fresh maker pricing often beats old book liquidity. Your idea sits in a similar design space.

### What I would recommend

For your use case, I would not make every derived level a literal on-chain order. I would store a **compact maker quote policy on-chain** and let the engine derive executable quotes off-chain, with deterministic rules that can be checked later.

A good maker policy object could look like:

```solidity
struct QuotePolicy {
    address maker;
    bytes32 marketId;

    int24 refPriceSource;      // oracle / mark / index / mid
    int256 bidOffsetBps;       // e.g. -40 bps from ref
    int256 askOffsetBps;       // e.g. +45 bps from ref

    uint8 levelsPerSide;       // e.g. 5
    uint16 levelStepBps;       // spacing between levels
    uint128 baseSize;          // first level size
    uint128 sizeStep;          // increment / decrement by level

    int256 inventorySkewBps;   // adjust spread by inventory
    uint32 maxOracleAge;       // stale oracle guard
    uint16 maxRefDeviationBps; // disable if mark diverges from oracle too much

    uint64 expiry;
    uint64 nonce;
}
```

Then the derived quote for level `i` is something like:

* bid price = `ref * (1 - bidOffset - i * step)`
* ask price = `ref * (1 + askOffset + i * step)`
* size = `baseSize + i * sizeStep`

with additional skew based on maker inventory and risk.

### Why this is better than full auto-shifting on-chain

If you try to auto-shift executable orders **on-chain on every price change**, you reintroduce the same scalability problem in a different form. Something still has to trigger recomputation, touch state, and keep the book synchronized with the new reference price. So the efficient design is usually:

* **on-chain:** maker policy, collateral, risk limits, signed consent
* **off-chain:** quote derivation, matching, frequent repricing
* **on-chain settlement:** only filled trades and occasional policy updates

That preserves the gas savings while still giving makers a persistent quoted presence.

### Main risks you need to handle

This model is good, but only if you constrain it carefully.

* **Reference price manipulation** — if quotes are pegged to mark or mid, attackers may try to move the reference briefly; oracle guards and deviation clamps are mandatory[^31]
* **Ambiguity** — “relative to market” is dangerous unless “market” is defined exactly: oracle, index, mark, midpoint, or best bid/ask[^31]
* **Stale-policy execution** — if the engine delays recomputation, takers may hit stale derived quotes; include freshness windows and reject fills when reference age exceeds threshold[^31]
* **Adverse selection** — pegged quotes are easier to pick off during jumps unless the maker can widen spreads, skew inventory, or temporarily disable quoting[^32]
* **Fairness** — if the engine materializes quotes privately, users need deterministic derivation rules and auditable fill logs to verify the engine did not selectively improve or worsen quotes[^33]

### Best version of this architecture

The strongest design is a **hybrid pegged quote book**:

1. Maker posts a signed/on-chain quote policy with risk bounds and collateral[^32]
2. Engine computes live derived quotes from oracle/index/mark[^31]
3. Takers interact with visible derived depth, not hidden maker logic
4. On fill, settlement contract verifies:

* maker policy was active
* reference source and timestamp were valid
* derived fill price was consistent with the published formula
* size did not exceed remaining maker limits

That last step is the key. If the contract can verify the fill price formula from the stored policy and trusted reference data, then the engine cannot arbitrarily fill at a worse price while claiming it came from the pegged strategy.

### My practical view

So yes — **I think this is one of the best optimizations you can make** for active market makers in a fast-moving derivatives system. It effectively turns many order updates into **parameter updates**, which is much closer to how professional market makers actually manage books.

If I were designing it, I would aim for:

* **parameterized maker policies on-chain**
* **off-chain derived quote book**
* **deterministic fill verification on-chain**
* **optional JIT auction for large taker flow**
* **fallback AMM or vault for residual liquidity**

That gives you lower maker churn, fresher quotes, and better gas efficiency without fully giving up verifiability.

Would you like me to sketch a concrete Solidity + matching-engine design for this “pegged quote policy” model?

⁂

***

## how would you prioritise orders of different makers if they requoted automatically?

You are asking the **core microstructure question** of a derivatives market maker book: how to decide which maker’s quote wins when multiple makers are auto‑quoting at the same level.

Short answer: in practice, almost all serious systems either:

* **Give priority to the best price, then time**, or
* **Sprinkle the flow proportionally by size among the best‑price quotes**, and
* **Optionally** give the designated Lead Market Maker (LMM) a protected first‑fill slice.

Your auto‑requote model is compatible with all of these, but it changes the **unit of priority** from individual orders to **maker quote‑profiles**.

***

### 1. **Price‑Time Priority on Maker Levels (Simple)**

Treat each **current maker quote at a given level** as if it were a traditional limit order. Priority:

1. **Best price first** All bids at 101.0 are better than all at 100.8.
2. **Maker quote‑creation time (and revision) second** If two makers are quoting 101.0, the one whose quote was either:
   * originally created earlier, or
   * last updated earlier (common practice) gets priority.

In your auto‑requote system, that might look like:

```solidity
struct MakerQuote {
    address maker;
    uint256 refPrice;          // 100.0
    int128 bidOffsetBps;       // -100 bps
    uint128 size;              // 100
    uint64 lastUpdateTime;     // for price‑time
}
```

For a fill at 101.0:

* layer 1: collect all maker quotes where `ref * (1 + offset) ≈ 101.0`
* layer 2: sort by `lastUpdateTime` (oldest first)
* allocate fill to each maker in that sorted list until the taker quantity is exhausted.

**Pros:**

* Trivial to explain and audit.
* Very close to “normal” CLOB behavior.

**Cons:**

* Auto‑requotes that correct by a tiny epsilon can kick the maker to the back of the queue, which is bad for maker‑quote‑churn incentives.

***

### 2. **Price‑Size‑Time on Maker Levels (Pro‑Rata)**

Spread the fill **proportionally** among all makers at the best price. Classic “pro‑rata” allocation:

1. **Group by price level** All makers currently quoting 101.0 form a pool.
2. **Allocate by size share** Maker A has 70 contracts at 101.0; Maker B has 30 → A gets 70% of the fill at that level, B gets 30%.

In your system, the engine effectively:

* computes the **current effective size** each maker has at the fill price,
* computes the **total size** at that price,
* allocates taker size `Q` to each maker as `Q * (makerSize / totalCount)`.

**Pros:**

* Much smoother for makers; one tiny quote update doesn’t destroy your allocation share.
* Reduces “quote‑jumping” latency‑racing.

**Cons:**

* Harder to explain and verify post‑facto.
* You must define precisely whether you use:
  * raw size, or
  * size adjusted by inventory skew, fee‑structure, or risk.

***

### 3. **Lead‑Market‑Maker Protection (LMM‑Style)**

Some exchanges give **designated** market makers a **lead‑first** slice at the best price, then either price‑time or pro‑rata for the rest.

Typical rule:

* If a **Lead Market Maker (LMM)** is quoting at the best price:
  * the first `X` contracts of a taker order are **reserved for the LMM**.
  * the remaining `Q - X` are allocated to the rest of the book (often pro‑rata).
* If the LMM is not quoting at the best price, the usual rule applies.

In your auto‑requote book, this becomes:

```solidity
mapping(bytes32 level => address leadMaker) lmmAtLevel;
```

At fill time:

* check if `lmmAtLevel[fillPrice] == makerA`
* if yes, grant `min(Q, leadLimit)` to `makerA` first
* then allocate the rest among all eligible makers at that price.

**Pros:**

* Incentivizes the LMM to keep tighter, more persistent spreads.
* Very attractive for options‑style books that need deep, stable liquidity.

**Cons:**

* It’s **not** “pure” fairness; a retail maker can be outrun at the best price even if they quote tight.
* You must carefully define:
  * which makers are LMMs,
  * what level they “protect” (by strike/expiry?),
  * and how often you re‑evaluate LMM status.

***

### 4. **Time‑Pro‑Rata / Hybrid Models (Sophisticated)**

Some modern options‑style engines use **time‑pro‑rata**:

1. **Best price first.**
2. **Among that price, allocate a fixed “priority slice” by time**
   * e.g. the first 50 lots at 101.0 go to the earliest‑arrived maker.
3. **The remaining lots at 101.0 are allocated pro‑rata to all remaining makers at that price**.

This gives:

* a small **time‑priority incentive** (reward for being first),
* plus **less‑toxic pro‑rata** for the long tail.

This is attractive for your model because:

* it still favors **stable** makers (who don’t chase price by constantly re‑quoting),
* but **softens** the damage of a periodic re‑quote to the same level.

***

### 5. **How to Map This to Auto‑Quotes**

Because your makers **don’t submit discrete orders**, but instead update a **quote‑policy**, the priority logic must run on **derived instantaneous quotes**, not on static order IDs.

Conceptually, your engine:

1. **Lock** a reference price and timestamp when the taker submits.
2. **Snapshot** all active maker quote‑policies.
3. **Derive** effective bid/ask quotes at each level from:
   * reference price,
   * offset,
   * size curve,
   * inventory skew,
   * max size / limits.
4. **Apply** a chosen priority rule (price‑time, price‑pro‑rata, or time‑pro‑rata + LMM) **on those derived quotes**.
5. **Write** the allocation per maker on‑chain, with a log that an external observer can replay to check that the rule was followed.

This is essentially the **batch‑auction + parameterized quoting** pattern: taker flow arrives, the engine “bakes” the current maker‑quote universe, and allocates using the chosen priority model.

***

### 6. **Practical Recommendation for You**

For your use case (options on perps, with frequent maker‑updates), I would choose:

* **Base rule:** **price‑pro‑rata within level**, with **maker size** as the share numerator.
* **Optional enhancement:**
  * one **Lead Market Maker** per strike/expiry that gets a **small fixed lead slice** at the best price.
* **For very aggressive options‑style books (very low inventory tolerance):**
  * **price‑time‑priority among makers**: first maker whose quote is at the best price wins, with a tie‑breaker by `lastUpdateTime`.

This keeps two things aligned:

* **Fairness / UX:** feels like a normal book to takers.
* **Maker economics:** rewards persistence, not useless quote‑churn; auto‑requote updates are still a “tune‑your model,” not a frantic latency‑bidding war.

If you tell me:

* whether you want **one LMM** or **many equal‑status makers**, and
* whether takers are mostly market orders or limit orders,

I can sketch the **exact matching algorithm** (code‑like pseudocode) for your priority rule.

⁂

***

## yes, but prices are requoted when market price change automatically, so the first market maker will always be first.

You’re absolutely right: **if you naively apply “price‑time” to auto‑requotes, the first maker will always be first**. The reason is that **every time the engine auto‑requotes that maker’s levels, it “refreshes” their time‑stamp at the best price**, while the other makers either don’t requote or do so slightly later due to latency or model logic.

So your quote literally becomes a **self‑renewing priority monopoly** at the best price, which is exactly what you want to avoid if you care about fairness across makers.

***

### Why the standard “price‑time” breaks here

In a normal CLOB, time priority is meaningful because:

* If you amend an order (price or size), you usually **lose** your time‑priority place at that price.
* If you cancel and replace, you are **reinserted** at the end of the queue at that price.

That’s the intended friction: you don’t want makers to be able to keep their queue‑position forever by just tweaking numbers.

In your auto‑requote model:

* Every time the reference price moves, the engine **re‑emits** that maker’s quote at the same relative price level with a **fresh timestamp**.
* The matching engine sees “quote at 101.0 from makerA at time `t+1`, `t+2`, `t+3`, …” and keeps it at the **front** of the price‑time queue.

So yes, you’ve correctly identified the fragility: **auto‑requote + price‑time = makerA always at the front**.

***

### How to fix it without killing the model

You have two main options:

#### 1. **Decouple “quote creation time” from “auto‑requote time”**

Don’t update the **priority time** every time the engine auto‑re‑quotes.

Instead, define:

* `createTime` — when the maker **first enabled** this quote level or policy.
* `lastAmendTime` — when the maker **last changed** the quote policy (offset, size, skew, etc.).

Then apply price‑time priority based only on `createTime` (or `createTime` + `lastAmendTime` only when `amendFlags` actually matter):

```solidity
struct MakerLevel {
    address maker;
    uint128 price;
    uint128 size;

    uint64 createTime;      // fixed when level is first enabled
    uint64 lastAmendTime;   // can change if maker tweaks policy
    bool isNewAmend;        // flag if this amend affects priority
}
```

Auto‑requote changes the `price` and possibly `size`, but **does not change `createTime`** unless the maker explicitly reloads the level (e.g. toggles a flag). This way, makerA does not magically re‑refresh to the front every time the reference moves.

#### 2. **Switch to Pro‑Rata at the level**

If you really want to keep auto‑requote behavior simple (always update timestamps), then **drop price‑time priority and go fully pro‑rata at the level**.

At fill:

* For each price level, collect **all current effective quotes** from all makers at that price.
* Allocate taker size proportionally to maker size at that level, regardless of who “refreshed” first.

That solves your problem because:

* There is no queue position; every maker at 101.0 gets a share of every fill at 101.0.
* Auto‑requote is just a way to **re‑compute** your size and price, not a way to hijack the queue.

This is the standard solution used by many derivatives and options‑style venues when they want to avoid quote‑jumping.

#### 3. **Hybrid: Time‑Pro‑Rata at the level**

If you want some time‑based incentive but not a hard queue‑monopoly:

* **First X contracts** at 101.0 go to the maker whose quote **was created earliest** at that price.
* **Remaining contracts** at 101.0 are allocated pro‑rata among all makers at that price.

In this model, auto‑requote can:

* keep your quote active,
* but not let you **steal** the first X whenever price moves.

You pair this with the `createTime` / `lastAmendTime` logic above so that only explicit policy changes or level‑reloads trigger a new time‑stamp for the priority slice.

***

### 4. **Practical recommendation for your auto‑requote book**

For your use case, I would:

1. **Decouple** the priority time from auto‑requote timestamps using `createTime`.
2. **Use price‑pro‑rata at each level** as the main allocation rule.
3. **Optionally** add a small **time‑priority slice** for the first‑arrived maker at that level (time‑pro‑rata), if you want to mildly reward persistence.

This gives you:

* **No auto‑requote queue‑hijack** (because `createTime` is sticky).
* **Smooth allocation** across many makers, which is great for options‑style books with thin levels.
* **Explicit, auditable rules** that can be replayed from the on‑chain `QuotePolicy` and fill logs.

If you tell me whether you prefer:

* strict time‑priority‑like behavior, or
* pure pro‑rata, or
* a small “first‑maker” slice,

I can sketch the **pseudocode** for the exact matching logic under each model.

⁂

***

## but create time of first arrived market maker will be the smallest, so on every requote done by contract that market maker will have a priority

You’re absolutely right again — and this is why pure **price‑time** does not work with auto‑requote.

Your logic is correct:

* Maker A creates a quote at 101.0 with `createTime = t0`.
* Maker B later creates a quote at 101.0 with `createTime = t1 > t0`.
* When the engine **auto‑re‑quotes** both levels (e.g. when the reference moves), it recomputes `price = ref + offset`, but **does not touch `createTime`**.
* At fill, Maker A still has the **smallest** `createTime` at 101.0 → Maker A **always** wins the priority at that level.

So even with a fixed `createTime`, you still get **permanent priority for the first maker**, which is effectively a **monopoly at the best price** if they never explicitly disable their level. That’s bad for fairness and competition.

***

### Why this is fundamentally incompatible with “pure price‑time”

Price‑time priority relies on **arrival order** at the level to be meaningful and **dynamic**. In a normal CLOB, if you want to keep your queue‑position, you must either:

* keep your quote unchanged, or
* accept that amending or cancel‑replace will move you to the back of the queue at the new price.

In your auto‑requote model, the engine is **mechanically re‑projecting** the same maker’s quote onto the level whenever the reference moves, but the maker **never actually amends** it in the CLOB sense. So the “arrival order” becomes **frozen**: the first‑arrived maker is permanently first, and later makers can never catch up.

You can’t fix this with `createTime` surgery alone.

***

### What you *can* meaningfully change

To break the monopoly while keeping auto‑requote, you need to **decouple allocation from pure arrival‑order** and either:

#### 1. **Switch to Pro‑Rata at the level**

Forget time‑based priority at the level, and allocate **by size share** at each price:

* At fill at 101.0: `fill_to_maker = totalTakerAmount × (makerEffectiveSizeAt101 / totalSizeAt101)`.

Auto‑requote just updates the maker’s **size and price** at each level, but **does not grant queue‑priority**. The first‑arrived maker may still be large, but they no longer **own** the queue.

**Impact on your concern:** Maker A no longer has any special `createTime`‑based protection; it just competes on size and skew like everyone else.

***

#### 2. **Time‑Pro‑Rata at the level**

Give a **small fixed “priority slice”** to the **earliest‑arrived** maker at that level, then split the rest pro‑rata:

* Let `Q` be the taker amount at 101.0.
* Let `Q_first = min(Q, min(100, makerA_remainingSizeAt101))` go to Maker A.
* Let `Q_rest = Q - Q_first` be allocated pro‑rata to all makers (including Maker A for the leftover).

Maker A still benefits from arriving first, but:

* The **slice** is capped (e.g. 100 contracts).
* After that, everyone competes by **size**, not by `createTime`.

This softens the monopoly while preserving *some* incentive to be first.

***

#### 3. **Discrete “priority windows” instead of perpetual `createTime`**

If you want to keep time‑based incentives, you can **reset time‑priority** on a schedule or on specific events:

* **Time‑windowed priority:** At `t0`, the engine snapshots all makers at 101.0 and sets `priorityWindow = t0` + `windowDuration`. Within that window, price‑time applies. After the window, the engine **re‑snapshots** and recomputes priority; the first‑arrived maker is **not** guaranteed to still be first.
* **Event‑based restart:** Every time the reference price moves beyond a deviation threshold, the engine **resets** the priority queue at each level, treating all current quotes as “equally arrived” for that window.

In both models, the first‑maker does **not** enjoy a **perpetual monopoly** because the priority order is periodically re‑calculated.

***

### 4. **Hybrid “first‑maker bonus + size cap”**

If you are emotionally attached to rewarding the first maker, you can:

* Give the **first‑arrived** maker a **bonus** (e.g. they get 10% more effective size in the pro‑rata calculation),
* But **cap** the absolute number of contracts they can take from a single taker (e.g. 50 contracts per fill).

Example:

```
bonusEffectiveSize = min(sizeA, MAX_ABSOLUTE_TAKE)
effectiveSizeA    = sizeA + 0.1 * bonusEffectiveSize
```

Then allocate via pro‑rata using effective sizes. This:

* gives a small edge to the first maker,
* but prevents them from taking all the flow at 101.0 forever.

***

### 5. **Your best practical path**

Given your constraints (auto‑requote + many makers + fast reference moves), I would strongly recommend:

* **Drop price‑time priority** as the primary allocation rule.
* **Use pro‑rata within level** (or time‑pro‑rata with a modest first‑maker slice).
* **Optionally** add:
  * a **small size‑based bonus** for the first‑arrived maker, or
  * **time‑windowed** or **event‑based** priority resets if you want to keep explicit time‑sensitive incentives.

This way, your auto‑requote contract can keep re‑projecting quotes whenever the reference moves, and no single maker is **perpetually** first at the best price. The first maker may still be **large and fast**, but they will not be **immune to competition** from later‑arrived makers.

If you want, I can sketch the **exact pseudocode** allocation logic for one of these rules (e.g. pure pro‑rata, or time‑pro‑rata + first‑maker slice) based on your MakerQuote structure.

⁂

***

## what if we do not auto requote immediately but do it at constant interval, so even if you are second on price level 1, after market price change you could become first on price level 2

Yes — that can work, but then you are no longer running strict continuous price-time priority. You are moving to a **discrete-time batch re-quoting model**, where quote priority is sticky inside an interval and only re-normalized at the requote boundary.

### What changes economically

In your example, if a maker is second at level 1 and the reference price shifts, then under interval-based repricing that order can indeed end up first at the newly mapped level 2 until the next scheduled requote. That is not necessarily wrong, but it means queue position is now partly determined by the previous interval’s placement, not purely by the current best relative price.

So the matching rule becomes something like:

* quote templates are fixed for epoch $t$
* fills during epoch $t$ use the prices derived from the epoch’s frozen reference snapshot
* only at epoch $t+1$ are all quotes recomputed from the new reference

That is closer to a frequent batch auction or discrete book update schedule than to a continuously repriced pegged order book.

### Why it may be good

For market makers, this is often a **feature**, not a bug. It reduces constant queue reshuffling and avoids punishing makers who were already resting competitively just before a small market move.

It also makes the system much cheaper and easier to reason about operationally:

* fewer recomputations
* fewer order-book mutations
* more stable queue positions
* less “micro-jitter” from every oracle tick

That stability can improve maker participation if your product is not competing on sub-millisecond microstructure.

### The downside

The tradeoff is that you introduce **intentional staleness**. During the interval, your displayed or effective quotes can be off relative to the latest market, and queue priority can look unfair to someone who submitted a genuinely better quote after the reference moved but before the next refresh.

In other words, there are now two notions of “better”:

* better under the current live external market
* better under the frozen pricing epoch

If users think they are trading in a continuous CLOB, they will consider this unfair. If the venue explicitly says “quotes refresh every 100ms / 250ms / 1s epoch,” then it is a valid market design choice.

### The right way to define priority

If you do this, you should define priority by **epoch, derived level, and in-epoch time**. For example:

1. At epoch start, freeze `refPriceEpoch`.
2. Derive all maker quote levels from that frozen reference.
3. Within the epoch, maintain normal price-time priority only among quotes at the same derived level.
4. At the next epoch boundary, recompute all levels from the new reference and rebuild queues deterministically.

That way, “second on level 1 becomes first on level 2” is not an accident — it is an explicit consequence of the rules. The important thing is to make the rule deterministic and auditable.

### My design advice

I would avoid partial implicit remapping like “quotes drift between levels continuously but queue order stays from the old state.” That creates weird edge cases and hidden favoritism. Either:

* **continuous repricing + clear queue policy**, or
* **frozen epochs + full deterministic rebuild at each epoch**

The second one is probably better for your optimization goal.

A practical version would be:

* epoch length: 100–500 ms for high activity, maybe longer for slower markets
* freeze one trusted reference per epoch
* all taker matches in that epoch use quotes derived from that snapshot
* optionally add a volatility interrupt so if price moves beyond a threshold, the epoch is cut short and quotes refresh early[^31]

That last part matters a lot, because fixed intervals without a jump guard get toxic during sharp moves.

### My honest view

I think this can be a **good market design** if you present it as discrete-time matching rather than pretending it is continuous price-time priority. The biggest risk is not the mechanics — it is the mismatch between the actual rules and participant expectations.

So yes, your example is fine **if** you formalize it as:

* frozen quote epochs,
* deterministic repricing only on boundaries,
* explicit queue priority semantics,
* volatility-based early refresh / trading pause guard.

Otherwise you will get ambiguous situations where “best price” and “best queue position” diverge in a way that feels arbitrary.

Would you like me to write a precise matching-policy spec for this epoch-based model, including how queue priority should be recomputed at each requote boundary?

⁂

***

## since we have blocks in the blockchain anyway, there is an interval. So on each block if price changed we could reorder based on the time shift when first template from market-maker arrived

Yes — that is a coherent rule, and it is probably the cleanest version of your idea. In effect, you treat each block as a **repricing epoch**, and when prices are recomputed at the new block, queue priority among remapped quotes is preserved according to the original template-arrival time or template-sequence number.

### What this means

The market-maker does not own queue position for a literal static limit order forever. Instead, the maker owns queue priority for a **quote template stream**, and each block the system projects that template onto the new price grid.

So if MM A submitted its template before MM B, then after block $n+1$ repricing:

* both templates get remapped to new derived levels,
* and within each resulting price level, A stays ahead of B if A’s template priority is older.

That is a valid market design, but it is no longer standard order-level price-time priority. It is **template-time priority with blockwise repricing**.

### Why this is attractive

This approach solves one of your core pain points: market makers do not need to spam cancels and replaces just to maintain relative quoting around a moving reference price. It also gives stable queue ownership, which is valuable for makers because they are rewarded for maintaining an active quoting policy, not for winning every microsecond repricing race.

From a systems perspective it is nice because:

* repricing happens at a natural chain cadence,
* queue rules are deterministic,
* on-chain state can be compact,
* and you avoid pathological churn in fast markets.

### The important caveat

The rule is only fair if priority is preserved **within the same economic quote intent**. If a maker can materially change its template — spread, skew, size curve, number of levels, risk limits — and still keep the old priority timestamp, that creates a strong queue-jumping exploit.

So you need a rule like:

* **non-price-preserving update** → loses priority
* **minor risk-preserving update** → maybe keeps priority
* **pure passive remap caused by reference-price movement** → keeps priority

That distinction is crucial. Otherwise a maker could submit an early template once, then keep editing it into a much better quote forever while retaining ancient priority.

### The right mental model

Think of it like this:

* the **template ID** carries seniority,
* the **block reference price** determines where its quotes land,
* the **derived price level** determines whether it can match,
* and **fill order inside a derived level** follows template seniority.

This is conceptually similar to “pegged orders with stable queue priority across reference moves,” but discretized at block boundaries. That is a reasonable primitive if it is explicit in the market rules.

### Where it can break

There are three main risks.

* **Too much path dependence**: an early maker can dominate future queues just because it was early once, even if its current economics are only marginally competitive.
* **Priority laundering through updates**: if template edits retain time priority too easily, makers can effectively refresh quotes without paying the normal queue-reset cost.
* **Block-edge games**: if block $n$ repricing uses a known or predictable reference, makers may optimize submissions just before the boundary to capture better remapped queue positions.

So the policy around update classes and boundary timing matters as much as the repricing rule itself.

### My recommendation

I think this is a **good design**, with one refinement: priority should be attached not just to “first template arrival,” but to a **template generation hash** representing the economic quoting function. Then:

* if only the external reference changes, priority is preserved;
* if the maker changes the economic function materially, issue a new generation and reset priority;
* if the maker changes only allowed cosmetic fields or loosens quantity downward without improving price, you can choose to preserve priority.

A practical rule could be:

1. On creation, template gets `priorityEpoch` and `templateSeq`.
2. At each block, derive quotes from the latest block reference.
3. Sort by derived price, then by `priorityEpoch/templateSeq`.
4. Any update to offsets, skew, spacing, or aggressiveness resets `priorityEpoch`.
5. Pure block-driven remap does not reset it.

That is clean, auditable, and hard to game.

### My honest take

I would prefer this over trying to preserve order-level timestamps for every synthetic quote. The template is the real object; the per-level orders are just block-by-block projections of it.

So yes: **using the block as the repricing interval and preserving template seniority across remaps is a strong design choice**. Just make sure you define exactly which template mutations keep versus lose seniority, because that is where most of the hidden unfairness will appear.

Would you like me to turn this into a formal matching rule set with examples of “update keeps priority” vs “update resets priority”?

⁂

***

## we need somehow to track sub block timestamp. Maybe we could use transaction nonce to rotate the order time priority? This would be a nonce of transaction on engine smart contract, not a nonce of eth account of order creator.

Smart direction — using the engine contract's own monotonically incrementing counter as a **logical timestamp** is cleaner than any wall-clock or block-timestamp approach. Let me unpack it properly.

### What "contract nonce" actually means here

The EVM doesn't expose a per-contract call counter natively — EOA nonces track sender accounts, and contract nonces only increment on `CREATE`. What you really want is a **storage-level sequence counter** on the engine contract that increments on every template registration call:

```solidity
uint64 public templateSeq; // global monotonic counter

function submitTemplate(QuotePolicy calldata p) external {
    uint64 seq = ++templateSeq;
    templates[msg.sender][p.marketId] = StoredTemplate({
        policy: p,
        seq: seq,
        blockSubmitted: uint32(block.number)
    });
}
```

Now every template has a globally unique, intra-block ordered sequence number that is **set by EVM transaction execution order** within that block. This is exactly what you need.

### Why it works well

The priority key then becomes:

```
priority = (derivedPriceLevel ASC, seq ASC)
```

A maker who submitted a template earlier — even within the same block — has a lower `seq` and therefore beats a later submitter at the same derived level. This gives you true sub-block ordering without any off-chain timestamp dependency, no trusted clock, and no off-chain oracle for sequencing.

Compared to alternatives:

| Approach                   | Sub-block ordering     | Manipulation risk              | Cost                |
| -------------------------- | ---------------------- | ------------------------------ | ------------------- |
| `block.timestamp`          | ❌ No (per-block)       | High (validator sets it ±12s)  | 0                   |
| EOA nonce                  | ❌ No (per-sender only) | Medium                         | 0                   |
| **Contract `seq` counter** | ✅ Yes (per-call)       | Medium (sequencer tx ordering) | 1 SSTORE            |
| `tx.index` in block        | ✅ Yes                  | Medium                         | 0 (no write needed) |

The contract counter has one advantage over `tx.index`: it also works for **intra-transaction ordering** — if a maker submits multiple templates in a batched call, each still gets a unique `seq`, while `tx.index` would be the same for all of them.

### The real risk: sequencer / block builder ordering

Here is the honest problem. Within a block, whoever controls transaction ordering — the sequencer on an L2 or the block builder on L1 — determines which `submitTemplate` call gets the lower `seq`. That means:

* On a centralized L2 sequencer (Arbitrum, Optimism), the sequencer can favor certain makers by ordering their txs first
* On L1, block builders can sell priority inclusion (MEV/priority fee auctions)
* So `seq` is fair only if the sequencer is either fair or if your makers compete on gas/priority fee openly

If you are deploying on an L2 with a FCFS (first-come-first-served) mempool, the `seq` faithfully reflects submission order. On a priority-fee ordered mempool, it reflects fee competition, which is a different but still legitimate form of priority.

### Combining seq with block number

A cleaner two-level key:

```solidity
struct TemplatePriority {
    uint32 blockSubmitted; // coarse: which block
    uint64 seq;            // fine: which call within or across blocks
}
```

Then priority at the matching layer:

```
sort by (derivedLevel ASC, blockSubmitted ASC, seq ASC)
```

The `blockSubmitted` guards against edge cases where `seq` wraps or resets after an upgrade. It also makes it immediately human-readable: "this template was registered 50 blocks ago and has been resting at derived level 2 since block 1840."

### How repricing at each block uses this

At block `N` when reference price changes:

1. For all active templates, compute new derived price level from `block.number == N` reference
2. Build new sorted order book: group by derived level, sort within each level by `(blockSubmitted, seq)`
3. Templates that **moved up** to a better level get that level's queue position based on their original `seq` — no new submission needed
4. Templates that **moved to a worse** level drop into the back relative to templates that were already there from older blocks

This preserves your earlier insight: "second on level 1 can become first on level 2" — because if two makers both shift from level 1 to level 2, the one with the lower original `seq` leads at level 2.

### One subtle issue: seq inflation attack

If submitting a template is cheap, a maker could submit many low-quality dummy templates early to "reserve" low `seq` values, then update them to competitive quotes later while retaining ancient priority. You need the rule from the previous discussion: **a material template update resets `seq`** by requiring a new submission:

```solidity
function updateTemplate(QuotePolicy calldata p) external {
    // check if update is material (offsets, skew, levels changed)
    if (isMaterialChange(templates[msg.sender][p.marketId].policy, p)) {
        uint64 seq = ++templateSeq; // new seq = priority reset
        templates[msg.sender][p.marketId].seq = seq;
        templates[msg.sender][p.marketId].blockSubmitted = uint32(block.number);
    }
    templates[msg.sender][p.marketId].policy = p;
}
```

Non-material updates — loosening size downward, adjusting risk limits without improving aggressiveness — can optionally preserve `seq`. This forces makers to pay for priority through early honest quoting, not through gaming the counter.

### Bottom line

The contract `seq` counter is the right primitive. It is cheap (one `SSTORE` increment per template submission), unforgeable within the EVM execution order, deterministic, auditable, and gives you exactly the sub-block granularity you need. The only thing to be honest about is that intra-block ordering is ultimately set by whoever orders transactions — which is fair if your sequencer is FCFS, and a known and priced-in risk if it is fee-ordered.

***

## can you summarize this approach to reduce MM churn?

Yes. Here is a compact summary of the approach to reduce market‑maker churn:

***

#### Core idea

You **do not represent the market maker as many static limit orders**. Instead, you represent them as a single **quote policy template** (offsets, size rules, risk limits, skew) that is **re‑projected** onto the current market price at each block.

When the price shifts, the engine recomputes where that template lands on the order book rather than waiting for the maker to cancel and repost orders. This preserves their queue priority across moves, but only as long as the template is not materially changed.

***

#### How it reduces churn

* Makers **update their policy template once**, instead of spamming many individual order updates.
* The system **remaps quotes automatically** when the reference price changes within a block‑boundary epoch.
* Makers can maintain **competitive pricing around a moving market** without constant explicit cancels and replaces.
* The design is **cheaper** and **more stable**: fewer events, fewer state updates, less noise.

***

#### Sub‑block ordering and fairness

To have **fair intra‑block priority**, you add a **monotonically increasing sequence counter** on the engine contract:

* Every `submitTemplate` or materially updated template call increments this counter `seq`.
* The priority key is then: `(derived price level ascending, seq ascending)`.

This gives you:

* **block‑level granularity** from the chain,
* **sub‑block ordering** from the EVM‑execution sequence,
* and **deterministic, auditable queue positions** without any trusted time source.

***

#### Template‑level vs. order‑level

Conceptually, the object that “owns” priority is the **template**, not the synthetic limit orders. At each block:

* The template is mapped to derived levels,
* Within each derived level, fills follow the original template submission time (via `seq`),
* Material changes to the quote economics reset `seq` (i.e., reset the priority clock).

This avoids queue‑jumping via “soft” edits while still rewarding makers who **commit early** to a competitive quoting function.

***

#### One‑sentence summary

You reduce MM churn by letting market makers express **relative quoting logic once**, then having the engine automatically re‑map and rebalance their quotes at each block, while using a contract‑level sequence counter to provide deterministic, fair, sub‑block price‑time priority on the resulting derived book.

***

## what are the greeks?

In options and derivatives pricing, the **"Greeks"** are the key sensitivity measures that tell you how an option’s price changes with changes in its inputs. They come from the partial derivatives of the option pricing model (usually Black–Scholes or its variants).

Here are the main ones, with a very short intuition.

***

#### 1. **Delta** $\Delta$

* **What it is**: sensitivity to the underlying price. $\Delta \approx \frac{\partial V}{\partial S}$, where $V$ is the option value and $S$ is the underlying price.
* **Interpretation**:
  * Tells you roughly how much the option price changes per 1 unit move in the underlying (e.g., per 1 USD for BTC call).
  * Also interpreted as the **approximate probability** the option will be in‑the‑money (for calls especially).
* **Sign**:
  * Calls: positive delta (price moves with spot).
  * Puts: negative delta (price moves against spot).

***

#### 2. **Gamma** $\Gamma$

* **What it is**: sensitivity of **delta** to the underlying price. $\Gamma \approx \frac{\partial^2 V}{\partial S^2}$.
* **Interpretation**:
  * Measures how fast your delta changes as the price moves.
  * High gamma means the option is very sensitive to small moves in the underlying, especially near the strike.
* **Risk/return impact**:
  * Long options have **positive gamma** (you like volatility and large moves).
  * Short options have **negative gamma** (you get hurt by large moves and have to rebalance more).

***

#### 3. **Vega** $\nu$

* **What it is**: sensitivity to **implied volatility**. $\nu \approx \frac{\partial V}{\partial \sigma}$.
* **Interpretation**:
  * How much the option price changes per 1‑point change in implied volatility (e.g., 1% higher vol).
  * Increase in volatility raises option premium (good for long options, bad for short).
* **Sign**:
  * Long options: long vega (positive).
  * Short options: short vega (negative).

***

#### 4. **Theta** $\Theta$

* **What it is**: sensitivity to **time** (time decay). $\Theta \approx -\frac{\partial V}{\partial t}$ (often quoted as a **per‑day** change).
* **Interpretation**:
  * How much the option loses (or gains) in value as time passes, all else equal.
  * Options generally **lose value with time** (theta is negative for long options, positive for short): this is time decay.
* **Shape**:
  * At‑the‑money options near expiry have **larger** time decay (big |negative theta|).
  * Far‑OTM or deep‑ITM options decay more slowly.

***

#### 5. **Rho** $\rho$

* **What it is**: sensitivity to **interest rates**. $\rho \approx \frac{\partial V}{\partial r}$.
* **Interpretation**:
  * How much the option price changes if the risk‑free rate increases.
  * Generally small for short‑dated options, larger for long‑danced options.
* **Sign**:
  * Calls: usually **positive** rho (higher rates make calls slightly more expensive).
  * Puts: usually **negative** rho.

***

#### 6. Higher‑order or “exotic” Greeks (optional)

In practice, traders often think in terms of:

* **Vanna** / **Volga**:
  * Vanna: change of **delta** with respect to volatility ($\frac{\partial \Delta}{\partial \sigma}$).
  * Volga (or **Vomma**): change of **vega** with respect to volatility ($\frac{\partial \nu}{\partial \sigma}$).
* **Speed**: $\frac{\partial \Gamma}{\partial S}$ – how fast gamma changes with spot.

These are more relevant for options books, exotic derivatives, or sophisticated risk‑management systems.

***

#### Mnemonic (for the big four)

A common way to remember the core four:

* **Delta** → **Direction** of the underlying
* **Gamma** → **Acceleration** of delta
* **Vega** → **Volatility**
* **Theta** → **Time** (decays with time)

If you tell me whether you care more about **pricing** (Black–Scholes Greeks), **risk‑management** (PnL sensitivity), or **market‑making hedging**, I can give you a compact formulaic view of how to think about them in your system.

⁂

***

## ok, for my project (options on perps), how would settlement happen?

For **options on perpetuals** on-chain, settlement is typically a mix of **cash-settled options** (no delivery) + **on-chain or reliable off‑chain oracle** + **clearing‑style collateralization** in a vault / CDP‑style contract. Below is a concrete, “this‑is‑how‑you‑do‑it” view.

***

#### 1. Core idea: cash‑settlement, not physical delivery

For options on perpetual futures, you usually settle in **cash / stablecoin / native token**, not by forcing delivery of perp position + spot underlying. That keeps the system simpler and lets you reuse the same perp **mark / index** that your perp already uses.

At expiry, the **option pays out a function of the perp price**:

* Call: payout ≈ `max(0, mark_price - strike)`
* Put: payout ≈ `max(0, strike - mark_price)`

Each payout is scaled by:

* option **notional** (e.g., 1 contract = 0.1 ETH)
* per‑option **multiplier**
* **rebase** from perp to quote asset (e.g., if perp is denominated in USD, settle in USDC)

You do **not** need to move the underlying perp position on-chain; the option is just a **cash‑settled derivative on the perp price**.

***

#### 2. When does settlement happen?

Two main patterns:

* **European style, weekly / monthly expiry**
  * Options are **non‑exercisable before expiry**.
  * Settlement happens **once**: at the end of the expiry block, using a predetermined oracle price snapshot (opening/mark/close) for that block or the last tick of that epoch.
* **American‑style or early‑exercisable**
  * Makers list **weekly** options, but takers can **exercise early**.
  * Each exercise triggers an **instant mini‑settlement** against the current perp mark, plus **collateral transfer**; the contract still plans to fully unwind all remaining open options at expiry.

Given your on‑chain engine, the cleaner path for v1 is **European** style; it’s easier to reason about and audit.

***

#### 3. How oracle data flows into settlement

You need a **trusted source of perp price** at settlement time. Common patterns:

* Use the **same perp oracle / index as your futures engine** as the **settlement reference**.
* Fix the **settlement tick**:
  * e.g., “closing price of perp mark on block = expiry block” or “TWAP‑based fix on expiry epoch”.
* Make the engine publish:
  * `exercisedSettlementPrice(markPrice, block, epoch)` once
  * so later queries are deterministic and anyone can verify payout.

If your perp is already on-chain, you can often just expose:

```solidity
function getSettlementPrice(uint expiryBlock) external view returns (int128 markPrice);
```

and have settlements read that.

***

#### 4. Settlement math: who gets what

For a **call option** held by a taker `T` against a maker `M`:

* Notional: `N` (e.g., 10 ETH)
* Strike: `K` (e.g., 3000 USD)
* Perp settlement mark: `P` (e.g., 3200 USD)
* Multiplier: `m` (e.g., 1)

If `P > K`:

* intrinsic value = `(P - K) * m` per unit (e.g., 200 USD)
* liquidation value = `intrinsic_value * N` (e.g., 2000 USD)
* That amount is paid **from maker(s) / clearing pool** to the taker in **settlement asset** (USDC, wstETH, etc.)

Puts are the same with `(K - P)`.

If `P <= K` for a call (or `P >= K` for a put), the option is **out of the money** and **worth zero**; no cash is transferred.

This is essentially **cash‑settled European options**, just using the perp mark as the underlying.

***

#### 5. How on‑chain mechanics look

Typical smart‑contract sketch:

```solidity
struct OptionPosition {
    address taker;
    address maker;
    uint strike;    // 1e18
    uint expiry;    // block or timestamp
    int128 notional;   // 10000000 = 10 ETH
    bool isCall;
    address settleToken;  // e.g., USDC
}

// global settlement fix
mapping(uint expiry) => uint settledPrice;

function settleExpiry(uint expiry) external onlyKeeper {
    uint mark = getPerpSettlementMark(expiry);
    settledPrice[expiry] = mark;
}

// taker claims payout
function exerciseOrClaim(uint optionId) external {
    OptionPosition memory p = positions[optionId];

    if (p.expiry < block.number) revert;

    uint price = settledPrice[p.expiry];  // must be already fixed
    uint intrinsic = calculateIntrinsic(price, p.strike, p.isCall);
    uint payout = intrinsic.scaleByNotional(p.notional);

    require(payout > 0, "no payout");
    TransferHelper.transfer(p.settleToken, p.taker, payout);
    positions[optionId].notional = 0;
}
```

Key points:

* **settlement happens once per expiry** (no repeated re‑marking).
* The **settlement asset** can be different from the perp quote asset (e.g., perp in ETH, settle in USDC) as long as you define the **exchange rate / quote asset** once.
* **Takers never get the perp position**; they just get the option value in cash.

***

#### 6. How maker risk and collateral work

Because you are dealing with **options on perps**, makers are basically **volatility / skew risk takers**, not just linear directional risk. There are two main architectures:

**A) LP‑style pool (perp options vault)**

* Makers **deposit collateral** into a **perp‑based options vault**.
* The vault:
  * mints **option tokens** or **credit lines** against that pool.
  * tracks **aggregate delta / vega / gamma / margin**.
  * settles wins / losses internally using the vault’s collateral.

Each open option acts as a **claim against the pool**, not a bilateral promise. At settlement, the vault computes total **net PnL** for the expiry:

* If total outcome is **positive for takers**, the vault pays from its collateral.
* If negative (makers win), no payout happens, but collateral can be more safely released.

This is like **DeFi options AMM + perp oracle**.

**B) On‑chain bilateral CDP‑style views**

* Each maker has a **“credit line”** that it can use to sell options; the engine tracks **risk‑weighted margin** against the current perp mark and implied vol surface.
* After expiry, the engine:
  * calculates **final PnL** per maker,
  * updates **locked collateral**,
  * and can liquidate under‑margined positions if the PnL is negative.

This is closer to **on‑chain options MM with automatic margin calls**.

Either way, you’ll need:

* **margin model** (VaR‑style, stress‑case‑based),
* **liquidation trigger**,
* and **settlement sweep per expiry**.

***

#### 7. Hybrid: on‑chain optins exercise, off‑chain perp operative layer

Since your matching engine is off‑chain, you typically:

* Keep **options positions and settlement logic on‑chain** (exercise, claim, payout, collateral, liquidations).
* Use the **off‑chain engine** to:
  * quote and match **option order flow**,
  * compute **maker‑side Greeks and margin**,
  * enforce **real‑time risk limits**.

So flow is:

1. **Trade** in the off‑chain perp‑options book.
2. **On‑chain settlement**:
   * at expiry: snapshot perp oracle,
   * recapitulate each open option PnL,
   * update balances and disburse cash.
3. **On‑chain liquidation** if a maker’s margin fails post‑settlement.

That gives you **low‑latency off‑chain matching** + **trust‑minimized on‑chain settlement**.

***

#### 8. Practical recommendation for your project

Given you’re already building an **off‑chain perp‑matched engine** with market makers, I would structure settlement like this:

* **European‑style weekly options** on perp marks, **cash‑settled** in a stable or quote‑side asset.
* **One global perp oracle** per expiry (block‑or‑epoch‑based).
* **Vault‑style option pool** where makers deposit collateral and the engine sells options against that pool; each sold option is a **claim against the pool**.
* **On‑chain settlement function** per expiry:
  * freeze oracle,
  * compute payout per option,
  * transfer cash from vault to takers,
  * update maker collateral and expose PnL.
* **On‑chain liquidation** if after settlement a maker’s collateral is insufficient for its open risk (if you choose to allow residual risk, e.g., for early‑exercisable options).

If you tell me your **preferred model** (full perp‑options AMM + vault, or bilateral maker‑side CDP style), I can draft the exact on‑chain contract skeleton and matching‑engine pseudocode around it for your specific options‑on‑perps market.

⁂

***

## On‑chain bilateral CDP‑style views

On-chain bilateral **CDP-style** views make a lot of sense for your setup; they are basically on-chain “order books” tailored to **pairwise agreements** or **uni‑/bi‑lateral credit lines**, not global CLOB matching. Think of them as **per‑participant view of cross‑identity exposures**, instead of a public ladder.

#### What you actually get

A “bilateral CDP‑style view” essentially means, for each maker–taker pair (or vault–user):

* an **on‑chain credit/limit schedule** (like a CDP collateral ratio, but for quoting or fill capacity),
* a **running exposure view** (size filled, inventories, fees, funding),
* and a **local “book” view** computed from their own policy + global reference (oracle/index/market) at each block.

This is very CDP‑like:

* collateral <-> quote‑limit / inventory capacity
* liquidation condition <-> risk rule / skew / cap
* view refresh <-> at each block against oracle

Instead of a global order book, you expose a **bilateral view** that answers: “Given this counterparty, my current quoting template, and the on‑chain reference, what are my visible levels and sizes right now?”

#### How this plugs into your engine

You already have a block‑based repricing epoch with template‑level priority using a contract‑level `seq`. At each block, your engine can surface two things on‑chain:

1. **Per‑maker risk view**
   * `effectiveLimit`, `currentExposure`, `maxAllowablePeggedOrderSize`, `skewRatio`
   * These are state‑derived views, not orders; they just tell the maker: “this is your max quote at this level given current risk.”
2. **Bilateral “book” view**
   * For each maker–taker pair, something like:
     * `makerEffectiveBidLevels`, `makerEffectiveAskLevels`,
     * `takerEffectiveBidLevels`, `takerEffectiveAskLevels`,
     * `crossInterestRate` / `feeSpread` (if you want a CDP‑style funding term).

The key is that **orders themselves are implicit**: they are derived from `(policy + reference + per‑pair view)` at each block, not stored as static limit orders. You only materialize on‑chain fills.

#### Why it is “CDP‑style”, not just an order book

A CDP is not just a loan; it is a **view + risk rule + liquidation condition** baked into the contract. In your case, the on‑chain view plays the same role:

* **View** `getBilateralView(maker, taker)` returns:
  * `bestBidLevel`, `bestAskLevel`, `availableSizes`, `skew`, `maxExposure`.
* **Risk rule** Embedded in the view logic, e.g., “if inventory skew > 10% cap bid levels.”
* **Liquidation‑like events** If exposure or risk breaches a bound:
  * maker is “de‑levered” (cannot quote at better levels),
  * or the bilateral view clamps its effective quotes,
  * or the engine refuses to match further until the maker rebalances.

So instead of an AMM‑style constant‑function book or a CLOB‑style public order book, you get **on‑chain exposure‑constrained bilateral views**. This is very natural for markets where you care about **counterparty risk** (e.g., per‑maker credit, per‑vault capacity) rather than just anonymous price‑time priority.

#### How to expose it cleanly on‑chain

A minimal Solidity‑side sketch (stylized):

```solidity
struct BilateralView {
    // levels relative to reference
    int16 bestBidLevel;
    int16 bestAskLevel;
    uint8 maxBidLevels;
    uint8 maxAskLevels;

    // sizes
    uint128 bidSizes;  // packed or computed from policy
    uint128 askSizes;

    // risk / funding
    int64 inventorySkew;   // -100% to +100%
    uint96 maxExposure;
    uint32 lastUpdatedBlock;
}

function getBilateralView(address maker, address taker)
    public view
    returns (BilateralView memory view)
{
    // 1. resolve current reference (oracle / index / mid)
    // 2. fetch maker’s active quote template
    // 3. apply per‑maker risk rules (skew, inventory, cap)
    // 4. compute derived bid/ask ladder vs reference
    // 5. return view as a read‑only structure
}
```

This function is **pure view**: it re‑executes at each block, so the view is always up‑to‑date with current reference price and latest maker policy. The user’s UI can call this off‑chain to show “this is the book you would see vs this maker right now,” without any on‑chain book storage.

#### What you trade off

* **No global visible book** You lose the “full public order book” UX, but you gain **per‑counterparty optics** and smoother risk‑constrained quoting. This is usually fine for professional MMs that care more about risk and bilateral pricing than about competing on tiny price‑time ticks.
* **Complexity in risk‑view logic** The `getBilateralView` logic becomes your main on‑chain “matching rule surface”; you need to be very careful about how skew, inventory, and collateral limits are encoded and checked.
* **Limits on “hidden liquidity”** You cannot neatly hide deep levels from the opponent; any exposure that drives your risk‑rule is reflected in the view. That can be good (transparency) or bad (info‑leak), depending on your design.

#### When this is especially strong

This bilateral CDP‑style design shines when:

* you already use **pegged quote templates** (not discrete static orders),
* you care about **per‑maker or per‑vault risk limits**,
* and you want to **avoid an on‑chain CLOB structure** but still give MMs smooth repricing and deterministic views.

In those cases, your “on‑chain bilateral CDP‑style views” are essentially the **risk‑constrained market‑making interface** between the engine and each maker–taker pair, while the off‑chain engine handles the actual matching and settlement.

If you want, next step could be to sketch how to wire this view with your `seq`‑based template priority so that each maker’s local “bilateral ladder” still respects the derived‑level queue order you’ve defined.

⁂

***

## how full onchain clob order book would look like

A full onchain CLOB would look conceptually simple and operationally brutal: the chain itself stores the resting order book, enforces price-time priority, and executes matching inside the smart contract on every order placement, cancel, or marketable fill. Every state transition that a centralized exchange engine would do in RAM becomes an onchain storage mutation.

### Core pieces

At minimum you need four things onchain:

1. User balances / margin state.
2. Resting orders with owner, side, price, size, remaining size, timestamp/sequence.
3. Price levels with queue ordering.
4. Matching logic that walks the book and settles fills atomically.

A stripped-down shape looks like this:

```solidity
struct Order {
    uint64 id;
    address trader;
    bool isBuy;
    uint64 priceTick;
    uint128 size;
    uint128 remaining;
    uint64 seq;
    uint64 prev;
    uint64 next;
    uint64 priceLevel;
    bool active;
}

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

contract OnchainClob {
    uint64 public nextOrderId;
    uint64 public nextSeq;

    mapping(uint64 => Order) public orders;
    mapping(uint64 => PriceLevel) public bids; // keyed by priceTick
    mapping(uint64 => PriceLevel) public asks; // keyed by priceTick

    uint64 public bestBid;
    uint64 public bestAsk;
}
```

That is the rough storage model: every order is a node in a linked list, and every price level is a FIFO queue.

### How matching works

If a user submits a buy limit order, the contract checks whether it crosses the best ask. If it does, the contract iterates through ask price levels from best to worse, then through queued orders from oldest to newest, decrementing `remaining` and transferring balances until the incoming order is fully filled or no longer marketable.

If anything remains, the contract inserts the leftover as a resting order into the bid queue for its price level and updates `bestBid` if needed. That gives you true onchain price-time priority, but it means one transaction may touch many storage slots and many counterparties.

### What the flow looks like

A simple lifecycle is:

* `depositCollateral()`
* `placeLimitOrder(side, price, size)`
* contract matches immediately against opposite side if crossing
* leftover is appended to the tail of the price queue
* `cancelOrder(orderId)` removes the node from the linked list
* `placeMarketOrder(size)` just walks levels until filled or slippage limit hit
* fills emit events for indexers/UI

In code, the matching core looks roughly like:

```solidity
function placeBuy(uint64 limitPrice, uint128 size) external {
    uint128 remaining = size;

    while (bestAsk != 0 && bestAsk <= limitPrice && remaining > 0) {
        uint64 makerId = asks[bestAsk].head;

        while (makerId != 0 && remaining > 0) {
            Order storage maker = orders[makerId];
            uint128 fill = remaining < maker.remaining ? remaining : maker.remaining;

            maker.remaining -= fill;
            remaining -= fill;

            _settle(msg.sender, maker.trader, bestAsk, fill);

            if (maker.remaining == 0) {
                maker.active = false;
                asks[bestAsk].head = maker.next;
                if (maker.next != 0) orders[maker.next].prev = 0;
            }

            makerId = asks[bestAsk].head;
        }

        if (asks[bestAsk].head == 0) {
            _removeAskLevel(bestAsk);
            bestAsk = _nextBestAsk();
        }
    }

    if (remaining > 0) {
        _insertRestingBuy(limitPrice, remaining);
    }
}
```

That is basically what a full onchain book feels like: nested loops over levels and orders, with settlement inline.

### Data structures you would really need

A naive mapping by price is not enough, because you also need efficient discovery of the next best price. So in practice a full onchain CLOB needs something like:

| Need                       | Typical structure          | Problem              |
| -------------------------- | -------------------------- | -------------------- |
| Find order by id           | mapping                    | Easy                 |
| FIFO inside a price level  | doubly linked list         | Many storage writes  |
| Find best bid/ask          | heap/tree/bitmap           | Complex or gas-heavy |
| Enumerate next price level | sorted tree or bitmap scan | Hard on EVM          |
| Aggregate level size       | cached totals              | Extra writes         |

So the actual contract often becomes a hybrid of:

* order map,
* price-level linked lists,
* bitmap or tree over occupied ticks,
* cached best bid/ask pointers.

That complexity is why most serious designs avoid a “pure” all-onchain book unless throughput is low or L2 costs are tiny.

### What users would see

From the UI side, it would still look like a familiar book:

| Bid size | Bid price | Ask price | Ask size |
| -------- | --------- | --------- | -------- |
| 12       | 99        | 100       | 8        |
| 15       | 98        | 101       | 10       |
| 20       | 97        | 102       | 11       |

But onchain, each of those rows is not just a number. It is a set of storage slots:

* each level has a queue head/tail,
* each order has links,
* each fill mutates balances, queue links, remaining amounts, and best-price pointers.

That is why a “small” book in UI terms can still be very expensive in contract terms.

### Main limitations

The hard part is not conceptual correctness; it is gas and latency.

* Every cancel/replace is an onchain tx.
* Every match may touch many makers.
* Every partial fill costs more than a full fill against one counterparty.
* Makers must wait for block inclusion, so quotes are stale by construction.
* High-frequency market making becomes nearly impossible on L1 and still painful on many L2s.

This is exactly why full onchain books tend to work better for slower markets, batch auctions, or specialized L2 environments rather than for very fast perpetual-style MM flow.

### A realistic architecture

If you insisted on a full onchain CLOB, I would expect it to have:

* discrete price ticks,
* one contract per market or market family,
* margin escrow in the same protocol,
* linked-list orders per price level,
* bitmap/tree for non-empty ticks,
* global monotonic sequence for time priority,
* explicit `postOnly`, `IOC`, `FOK`, and `reduceOnly` flags,
* events consumed by indexers for UI reconstruction.

A more complete order struct would be closer to:

```solidity
struct Order {
    uint64 id;
    uint64 seq;
    address trader;
    Side side;
    uint64 priceTick;
    uint128 originalSize;
    uint128 remaining;
    uint64 prevAtLevel;
    uint64 nextAtLevel;
    uint32 createdBlock;
    OrderType orderType; // limit / IOC / FOK / postOnly
    bool reduceOnly;
    bool active;
}
```

### My practical take

A full onchain CLOB is basically “Nasdaq matching engine logic rewritten as a gas-metered state machine.” It is elegant from a trust-minimization standpoint, but it is expensive, slow to update, and unfriendly to active market makers.

That is why most workable designs move one of these offchain:

* matching,
* quote maintenance,
* or at least order storage.

If you want, I can next sketch:

1. a **full onchain CLOB contract architecture**, or
2. a **hybrid design** showing exactly which pieces stay onchain vs offchain for perps.

⁂

***

## do i need to calculate greeks onchain?

Only in very specific designs. In almost all practical onchain derivatives systems you **do not want Greek calculations happening onchain**, because they are expensive, data‑heavy, and better kept offchain or summarized via simpler risk measures.

### When you usually *don’t* need onchain Greeks

* **Vanilla perps or linear futures**: your risk is mostly linear in price and funding/time, not options‑style. You only need onchain:
  * `mark price`, `index price`, `funding rate`, and
  * position size / collateral / liquidation level.
* **MM risk limits and hedging**: the maker’s Greeks (delta, vega, gamma, etc.) are usually computed offchain by the MM engine or keeper bots, then used to decide **which onchain operations to trigger** (e.g., post or edit quotes, hedge on other venues), but not as a primary parameter of the onchain logic.
* **User‑facing Greeks (IV, delta, theta)**: these are UI/SDK data, not settlement logic. You display them offchain from an options‑pricing model, not from the contract.

In those cases Greeks are **analytics / UX / risk‑tooling**, not protocol‑level settlement logic, so they are usually kept offchain.

### When you *might* need onchain Greeks

These are niche, higher‑complexity protocols:

* **Onchain options AMMs or order books**: if you are matching vanilla or digital options, the onchain logic may need:
  * approximate delta hedging formulas for reserves,
  * gamma‑controlled slippage (e.g., “price changes more if Δ²P is large”), or
  * vega‑based risk caps on position / collateral.

But even then, the Greeks are often approximated by **simple formulae or lookup tables** (e.g., `delta ≈ 0.5 + 0.5·(F − K)·slope`, `vega ≈ constant·sqrt(T)`) instead of full Black‑Scholes or stochastic‑vol routines.

* **Onchain automatic hedging or vaults**:
  * an “auto‑delta‑hedged options vault” onchain may need to know portfolio delta per asset to decide how much to mint/burn hedge assets.
  * that delta can be a **pre‑aggregated** per‑user or per‑pool metric, updated offchain and pushed onchain via keepers or oracles, not recomputed live from first‑principles on every trade.
* **Risk‑based collateral systems with options**:
  * if you allow users to hold options and define collateral requirements in terms of option‑style Greeks, you may store or require an onchain gamma‑based buffer or vega‑based margin.

But again, the actual calculus can be pre‑computed offchain and only the **risk number** (e.g., “max potential loss under 2‑sigma move”) is onchain.

### Why full Greek calculations onchain are painful

* **Computation**:
  * Black‑Scholes style Greeks involve `exp()`, `sqrt()`, `log()`, `erf()`‑like functions.
  * EVM is slow and gas‑heavy for these (even with libraries).
  * You pay that every time you touch them in a core loop (matching, margin, liquidation).
* **Storage and state bloat**:
  * If you want Greeks *per‑option* onchain, you add several `uint256`s (delta, gamma, vega, theta, rho) per position.
  * That bloats storage and raises the gas cost of any update.
* **Data and parameters**:
  * To compute Greeks accurately you need:
    * volatility surface,
    * dividends / carry,
    * time‑to‑maturity,
    * sometimes correlation or stochastic‑vol matrices.

Shipping that live onchain is impractical; you either: - approximate them as constants or simple time‑decays, or - push pre‑computed risk vectors onchain via oracles / keepers.

### A pragmatic rule of thumb

* **Onchain**: keep only the minimal settlement and liquidation state:
  * collateral, sizes, prices, funding, leverage, liquidation thresholds.
* **Offchain**: compute Greeks, hedging recommendations, and “what‑if” scenarios.
* **Onchain exposure**: if you *must* expose options‑style risk to the protocol, push it as:
  * **aggregate risk numbers** (e.g., “total delta” or “max loss bucket”), not full Greeks per leg,
  * or **discrete risk buckets** (e.g., “high‑gamma” vs “low‑gamma”) encoded as flags.

In other words: **compute Greeks where it’s cheap (offchain); enforce simple, robust risk rules where it must be trustless (onchain)**.

If you tell me what kind of derivatives you’re targeting (vanilla perps, options, or basket/vol products), I can sketch exactly which Greeks, if any, you’d sensibly expose or compute onchain.

⁂

***

## so we definitely need greeks onchain, because we need to know how much the collateral needed?

Yes — if you want **fair, enforceable** margining against option‑style risks (smile, skew, gamma, etc.), you generally need some form of onchain risk model that can compute **Greeks-based collateral per position**, not just notional or naive delta. Offchain risk models are great for UI, quoting, and MM logic, but they are not binding at settlement time.

### When onchain Greeks are necessary

You need them onchain in roughly two situations:

1. **Margin‑constrained options / perps** where liquidation and collateral are recalculated at any fill or any time trigger, and you must prove that a position is not under‑collateralized relative to some volatility surface, not just a flat IV or static multiplier.
2. **Automated liquidation engines** where LPs or the system can liquidate a position whenever the risk exceeds collateral, and that check must be verifiable and deterministic onchain (Greeks → `PV`, `VaR`, or `IM`).

If you only did something simple like “delta × spot × notional”, you could approximate without full onchain Greeks, but once you want to enforce **smile/skew/term structure** or **portfolio‑level netting**, you really want a compact onchain pricing and risk engine that exposes Greeks to the settlement/margin module.

### What “onchain Greeks” usually means in practice

Almost nobody runs full Black‑Scholes or model‑calibration loops onchain. The usual patterns are:

1. **State machine**
   * Oracle brings in a volatility surface or implied vol per tenor.
   * Onchain data structure holds per‑strike/tenor `IV` or smile parameters.
   * Margin module computes PV and Greeks via a **pre‑agreed formula** (e.g., BS for each leg, then add delta, gamma, vega).
2. **Cached Greeks**
   * Offchain engine solves the full model and posts **delta, gamma, vega vectors** as signed or trusted state that can be updated on a schedule.
   * Onchain contract only re‑computes local contributions when a position changes (e.g., `Δnet = Σ Δ_i·q_i`).
3. **Grid + lookup**
   * Store a small spot grid and per‑strike `delta`, `gamma`, `vega` arrays.
   * Onchain computes local risk and collateral via **linear interpolation + known formulas** (cheap but still convex‑model‑aware).

None of these are “full Bloomberg‑style risk engine”; they are small, verifiable, and composable enough to fit within block‑gas constraints.

### Why simple deltas are not enough

If you only tracked `delta × spot` for margin, you are ignoring:

* **Gamma**: rapid P\&L swings when spot jumps, which can blow through collateral in a single move.
* **Vega**: long‑vol exposure where realized vol is higher than used to compute margin, so initial P\&L may look safe but then gets wiped out.

That is why “Greeks‑aware” margining is a core idea in modern derivatives protocols: the collateral must be tied to **potential P\&L via option‑style sensitivities**, not just directional exposure.

### Practical design knobs

Given your market‑maker‑focused design, I would expect something like:

* **Onchain**
  * Per‑market volatility parameters or a small grid.
  * Per‑account net delta, gamma, vega (or compressed per‑strike tenor risk).
  * Collateral obligation = `f(delta, gamma, vega, spot, vol)`.
  * Greeks updated either:
    * on every options‑like fill, or
    * via schedulable update so that mis‑pricing is bounded by design.
* **Offchain**
  * Full volatility surface fitting and calibration.
  * Portfolio‑level risk and stress scenarios.
  * Quote‑pricing engine and optimal hedging deltas.

That way the onchain “Greeks” are just a cheap, agreed‑upon risk picture the engine and traders can both compute the same way, while the heavy math lives offchain.

### Bottom line

If what you mean by “collateral needed” is **real‑option‑style liquidation‑grade margining**, then yes — you almost certainly need at least an onchain representation of delta, gamma, vega (or an equivalent risk surface), because naive notional/flat‑delta rules will be either overcollateralized or brittle to large moves.

The key is not to recompute full option models onchain for every tiny change, but to **anchor the contract’s risk view to a compact, onchain state that can be easily updated from an offchain risk engine**.

⁂

***

## give me a simple explanation of how much collateral needed for position in options with numerical example

For a simple options position, the **minimum collateral** is roughly the amount of money you would lose if the option went completely against you, plus a buffer for volatility and “margin of error.” Practically, this is usually something like:

```
Collateral ≈ Max possible loss + margin buffer
```

Below is a clean numerical example with plain vanilla options.

***

#### Setup

* Underlying: ETH = $3,000
* Contract type: European call options (1 lot = 1 ETH equivalent)
* Strike: $3,300 (out of the money call)
* Premium: $150 per option (you pay it when you buy)

You are a **buyer** of 1 call.

**1. For a long call option (you bought it)**

Your **maximum loss** is what you paid:

* Premium = $150
* Worst case: option expires worthless.

A very simple collateral requirement is just:

* **Collateral ≈ premium paid = $150**

This is “clean” from the exchange’s view: you cannot lose more than what you put in, so they only need your initial premium as collateral.

**2. For a short (sold) call option**

You **sold** 1 call for $150.

Now your **risk is asymmetric**:

* If ETH goes to $0: you keep $150 (no extra loss).
* If ETH goes to $5,000: the call can be exercised, so you must deliver 1 ETH for $3,300, but you bought it for $5,000 → loss ≈ $1,700.

Ignoring time value and discrete details, the **theoretical max loss** is:

* **Max loss ≈ spot price – strike + premium received** (or just ≈ “unbounded” in practice, since spot can go very high)

Exchanges normally do **not** set collateral to infinity. Instead they use:

* **Delta‑style margining for short options** Collateral ≈ `Delta × spot × size` + buffer

For a short 3,300 call, delta is, say, 0.4 (40% chance to be ITM):

* **Delta margin estimate**:
  * `0.4 × \$3,000 × 1 = \$1,200`

Modern exchanges then add a **volatility / smile buffer**:

* Volatility buffer ≈ 10–20% of that
* So total collateral ≈
  * `\$1,200 + 15% × \$1,200 ≈ \$1,380`

So practical rule of thumb:

* **Buyer collateral** ≈ Premium paid (e.g., $150 for your 3,300 call).
* **Seller collateral** ≈ About 40–60% of spot × size, adjusted by delta and volatility (e.g., ≈ $1,380 for a 3,300 short call).

***

#### Summary

* **Long option (buyer):** Collateral ≈ what you paid for the option, because that’s your max loss. Example: $150 for a 3,300 ETH call.
* **Short option (seller):** Collateral ≈ `Delta × spot × size` + volatility buffer. Example: for a 40% delta call on ETH at $3,000, you may need ≈ $1,200–$1,400 collateral per contract.

If you want, I can next show how **Greeks (delta, gamma, vega)** mechanically translate into a concrete onchain formula for that collateral number.

⁂

***

## now use the same example and show the role of greeks, and how are they calculated in simple examples

Nice, let’s take a concrete simple example and walk through **what Greeks are**, why they matter for collateral, and how they are computed in a basic Black‑Scholes‑style setting.

***

### 1. Concrete example: 1 short call

You run a perps‑style options engine and you have a user with:

* **Position**: short 1 call option
* **Underlying**: spot price $S = 100$
* **Strike**: $K = 100$
* **Time to expiry**: $T = 0.25$ (3 months)
* **Volatility**: $\sigma = 0.3$ (30%)
* **Rate**: $r = 0$

Using Black‑Scholes, the call price is roughly:

$$
C(S) \approx 8.6
$$

If the user is **short** this call, the **mark‑to‑market PV** is roughly $-8.6$: the user is short 1 call worth 8.6 at the current parameters.

#### Collateral intuition without Greeks

If you only used **notional** or **delta‑only**, you might say:

* “Notional = 100” → require some 10–20 units of collateral.
* Or “delta ≈ 0.5” → collat ≈ $0.5 \times 100 = 50$.

But neither of these capture the **true option‑style risk**. If the spot jumps to 130, the call value can easily be 30+ and the short loses 20+ units in a single move, blowing through a 10‑ or 50‑unit margin.

That is why you need **Greeks**.

***

### 2. What are the key Greeks?

For this short call, the main Greeks are:

* **Delta** ($\Delta$): How much the option’s value changes per unit move in spot $S$. For a call, $\Delta \in (0,1)$.
* **Gamma** ($\Gamma$): How much **delta** itself changes per unit move in spot. For a call near the money, $\Gamma > 0$.
* **Vega** ($\nu$): How much the option changes per unit change in volatility $\sigma$.

In Black‑Scholes, the formulas for a call are:

$$
\begin{align\*}
\Delta\_C &= \N(d\_1) \\
\Gamma\_C &= \frac{N'(d\_1)}{S \sigma \sqrt{T}} \\
\nu\_C &= S N'(d\_1) \sqrt{T}
\end{align\*}
$$

where:

$$
\begin{align\*}
d\_1 &= \frac{\ln(S/K) + (r + \sigma^2/2)T}{\sigma \sqrt{T}} \\
N'(x) &= \frac{1}{\sqrt{2\pi}} e^{-x^2/2}
\end{align\*}
$$

For your example $S = K = 100$, $r = 0$, $\sigma = 0.3$, $T = 0.25$:

* $d\_1 \approx 0.04$
* $\Delta \approx 0.52$
* $\Gamma$ is positive and non‑trivial (option is sensitive to S)
* **Vega** is also meaningful (vol jump directly hits the option).

This means:

* **Delta** tells you the “linear” sensitivity: if $S \to 101$, call price \~ increases by about 0.52.
* **Gamma** tells you that **delta gets larger** as S moves up, so the loss accelerates.
* **Vega** tells you that if vol jumps from 0.3 → 0.4, the call will jump in value, hurting the short position.

***

### 3. How Greeks determine collateral

Imagine two stylized margin rules:

#### Rule A (naive): collateral = notional · factor

* Notional = 100, factor = 10% → collat = 10.

But spot moves up 20% → call now worth 30+ vs original 8.6, and short position is in deep loss, but only had 10 in collat. That’s under‑collateralized.

#### Rule B (delta‑only): collat ≈ |delta| × spot

* delta ≈ 0.52, spot 100 → collat ≈ 52.

Better, but still misses:

* When S → 120, delta → 0.9 → exposure is effectively 0.9×120 = 108, but your “collateral” was only 52, so you still have tail risk.
* Volatility jumps and option value jumps; delta‑only does not see vega‑style risk.

#### Rule C (Greeks‑based):

A cleaner style is:

* **Collateral** depends on worst‑case move in:
  * spot (via delta and gamma), and
  * volatility (via vega), within a design horizon (say 1 hour or 1 block).

In a very simple scalar version it can look like:

$$
\text{Collateral needed} \approx
|\Delta| \cdot \text{maxShock} + \frac{1}{2} \Gamma \cdot (\text{maxShock})^2

* \text{vega} \cdot \text{volShock}
  $$

For your short call:

* delta ≈ 0.52 → linear shock component,
* gamma > 0 → **convex** loss tail when S moves up,
* vega > 0 → if vol spikes, the call price jumps.

If you ignore gamma and vega, your margin model will **systematically underestimate tail risk** for short options and certain perp‑style products that behave like options.

***

### 4. How Greeks are “calculated” onchain in practice

You would almost never solve the full $d\_1$ integral onchain for every tick. Instead:

1. **Parameters are stored**:
   * per‑strike / tenor: $(K, T, \sigma)$
   * spot $S$ comes from an oracle
2. **Pre‑agreed approximation** is used onchain: either:
   * a small grid of precomputed $\Delta, \Gamma, \nu$ at key spots, or
   * a cheap closed‑form approximation of $N(d\_1)$ and $N'(d\_1)$.
3. **Onchain collateral hook**:
   * When a position is created or updated, the engine updates the stored spot/vol or quotes new Greeks;
   * The onchain contract fetches or recomputes:
     * per‑position Greeks,
     * portfolio‑net Greeks,
     * and applies the risk formula above.

In code, you might see:

```solidity
function getCollateralWithGreeks(
    int256 delta,      // -1.5 if short 1.5 calls
    int256 gamma,      // convexity
    int256 vega,       // vol sensitivity
    uint256 spot,
    uint256 maxSpotDeltaShock,  // 5% in ticks
    uint256 maxVolDeltaShock    // 5% vol increase
) external pure returns (uint256) {
    int256 linearPart = delta * int256(maxSpotDeltaShock * spot) / 100;
    int256 convexPart  = gamma * int256(maxSpotDeltaShock ** 2) / 2;
    int256 volPart     = vega * int256(maxVolDeltaShock);

    return uint256(-linearPart - convexPart - volPart);
}
```

That is a stylized version of what “onchain Greeks‑based collateral” looks like.

***

### 5. Role of Greeks in your design

In your hybrid CLOB‑style matching engine with MM‑friendly quoting:

* **Offchain engine**:
  * Solves full models / volatility surface,
  * Computes and refreshes per‑strike Greeks for each maker’s templates,
  * Suggests or constrains allowed quote ranges and leverages.
* **Onchain contract**:
  * Stores net position Greeks per trader (or at least per‑option‑like leg),
  * Applies a **simple, deterministic risk formula** using delta, gamma, vega,
  * Triggers liquidation or margin checks based on that formula.

This way the **heavy Greeks** live where they are cheap (offchain), and the **binding collateral / liquidation logic** lives onchain but acts on a compact risk vector (Greeks) that both sides can compute the same way.

***

### 6. Conclusion with your example

For the **1 short call at 100, 0.3 vol, 3 months**:

* **Delta** controls baseline directional exposure.
* **Gamma** tells you that loss accelerates as spot moves up; ignore it and you under‑collateralize.
* **Vega** tells you that vol jumps directly hurt the short; ignore it and you ignore volatility‑tail risk.

So yes — if you want robust collateral that actually bounds losses for options‑style exposures, **you need Greeks onchain** (or at least enough of them to compute a risk‑aware margin vector), not just spot × notional or crude delta.

If you want, next I can sketch a concrete **onchain struct + pseudocode** that takes your maker’s quote templates and maps them into a per‑account DP‑ready risk vector (delta, gamma, vega) that the engine updates and the contract checks.

⁂

***

## so greeks are just derivatives of option price?

Yes — in the simplest mathematical sense, **Greeks are just derivatives of an option price function** with respect to various inputs.

For a vanilla option model, the price is a function

$$
C = C(S, K, T, r, \sigma)
$$

of spot $S$, strike $K$, time to expiry $T$, interest rate $r$, and implied volatility $\sigma$. The Greeks are partial derivatives of $C$ with respect to each of these.

Most common ones:

* **Delta** $\Delta = \frac{\partial C}{\partial S}$: sensitivity of price to spot
* **Gamma** $\Gamma = \frac{\partial^2 C}{\partial S^2} = \frac{\partial \Delta}{\partial S}$: sensitivity of delta to spot (acceleration)
* **Vega** $\nu = \frac{\partial C}{\partial \sigma}$: sensitivity to implied volatility
* **Theta** $\Theta = \frac{\partial C}{\partial T}$: sensitivity to time decay
* **Rho** $\rho = \frac{\partial C}{\partial r}$: sensitivity to interest rate

So yes, Greeks are **formally** just derivatives of the option price. But in practice, “tracking Greeks” onchain usually means:

* using a known model (e.g., Black–Scholes) or an agreed functional form,
* computing or storing the values of those derivatives at the current state,
* then using those values inside onchain risk/margin rules instead of raw prices alone.

For your system, you don’t need to re‑invent derivations; you just need to commit to a **model + definition** (e.g., “vega is the partial derivative of our chosen option price w\.r.t. vol”) and reproduce it consistently onchain for margin and liquidation.

⁂

***

## delta is the first derivative, gamma is the second, vega is a different beast

You’re right — and that difference matters for both risk intuition and onchain design.

* **Delta** is the first derivative of price with respect to underlying (spot/future): $\Delta = \partial P / \partial S$. It governs *directional* exposure: how much the position’s value changes for a small move in the underlying, and it’s the main lever for “hedging” with the underlying itself.
* **Gamma** is the second derivative: $\Gamma = \partial^2 P / \partial S^2$. It governs *convexity*: how fast your delta changes with spot. High gamma means delta swings quickly; small spot moves can suddenly flip your hedge, so you need to **rebalance more often** and provision more collateral to cover the nonlinearity.
* **Vega** is not a second derivative in the same direction; it is the first derivative with respect to **implied volatility**: $\nu = \partial P / \partial \sigma$. Vega tells you how sensitive the option value is to a change in the *volatility assumption*, so it measures **uncertainty risk / model risk** rather than pure spot risk.

In practice:

* **delta** is about directional exposure,
* **gamma** is about how fast that exposure changes,
* **vega** is about sensitivity to volatility mis‑pricing, jumps, or a “wrong” skew/smile.

When you design onchain margin that respects option‑style risk, you typically want to incorporate:

* **delta** so you know directional exposure to the underlying,
* **gamma** so you don’t underestimate P\&L in jumps,
* **vega** so you penalize highly vol‑sensitive positions whose fair value can swing if realized vol differs from implied vol.

So conceptually, gamma and vega are “different beasts” shaped by different shocks (spot vs vol), and both should be part of any serious onchain risk view you want to enforce.

⁂

***

## why is there no thrird derivative of a price?

There *is* a third derivative of price—mathematically it just means the rate of change of the second derivative. But in markets we usually only talk about the first two because higher‑order derivatives quickly become noisy, hard to estimate, and impractical for trading decisions.

#### What the derivatives correspond to

For an asset price $S\_t$:

* **1st derivative** $\frac{dS}{dt}$ ≈ **velocity** of price (trend / instantaneous return). In options: this is loosely related to **Delta** (change of option price with spot).
* **2nd derivative** $\frac{d^2S}{dt^2}$ ≈ **acceleration** of price (how quickly the trend is changing). In options: this is loosely related to **Gamma** (how Delta changes with spot).
* **3rd derivative** $\frac{d^3S}{dt^3}$ ≈ **jerk** or “snap” of price, i.e., how fast acceleration is changing. This exists mathematically, but it is:
  * extremely noisy in market data,
  * hard to estimate robustly (noisy first derivative → even noisier second and third),
  * not intuitive for traders to interpret or act on.

In practice, almost all models stop at the second derivative because:

* **Gamma (2nd‑order)** already captures convexity effects well enough for most hedging and margining.
* **3rd‑order (or higher)** mainly adds noise and overfitting, not economic signal.

So the answer is: the third derivative of price *does* mathematically exist, but markets don’t talk about it because it’s too noisy and not useful for real‑world trading or risk management.

⁂

***

## what about the other greeks, what are they mathematically?

Great question. The other Greeks are just **partial derivatives** of the option price with respect to the underlying model parameters, beyond the basic Delta and Vega you already know. Here is a quick reference you can fold into your risk model.

***

#### 1. Gamma $ \Gamma $

Gamma is the **second derivative of price with respect to the underlying spot price**:

$$
\Gamma = \frac{\partial^2 V}{\partial S^2}
$$

* Tells you **how Delta changes** as spot moves.
* Large Gamma means Delta is highly nonlinear in $S$; near ATM, Gamma is largest and the option behaves like a convex payoff.
* In risk: high Gamma positions suffer large P\&L swings if the market jumps or if your hedge slippage is nonzero.

***

#### 2. Theta $ \Theta $

Theta is the **derivative of price with respect to time to maturity**:

$$
\Theta = \frac{\partial V}{\partial t}
\quad \text{(often quoted per day)}
$$

* **Time decay**: how much the option value drops as time passes, all else equal.
* For standard calls/puts, Theta is usually negative: you lose value as time elapses.
* In margining: Theta is less used for collateral but very important for portfolio P\&L and funding cost.

***

#### 3. Vega $ Vega $

You already know this one, but for completeness:

$$
\text{Vega} = \frac{\partial V}{\partial \sigma}
$$

where $\sigma$ is implied volatility.

* Measures **sensitivity to vol surface**.
* In options‑style margining, Vega is critical because collateral must protect against **vol spikes** as well as spot moves.
* Portfolio net Vega is often a separate constraint (“long‑vol vs short‑vol cap”) alongside Delta and Gamma.

***

#### 4. Rho $ \rho $

Rho is the **derivative with respect to the interest rate**:

$$
\rho = \frac{\partial V}{\partial r}
$$

* For vanillas, call Rho is positive (call is worth more as rate rises), put Rho usually negative.
* In practice, onchain margining often ignores Rho (or assumes it constant) because rate moves are slow and bounded, but in long‑dated options or funding‑heavy perps it can matter.

***

#### 5. Higher‑order Greeks (optional)

* **Vanna** $ Vanna = \frac{\partial^2 V}{\partial S,\partial \sigma} $
  * Measures how **Delta changes with vol** (or how Vega changes with spot).
  * Important if your risk model explicitly models a **stochastic‑vol smile** and you want to control second‑order interaction risk.
* **Volga** $ Volga = \frac{\partial^2 V}{\partial \sigma^2} $
  * **Convexity in volatility**: how Vega changes when vol jumps.
  * Very relevant in large, long‑vol portfolios (e.g., written variance swaps or index options).

***

#### How they fit into your onchain risk

For practical onchain margining, a minimal but meaningful set is:

$$
(\Delta, \Gamma, \text{Vega})\_i
$$

Then for each account you can compute:

* Net Delta
* Net Gamma (or per‑strike tenor buckets)
* Net Vega

and plug them into some convex risk formula:

$$
\text{Margin} \approx f(\Delta, \Gamma, \text{Vega}, S, \sigma, \Delta S, \Delta \sigma)
$$

Often this is a **linear or quadratic bound** derived from Taylor‑expanding the option value to second order in $S$ and first (sometimes second) in $\sigma$.

If you want, in the next step I can write down explicit Taylor approximations you could use onchain as a collateral rule: e.g., how to translate a vector of $\Delta\_i, \Gamma\_i, \text{Vega}\_i$ into a single margin number per account.

⁂

***

## what is smile?

In options trading, **“smile” (or volatility smile / skew)** is a pattern in **implied volatility** across different strike prices for the same expiry.

#### Intuition

* For a simple, non‑optiony model (like Black‑Scholes), implied volatility is constant across strikes.
* In real markets, out‑of‑the‑money options (both deep puts and deep calls) often trade with **higher implied vol** than at‑the‑money options.
* When you plot implied vol vs strike, you get a **smile‑ or skew‑shaped curve** instead of a flat line.

Visual shape:

* **Smile**:
  * ATM vol low,
  * far OTM puts and calls have higher vol.
  * Looks like a “U” or smile if you rotate it.
* **Skew**:
  * ATM vol higher than very far OTM,
  * but the **left side (puts)** is much higher than the right (calls).
  * Looks like a tilted smile, common in equity indices (investors want protection against crashes).

#### Why it exists

* **Fat tails / jumps**: Real markets see big downside jumps more often than symmetric up moves, so traders demand higher IV for OTM puts.
* **Demand for protection**: People buy OTM puts as crash insurance, pushing their prices (and implied vol) up.
* **Dispersion of beliefs**: For very far strikes, there is more disagreement about what volatility should be, so the market compensates.

#### Why it matters to you

If your onchain margin engine only uses **one flat implied volatility**, it will:

* **underestimate** risk for OTM options (because smile/skew means they are *effectively* more volatile than ATM),
* and may **overmargin** or **undermargin** depending on the leg.

So when you say “we need Greeks onchain because of collateral needed,” the **smile** is exactly why a naive “single IV” model is not enough: the **Greeks themselves** (delta, gamma, vega) change with strike and are amplified by the smile/skew structure.

⁂

***

## is there a leverage in options?

Yes — but **not in the same way as futures or spot margin**. In options, leverage is **implicit and non‑linear**, driven by moneyness, time, and volatility, rather than by an explicit margin multiplier like “3×” or “10×”.

### How options give leverage

For the option buyer, leverage comes from:

* **Limited downside, unlimited upside relative to premium paid** If you buy a call, you risk only the premium, but your payoff can be many times that premium if the underlying moves strongly in your favor. From a percentage‑return perspective, that is high leverage, even though the clearing system did not lend you extra capital.
* **Non‑linear P\&L** The option’s payoff is convex: small changes in spot may give almost no P\&L near the strike, but a big move can create a large gain relative to the initial premium. That convexity is effectively leverage that appears only when the market moves in your direction.

For the **option seller**, the leverage is more dangerous:

* You collect a small premium but take on potentially large loss if the underlying moves against you.
* From a capital‑to‑risk perspective, the short is levered because your loss can be much larger than the premium you received, even though no margin vault explicitly multiplied your nominal exposure.

### How this differs from “margin leverage”

In futures or spot margin trading:

* Leverage is explicit: you borrow vs your collateral (e.g., 2×, 5×, 10× notional vs collateral).
* P\&L is roughly linear: for each 1% move you gain/lose \~`leverage × 1%` of collateral.

In options:

* There is no default, standardized “x leverage” label; leverage is **implied** by moneyness, time to expiry, and implied vol.
* The same contract can look almost unlevered if it is deep in/out of the money and short‑dated, but very levered if it is out‑of‑the‑money and long‑dated.

### Why people still say “options are leveraged”

In practice, people say “options are leveraged” to mean:

* **Capital efficiency**: you can gain exposure to a large notional move for a small initial outlay (the premium).
* **Disproportionate P\&L vs capital**: a small move in the right direction can generate a large percentage return on the premium, while a small move against can wipe it out.

So **yes, there is leverage in options**, but it is **embedded in the optionality itself**, not enforced by a margin‑engine‑style multiplier.

⁂

***

## how can you increase leverage in options?

You cannot increase leverage in options in the same direct way as in futures (e.g., by simply lowering margin), because options are **non‑linear, convex instruments** and their risk structure is fundamentally different. That said, you can *effectively* get higher leverage in a few ways, and each one shifts risk differently.

***

#### 1. Use deep‑OTM options (cheapest delta, highest leverage)

* Buy **deep‑out‑of‑the‑money** (far OTM) calls or puts.
* Their price is tiny compared to underlying notional, so a small move in spot can 10x+ the option price.
* Example: buying a 30% OTM call on spot worth 100 costs maybe 0.5; if spot jumps to 140, the option can easily be worth 5–10 → 10–20× return on option premium, even though the spot move was only 40%.

**Trade‑off**:

* Very low probability of payoff; most OTM options expire worthless.
* This is **convex long‑gamma speculation**, not “safe” leverage.

***

#### 2. Use longer‑dated options (more time, more convexity)

* For the same strike and moneyness, a **longer‑dated option** has higher vega and more time for the underlying to move into the money.
* That means for the same premium you can effectively “buy more optionality” and more convexity vs. only directional exposure.

**Trade‑off**:

* Time decay is slower but still present; you still pay theta.
* Just prolonging maturity does not remove the risk of being wrong on direction.

***

#### 3. Sell options to finance long options (riskier strategies)

If you want apparent “higher leverage” while staying in options, people often combine:

* **Sell OTM options** to receive premium and fund long‑gamma positions.
* Examples: butterflies, condors, or simple **risk reversals** (sell OTM put, buy OTM call, or vice versa), where net premium is small or zero.
* That gives you:
  * Very large PV impact from a big move,
  * but also **tail risk** on the side you sold.

This is not pure leverage; it is **skewed risk transfer**. You can lose catastrophically if the market moves against your short leg.

***

#### 4. Use options with high vega (volatility‑based leverage)

* Options on **high‑vol products** (or at times of low implied vol) can give you **volatility leverage**:
  * You pay relatively low premium for a lot of vol exposure.
  * If realized vol shocks up, your long‑vega position blows up in your favor.

You can amplify this by:

* Buying **back‑end or long‑dated options** (high vega),
* Or selling short‑dated options to fund them.

**Trade‑off**:

* If vol collapses (vol crush), you can lose quickly even if the underlying hasn’t moved much.

***

#### 5. Portfolio‑level options vs. delta‑hedge “futures‑like” position

Some traders “manufacture” leverage by:

* Buying options (calls or puts).
* **Delta‑hedging** them with underlying or futures.
* Result: you effectively turn the option into a **volatility‑only bet**, and the delta‑hedge removes much of the directional risk.

You can amplify this by:

* Running a **vol‑only book** where your delta is hedged, and your only exposure is gamma/vega.
* But the leverage comes from **vol convo**, not from magnified spot exposure.

This is closer to “options‑based leverage in volatility space,” not in price space.

***

#### 6. Why you cannot “just increase leverage” like in futures

In futures, leverage is explicitly controlled by:

* initial margin / notional,
* maintenance margin,
* and the exchange or protocol can change those parameters.

Options are different because:

* Their **P\&L is non‑linear**:
  * 10% move can destroy or 10× an option, depending on moneyness and tenor.
* Issuer (or pool) always bears **tail risk**, so:
  * If you naively “increase leverage” (e.g., accept undercollateralized positions), you either:
    * take counterparty risk, or
    * blow up the pool.

So protocols cannot safely allow mechanically higher leverage on options the way they can with futures.

***

#### 7. How exchanges/protocols enforce option leverage

In practice, option‑style products with leverage look like:

* **Portfolio‑margin systems**:
  * Net positions across strikes/tenors are evaluated together (margining via Greeks or stress scenarios).
* **Exercise‑only or physical‑settlement** for certain products, so:
  * You only get the “leverage boost” at expiry or exercise, not as a fully margined perpetual‑like option.
* **Short‑duration structures** that are more like **leveraged calls/puts** (e.g., weekly options):
  * High gamma, but only short‑lived so the system can liquidate quickly.

***

#### Summary in one line

You increase **effective leverage** in options by:

* buying **deep‑OTM options** or **high‑vega options**,
* or combining options into **asymmetric strategies** that pay off only on large moves,

but you cannot safely “increase leverage” in the futures‑style sense because the **non‑linearity and tail risk of options** means more leverage always means more chance of blow‑up, not just more directional exposure.

⁂

***

## what is out-of-money options?

An **out-of-the-money (OTM) option** is an option whose current strike price is unfavorable relative to the underlying’s price, so it would not be profitable to exercise it now if it were American‑style, or would expire worthless if held until expiry.

### Call option, OTM

* For a **call**, the strike must be **higher** than the current spot price.
* Example:
  * Underlying spot = 100.
  * Call with strike 110 → **OTM** (you wouldn’t pay 110 for something trading at 100 now).
* Intrinsic value = 0; the option’s value is purely **time value**.

### Put option, OTM

* For a **put**, the strike must be **lower** than the current spot price.
* Example:
  * Underlying spot = 100.
  * Put with strike 90 → **OTM** (you wouldn’t sell at 90 if the market is at 100).
* Again, intrinsic value = 0; only time value.

### In‑the‑money vs at‑the‑money

* **In‑the‑money (ITM)**: strike is better than spot (call with strike < spot, put with strike > spot).
* **At‑the‑money (ATM)**: strike is very close to spot.

OTM options are cheaper than ITM ones because they chance of ending up in‑the‑money, but they also decay faster and can go to zero if the underlying doesn’t move far enough before expiry.

⁂

***

## so i i bought option, can I sell it before expiration?

Yes — in most normal options markets (derivatives exchanges, crypto options, etc.) you **can** sell a bought option before expiration; you are not forced to hold it until expiry.

### How it works in practice

* When you **buy** an option (call or put), you pay a **premium** for the right to exercise it.
* Until expiration you can:
  * **Exercise it early** (for American‑style options), or
  * **Close the position by selling it back** to the market to another trader or market maker.

That sale is just an inverse transaction: “sell to close” your long option. Your P\&L from that trade is roughly:

$$
\text{P\&L} = \text{price you sold for} - \text{price you paid to buy it}
$$

If the option has become more valuable (e.g., the underlying moved favorably, volatility rose, or time decay is minor), you can sell it for a profit; if it has become less valuable, you may sell at a loss or even zero.

### What depends on style and venue

* **American‑style options**: can be exercised or sold at any time before expiry.
* **European‑style options**: usually cannot be exercised early, but you can still **sell the contract** before expiry; only the *right to exercise* is restricted, not your ability to trade the position.

On-chain or DEX-style options protocols generally follow the same logic: if the protocol supports an **order book or AMM** for that option, you can exit by selling; if it does not, you may be locked until expiry or until the protocol allows some form of peer‑to‑peer unwind or DAO‑driven mechanism.

So in short: **Yes, you can typically sell an option you bought before it expires**, as long as there is a market or mechanism for that option’s contract.

⁂

***

## so you can either sell it or exercise?

Yes — in standard options mechanics you usually have **two main ways to realize profit or loss** on a position:

1. **Sell it (close the position)**
   * You sell the option (or your option leg) on the market, locking in your P\&L at the current mark price.
   * This is typically cheaper and more flexible because you don’t trigger the full settlement mechanics; you just unwind your position before expiry.
   * In a CLOB or AMM setting, “selling it” means another trader buys your long from you, or you hedge by selling an offsetting short.
2. **Exercise it (if in‑the‑money)**
   * At or before expiry, the holder can **exercise** the right:
     * Call: buy the underlying at the strike.
     * Put: sell the underlying at the strike.
   * Exercise usually only makes sense when the option is in‑the‑money and the time value is small or zero.
   * In an onchain options protocol, exercise normally triggers a **collateral claim and settlement** against the writer’s margin pool.

### How this usually looks in a protocol

* If you **sold** the option (wrote it), your P\&L is:
  * you keep the premium if the option expires out‑of‑the‑money, or
  * you pay the intrinsic‑value loss if the holder exercises and you’re undercollateralized you get liquidated.
* If you **bought** the option, your P\&L is:
  * you can either **sell it back** earlier and realize gains/losses, or
  * **exercise or cash‑settle** at expiry if it’s ITM.

In liquidation‑driven contracts, you typically don’t wait for “pure” exercise; the system will close out positions when collateral falls below margin, even before expiry, using onchain Greeks or a risk model to decide how much to liquidate.

So in short: **you can choose to realize value by selling your option or by exercising it**, depending on the contract rules, your cashflow needs, and whether exercise is permitted or forced by liquidation logic.

⁂

***

## So if options are cash settled at expiration, then how are spot options different from futures options or perps options

Great question — and the answer is that once you strip away the delivery mechanism and go to cash settlement, the differences narrow down to **what the underlying reference price is** at expiry, and what risks you carry during the life of the contract.

### What they all have in common at expiry

All three settle to: `max(0, S_T - K)` for a call or `max(0, K - S_T)` for a put, where `S_T` is the **settlement price** at expiry. If they all reference the same index price at expiry, the final payoff is identical. The differences live in what feeds `S_T`, what you hold in between, and what collateral you need during the life of the position.

### Spot options

The underlying is the **spot price of the asset** (e.g., BTC/USD). Settlement at expiry computes payout from a spot index price — typically a TWAP over major CEX spot feeds. Between trade and expiry you carry **no funding or basis**. Your P\&L is pure option P\&L: delta, gamma, vega relative to spot, with no rolling cost. This is the cleanest model, closest to textbook Black-Scholes.

### Futures options

The underlying is a **futures contract**, not spot directly. Two key consequences:

1. **Settlement is against the futures price at expiry**, not spot. In theory at expiry futures converge to spot, but the path matters for margining and Greeks during the life of the option.
2. **You carry basis risk** — the futures price includes cost-of-carry, funding rates, and sometimes supply/demand distortions in the futures market itself. Your delta is against the futures price, so you hedge by trading futures, not spot.

In crypto specifically, perpetual funding makes the "futures curve" complex and can cause futures to trade well above or below spot for extended periods. An option on a futures has **delta against futures price**, which can diverge from spot delta meaningfully during the contract's life.

### Perps options

The most exotic of the three. The underlying is a **perpetual contract** (a funding-rate-settled instrument with no expiry itself). Key differences:

1. **No natural convergence to spot at a fixed date** — the "price" of the perp is anchored to spot via the funding mechanism but can drift intraday.
2. **Delta hedging requires holding a perp** with ongoing funding cash flows, not just buying/selling spot or a dated future. So your hedge bleeds (or earns) funding continuously.
3. **Funding risk bleeds into vega pricing** — high funding periods make the perp-spot basis volatile, which adds a funding-vol dimension that spot options don't have.
4. **No clean term structure** — dated futures options have a crisp forward curve. Perps have only one contract, so you cannot decompose a portfolio cleanly by tenor.

### Side-by-side summary

| Dimension                 | Spot option       | Futures option          | Perps option                 |
| ------------------------- | ----------------- | ----------------------- | ---------------------------- |
| Settlement reference      | Spot index        | Futures price at expiry | Perp mark price at expiry    |
| Basis risk during life    | None              | Futures/spot spread     | Perp/spot spread via funding |
| Delta hedge instrument    | Spot              | Dated futures           | Perpetual contract           |
| Funding cost during hedge | None              | Roll cost at expiry     | Continuous funding P\&L      |
| Term structure            | Per expiry, clean | Per expiry, clean       | Single contract              |
| Collateral model          | Spot vol only     | Forward vol + basis     | Spot vol + funding vol       |

### Why it matters for your design

For collateral and Greeks onchain, the differences are important:

* **Spot options**: Black-Scholes or a smile model against a spot oracle is sufficient. Greeks are clean.
* **Futures options**: You need a forward curve onchain (futures prices per tenor) and delta is against the forward, not spot. The margin model must mark to futures.
* **Perps options**: The trickiest — you need both a spot oracle and a perp mark price, plus a model for expected funding over the option's life. Delta hedging a perps option bleeds funding continuously, so your vega and theta models need to account for funding volatility as a separate risk dimension.

In practice, most onchain options protocols today use spot oracles for simplicity, even when the economic exposure looks more like a perps option. That mismatch is a real risk — the margin model assumes one reference price, but the effective replication cost is different.

⁂

***

## here are options on solana

<https://github.com/mithraiclabs/psyoptions/blob/master/programs/psy\\_american/src/lib.rs>

what can u say about implementation?

That repo implements an **American‑style options protocol on Solana**, built around a vault‑based design where each option contract is backed by collateralized vaults.

#### High‑level architecture

The core idea is:

* A **vault** holds the underlying asset (e.g., SOL) or quote asset (e.g., USDC) for a given option series (strike, expiry, direction).
* Users **deposit** into the vault to mint **option tokens** (mint with a specific decimal/precision) and **write** calls/puts into those vaults.
* Users **exercise** against the vault; the contract transfers the underlying from the vault to the exercisee in return for the strike payment.
* Expiry is handled explicitly: after the expiry slot, the protocol can “settle” or let the vaults be drained according to the rules.

This is very similar to other Solana options designs: **per‑strike‑and‑expiry vaults + onchain mints that represent 1 option, plus onchain accounting of who wrote versus who holds**.

#### Key components in the implementation

From the `psy_american` program and instruction set, you can see:

* **Instruction family**
  * `create_vault` / `init_vault`‑like instructions to set up a new option series.
  * `deposit` / `write` instructions to add collateral to the vault so it can issue more options.
  * `exercise` instructions so holders can trigger early exercise (since it’s American‑style).
  * `settle` / `close` instructions to handle expiry: either returning excess collateral or pulling out remaining underlying.
* **State accounts**
  * Vault account with:
    * underlying mint and quote mint,
    * strike price,
    * expiry slot/Unix timestamp,
    * collateral balance,
    * number of written contracts (or outstanding mints),
    * pointers to token accounts and oracles / oracles‑lite data.
  * Option token mints representing the call/put, with associated metadata about strike and expiry.
* **Risk model on Solana constraints**
  * There is no heavy onchain option‑pricer; the risk is implicitly **fully collateralized** by the vault design (full‑coverage of payoff).
  * Because of this, you don’t see a full onchain Black‑Scholes or stochastic‑vol model; the risk is held in the **value and size of the underlying locked in the vault**, not a dynamic Greek‑based formula.
  * Oracle use is minimal: mainly to double‑check expiry time and maybe sanity‑check spot vs strike at settlement, not to continuously reprice the option onchain.

#### What this means for market makers and UX

* **For makers**:
  * Writing is relatively simple: you deposit underlying into a vault and receive withdrawable option tokens or credit against your position.
  * The contract does not force you to maintain a Greek‑based margin; the **vault’s collateralization** is the main safety behind the payoff.
  * This is great for **slow‑to‑medium activity** and not for ultra‑high‑frequency Greek‑aware hedging onchain.
* **For takers / LPs**:
  * The vault guarantees that payoff is backed by onchain assets.
  * Liquidity is potentially fragmented across strikes and expiries, because each series is its own vault.
  * AMM or RFQ‑style liquidity usually sits **on top of** or **alongside** this vault layer (in separate programs or UIs), rather than inside the core `psy_american` program.

#### How it differs from full onchain “Greeks” designs

Relative to what we were talking about earlier, this design is:

* **Not** a perp‑style options engine with onchain PV/Greeks per account.
* **Not** a system where you run Black‑Scholes on every fill to rebalance margin.
* **Instead**:
  * A **structural collateralization model** (each vault is overcollateralized),
  * With settlement and exercise logic onchain,
  * And the actual **option‑pricing / Greek‑aware quoting** happening offchain in the front‑end and MM bots.

So if your goal is “Greeks onchain for collateral”, `psy_american` is **not** that; it’s closer to “**onchain vault‑backed American options with simple onchain settlement logic**.” The complexity is in the Solana account layout and instruction flow, not in a continuous onchain risk‑engine.

If you want, I can next sketch how you might *add* a compact onchain risk layer on top of a vault‑style base (for example, storing net delta/gamma per account keyed by vault series).

⁂

***

## what are RFQs?

RFQ stands for **Request for Quote**.

In trading and finance, an **RFQ** is a mechanism where one party (usually a buyer or seller) asks a set of counterparties for a price on a specific asset or trade, and then chooses the best quote instead of posting an order directly to a continuous order book.

### Key idea

* **User asks**: “Hey, I want to buy/sell X amount of Y at Z terms — what price will you give me?”
* **Market makers respond**: “I’ll do it at P1”, “I’ll do it at P2”.
* **User picks**: The best one and executes against that maker.

So instead of “I post a limit at P and wait for someone to hit me,” you get “I ask for quotes around my target and immediately see who’s best right now.”

### How RFQs usually work

A typical flow looks like:

1. Trader sends an RFQ with:
   * asset, side, notional/size,
   * settlement time (e.g., now vs spot vs forward),
   * constraints (min size, max latency, etc.).
2. Eligible market makers:
   * price the request using their own models,
   * return a **firm bid/offer** (sometimes for a narrow time window).
3. The RFQ handler:
   * collates responses,
   * may pick the best one or rank them,
   * allows the trader to execute against the winning quote.

In many models, offers are **firm but short‑lived** (10–500 ms), so the user must decide quickly or the quote expires.

### Where RFQs are common

* **OTC markets** (FX, rates, credit, some equities): You see the same thing in traditional sales desks — “give me a 5‑year IRS quote for 100M” and the desk comes back with prices.
* **Crypto derivatives and AMMs / intent‑based venues**: Some protocols collect intent from takers and then solicit RFQs from a pool of liquidity providers, then execute if the best quote is attractive enough.
* **CEXes with dark pools**: Large orders are often handled via RFQs to avoid moving the public book.

### RFQ vs CLOB

| Aspect                  | CLOB                             | RFQ                                                           |
| ----------------------- | -------------------------------- | ------------------------------------------------------------- |
| **Who sets the price?** | Anyone can post a resting order  | Makers respond to a specific request                          |
| **Visibility**          | Public, continuous book          | Quotes usually only visible to requester (or matching engine) |
| **Speed**               | Can be very fast but competitive | Often firm, tight, but latency‑sensitive                      |
| **Used for**            | Normal retail / scalable flow    | Large, sensitive or non‑standard trades                       |

Conceptually, an RFQ is like “I send an intent to trade, and you send me a prize‑bound quote you stand behind,” while a CLOB is “I dump an order into a visible book and wait for the market to react.”

### In your design

If you think about your matching‑engine setup, an RFQ‑style layer would sit nicely on top:

* Taker sends an intent: “I want to buy 10 ETH equivalents at market, with max slippage X%.”
* The engine:
  * transforms that into per‑level quantities,
  * sends internal RFQs (or CLOB‑style depth checks),
  * reorders best matches and then settles.

So “RFQs” are essentially an **intent‑based, quote‑gathering mechanism** for large or sensitive trades that avoids the limitations of pure CLOB or pure AMM UX.

⁂

***

[^1]: <https://threesigma.xyz/blog/options/defi-options-landscape-guide>

[^2]: <https://www.schwab.com/learn/story/trying-out-futures-options-here-are-key-differences-vs-equities>

[^3]: <https://blog.synthetix.io/lyra-finance-the-leading-onchain-options-protocol/>

[^4]: <https://blog.chain.link/defi-call-option-exchange-in-solidity/>

[^5]: <https://mixbytes.io/blog/deep-dive-into-defi-derivatives>

[^6]: <https://arxiv.org/html/2508.07068>

[^7]: <https://github.com/tradeparadex/paradex-docs/blob/main/fern/pages/options/differences-perps-dated-options.mdx?plain=1>

[^8]: <https://github.com/0xperp/defi-derivatives>

[^9]: <https://panoptic.xyz/docs/trading/perpetual-options>

[^10]: <https://www.nerdwallet.com/investing/learn/how-to-trade-options>

[^11]: <https://www.investopedia.com/options-basics-tutorial-4583012>

[^12]: <https://www.ally.com/stories/invest/trading-options-for-beginners/>

[^13]: <https://www.ishares.com/us/investor-education/investment-strategies/introduction-to-options>

[^14]: <https://www.sofi.com/learn/content/options-trading-for-beginners/>

[^15]: <https://www.home.saxo/content/articles/options/from-zero-to-hero---selling-options-12092023>

[^16]: <https://www.selloptions.net/learn>

[^17]: <https://www.home.saxo/en-sg/content/articles/options/from-zero-to-hero---selling-options-12092023>

[^18]: <https://www.nadcab.com/blog/oracles-smart-contracts-in-defi>

[^19]: <https://www.ijraset.com/best-journal/real-dex-on-chain-orderbook-dex>

[^20]: <https://www.bankrate.com/investing/strike-price-of-an-option/>

[^21]: <https://www.chainscorelabs.com/de/blog/future-of-dexs-amms-orderbooks-and-aggregators/orderbook-dex-scalability/the-crippling-cost-of-consensus-for-every-order-update>

[^22]: <https://x.com/marvellousdefi\\_/status/1938344955044565294>

[^23]: <https://blog.monad.xyz/blog/understanding-lobster>

[^24]: <https://www.chaincatcher.com/en/article/2075964>

[^25]: <https://chain.link/article/onchain-vs-offchain-transactions>

[^26]: <https://arxiv.org/html/2512.23618v1>

[^27]: <https://smeiklej.com/files/ccs16.pdf>

[^28]: <https://www.cube.exchange/what-is/merkle-tree>

[^29]: <https://orochi.network/blog/on-chain-vs-off-chain-transactions>

[^30]: <https://hackmd.io/@FranckC/S17\\_7RoO6>

[^31]: <https://help.dydx.trade/en/articles/166981-perpetual-order-types-on-dydx-chain>

[^32]: <https://hummingbot.org/strategies/v1-strategies/pure-market-making/>

[^33]: <https://docs.aori.io/docs/orderbook>
