Skip to content

Instantly share code, notes, and snippets.

@MdSadiqMd
Created March 31, 2026 07:11
Show Gist options
  • Select an option

  • Save MdSadiqMd/820c5b4aef4d7b0b59bbfae126e2b307 to your computer and use it in GitHub Desktop.

Select an option

Save MdSadiqMd/820c5b4aef4d7b0b59bbfae126e2b307 to your computer and use it in GitHub Desktop.

Incognitus — User Flow Sequence Diagrams

Every user-facing flow in the system, traced end-to-end with full detail. Covers onboarding, deposits, limit orders, market orders, matching, settlement, cancellation, withdrawal, and the crank lifecycle. Each diagram shows every account touched, every validation performed, and every state change made.


Table of Contents

  1. Onboarding — New Trader Setup
  2. Deposit Tokens
  3. Place a Limit Order (Full Flow)
  4. Place a Market Order (Full Flow)
  5. Limit Order Through the Pipeline
  6. Market Order Through the Pipeline
  7. The Matching Process — Deep Dive
  8. Settlement — Updating Balances
  9. Cleanup — Freeing Consumed Nodes
  10. Cancel a Limit Order
  11. Withdraw Tokens
  12. Crank Lifecycle — Decision Tree
  13. Full Trade: Limit Sell + Market Buy
  14. Partial Fill Continuation
  15. Concurrent Pipeline — Multi-Batch View

1. Onboarding — New Trader Setup

Before a trader can place any order, they need an AccountStatus for the specific market. One-time setup per market.

sequenceDiagram
    actor Trader
    participant Wallet as Wallet Adapter
    participant Frontend as Frontend UI
    participant WASM as WASM Client
    participant RPC as Solana RPC
    participant Program as Solana Program
    participant MC as MarketConfig
    participant AccStatus as AccountStatus

    Trader->>Frontend: Opens trading page for SOL/USDC
    Frontend->>WASM: Check if AccountStatus exists
    WASM->>RPC: getAccountInfo(PDA derived from trader + market)
    RPC-->>WASM: Account not found

    Note over Frontend: First time trading this market

    Frontend->>Trader: Prompt to initialize account
    Trader->>Wallet: Approve transaction
    Wallet->>WASM: Signed transaction

    WASM->>WASM: Build initialize_account_status instruction
    Note over WASM: PDA seeds: [program_id, trader_pubkey, market_config_pubkey]

    WASM->>RPC: Submit transaction
    RPC->>Program: initialize_account_status

    Program->>Program: Validate Owner.is_signer == true
    Program->>MC: Validate MarketConfig exists and is valid
    Program->>Program: Derive PDA for AccountStatus
    Program->>AccStatus: Create account (rent-exempt)
    Program->>AccStatus: Set owner = Trader pubkey
    Program->>AccStatus: Set market_config_account = MarketConfig
    Program->>AccStatus: Set quantity_amount = 0
    Program->>AccStatus: Set quote_amount = 0

    Program-->>RPC: Success
    RPC-->>WASM: Confirmed
    WASM-->>Frontend: Account initialized
    Frontend-->>Trader: Account ready, deposit tokens to start trading
Loading

2. Deposit Tokens

Trader deposits base tokens (SOL) or quote tokens (USDC) into their AccountStatus.

sequenceDiagram
    actor Trader
    participant Wallet
    participant WASM
    participant RPC
    participant Program
    participant SPL as SPL Token Program
    participant TraderATA as Trader Token Account
    participant Vault as Market Vault
    participant AccStatus as AccountStatus

    Trader->>WASM: Deposit 500 USDC
    WASM->>WASM: Determine token type: quote = USDC
    WASM->>WASM: amount = 500_000_000 (raw lamports)
    WASM->>WASM: Build deposit instruction

    Trader->>Wallet: Approve transaction
    Wallet->>WASM: Signed

    WASM->>RPC: Submit transaction
    RPC->>Program: deposit instruction

    Program->>Program: Validate Owner.is_signer == true
    Program->>Program: Validate AccStatus.owner == Owner
    Program->>Program: Validate AccStatus.market_config == MarketConfig
    Program->>Program: Validate TraderATA balance >= 500_000_000

    Program->>SPL: Transfer 500_000_000 from TraderATA to Vault
    SPL->>TraderATA: Debit 500_000_000
    SPL->>Vault: Credit 500_000_000

    Program->>AccStatus: quote_amount += 500_000_000

    Program-->>RPC: Success
    RPC-->>WASM: Confirmed
    WASM-->>Trader: Balance is now 500 USDC
Loading

3. Place a Limit Order (Full Flow)

Stage 1 of the pipeline. User-signed. Every validation check and every account write.

sequenceDiagram
    actor Trader
    participant WASM as WASM Client
    participant RPC as Solana RPC
    participant Program as Solana Program
    participant MC as MarketConfig
    participant AccStatus as AccountStatus
    participant PQ as PriceQueue
    participant PT as PriceTrie
    participant EQ as EntriesQueue
    participant AIQ as AddressIndexQueue
    participant CQ as CoordinatesQueue

    Note over Trader,CQ: Client-Side Pre-Computation
    Trader->>WASM: Sell 100 SOL at $150
    WASM->>WASM: side = ask
    WASM->>WASM: price = 150_000_000 (raw)
    WASM->>WASM: quantity = 100_000_000_000 (raw)
    WASM->>WASM: quote = price * quantity = 15_000_000_000_000
    WASM->>WASM: Validate quote % price == 0
    WASM->>WASM: Validate quote % quantity == 0
    WASM->>WASM: Compute sliding window slot accounts [n, n+1, n+2, n+3]
    WASM->>WASM: Build limit_order_queue instruction

    Note over Trader,CQ: Transaction Submission
    Trader->>WASM: Sign transaction
    WASM->>RPC: Submit tx with 4 slot-window accounts

    Note over Trader,CQ: On-Chain Validation (Stage 1, slot n)
    RPC->>Program: limit_order_queue instruction

    Program->>MC: Read and validate market exists
    Program->>AccStatus: Read and validate balance
    Program->>Program: Validate quote % price == 0
    Program->>Program: Validate quote % quantity == 0
    Program->>Program: Validate ask: quantity <= AccStatus.quantity_amount
    Program->>Program: Validate AccStatus.market_config == MarketConfig
    Program->>Program: Validate LOQ.market_config_account == MarketConfig
    Program->>Program: Validate AccStatus.owner == Owner
    Program->>Program: Validate Owner.is_signer == true

    Note over Trader,CQ: On-Chain Processing
    Program->>Program: Store coordinates pointer in local var
    Program->>PT: Traverse PriceTrie for price 150
    Program->>PT: Create TrieNode(digit=1, depth=2) if needed
    Program->>PT: Create TrieNode(digit=5, depth=1) if needed
    Program->>PT: Push each TrieNodePointer onto path stack

    Program->>PQ: Find or create PriceNode for price=150
    Program->>PQ: Validate price matches
    Program->>Program: Push PriceNodePointer onto stack

    Program->>EQ: Insert OrderEntry (qty=100B, quote=15T, addr_ptr, status_ptr)
    Program->>EQ: Set address_index_pointer on entry
    Program->>Program: Store OrderEntry pointer in local var

    Program->>Program: Pop PriceNodePointer from stack
    Program->>EQ: Add p_pointer to OrderEntry
    Program->>PQ: Add quantity + quote to PriceNode deltas
    Program->>Program: Pop each TrieNodePointer from stack
    Program->>PT: Add quantity + quote to each TrieNode delta

    Program->>AIQ: Write address index coordinate
    Program->>CQ: Write trie path coordinates

    Note over Trader,CQ: State Changes Written
    Program-->>RPC: Success
    RPC-->>WASM: Confirmed at slot n
    WASM-->>Trader: Limit sell order placed, pending pipeline
Loading

4. Place a Market Order (Full Flow)

Stage 2 of the pipeline. User-signed. Concurrent with Stage 1.

sequenceDiagram
    actor Trader
    participant WASM as WASM Client
    participant RPC as Solana RPC
    participant Program as Solana Program
    participant MC as MarketConfig
    participant AccStatus as AccountStatus
    participant MOQ as MarketOrderQueue
    participant MOPQ as MarketOrderPriceQueue
    participant AIC as AddressIndexCache

    Note over Trader,AIC: Client-Side
    Trader->>WASM: Buy 100 SOL at market
    WASM->>WASM: side = buy
    WASM->>WASM: target_price = 0 (no limit)
    WASM->>WASM: target_amount = 100_000_000_000 (raw)
    WASM->>WASM: Build event: flag(buy+quantity), price(0), amount(100B)
    WASM->>WASM: Compute sliding window accounts
    WASM->>WASM: Build market_order_queue instruction

    Trader->>WASM: Sign transaction
    WASM->>RPC: Submit tx

    Note over Trader,AIC: On-Chain Validation (Stage 2, slot n)
    RPC->>Program: market_order_queue instruction

    Program->>MC: Read and validate market
    Program->>AccStatus: Read and validate balance
    Program->>Program: Validate buy: amount <= AccStatus.quote_amount
    Program->>Program: Validate AccStatus.market_config == MarketConfig
    Program->>Program: Validate AccStatus.owner == Owner
    Program->>Program: Validate Owner.is_signer == true
    Program->>Program: If price target set: validate price is non-zero rational

    Note over Trader,AIC: On-Chain Processing
    Program->>MOQ: Write market order event (17 bytes)
    Note over MOQ: flag=buy+qty, price=0, amount=100B
    Program->>MOPQ: Write price target entry (none here)
    Program->>AIC: Write address index coordinate to cache

    Program-->>RPC: Success
    RPC-->>WASM: Confirmed at slot n
    WASM-->>Trader: Market buy submitted, pending matching
Loading

5. Limit Order Through the Pipeline

After the user places a limit order (Stage 1), the crank advances it through Stages 3 and 4 into the live order book.

sequenceDiagram
    participant Crank
    participant RPC as Solana RPC
    participant Program as Solana Program
    participant LOQ_Ask as LimitOrderQueue (ask)
    participant LOQ_Bid as LimitOrderQueue (bid)
    participant Agg as LimitOrderAggregation
    participant MC as MarketConfig
    participant OBLog as OrderBookChangeLog
    participant TrieSlab as TrieNode Slab (ask)
    participant PriceSlab as PriceNode Slab (ask)
    participant BlockSlab as OrderBlock Slab (ask)

    Note over Crank,BlockSlab: Stage 3: Aggregation (slot n+1)
    Crank->>Crank: Decision tree: LOQ has data, write-lock OFF
    Crank->>RPC: Submit limit_order_aggregation tx

    RPC->>Program: limit_order_aggregation
    Program->>LOQ_Ask: Read and consume prior slot ask queue
    Program->>LOQ_Bid: Read and consume prior slot bid queue
    Program->>Program: Group entries by price
    Program->>Program: Sort by price for efficient insertion
    Program->>Agg: Write aggregated output
    Program-->>RPC: Success

    Note over Crank,BlockSlab: Stage 4: Order Book Update (slot n+2)
    Crank->>Crank: Decision tree: Aggregation complete
    Crank->>RPC: Submit order_book_update tx

    RPC->>Program: order_book_update (action=create)
    Program->>MC: Write: SET WRITE-LOCK ON
    Program->>Agg: Read and consume aggregated orders

    loop For each price group in aggregation
        Program->>TrieSlab: Insert or update TrieNode path
        Program->>TrieSlab: Update delta_quantity + delta_quote on each node
        Program->>PriceSlab: Insert or update PriceNode
        Program->>PriceSlab: Set order_block_pointer and next_entry_offset
        Program->>BlockSlab: Insert OrderBlock if needed
        Program->>BlockSlab: Write OrderEntry at next_entry_offset
        Program->>BlockSlab: Update block delta_quantity + delta_quote
        Program->>PriceSlab: Advance next_entry_offset
        Program->>PriceSlab: Increment num_order_blocks_produced if new block
    end

    Program->>OBLog: Record all changes for pre-compute stage

    Note over Crank,BlockSlab: Ledger Insert (part of OB Update or Settlement S1)
    Note over Crank,BlockSlab: For each new order entry inserted:
    Note over Crank,BlockSlab: - Create OrderEntryStatusNode (status=open, price, slot_open)
    Note over Crank,BlockSlab: - Find or create AddressIndexNode for trader
    Note over Crank,BlockSlab: - Increment num_open_entries
    Note over Crank,BlockSlab: - Link into trader's order chain (ask or bid)

    Program-->>RPC: Success

    Note over Crank,BlockSlab: Order is now LIVE in the order book
Loading

6. Market Order Through the Pipeline

After the user places a market order (Stage 2), the crank advances it through Stages 5 and 6.

sequenceDiagram
    participant Crank
    participant RPC
    participant Program
    participant MOQ as MarketOrderQueue
    participant Cache as MarketOrderCache
    participant OBLog as OrderBookChangeLog
    participant PriceSlab as PriceNode Slab
    participant BlockSlab as OrderBlock Slab
    participant ME as Matching Engine
    participant TrieSlab as TrieNode Slab
    participant SQ as SettlementQueue

    Note over Crank,SQ: Stage 5: Pre-Compute and Cache (slot n+3)
    Crank->>Crank: Decision tree: OB updated, market orders pending
    Crank->>RPC: Submit precompute_market_orders tx

    RPC->>Program: precompute_market_orders
    Program->>MOQ: Read and consume market orders
    Program->>OBLog: Read latest order book state
    Program->>PriceSlab: Read to determine which price levels exist
    Program->>BlockSlab: Read to check order availability

    loop For each market order
        Program->>Program: If buy then scan ask side
        Program->>Program: If sell then scan bid side
        Program->>Program: Identify hot accounts needed for matching
        Program->>Cache: Write pre-computed account list
    end

    Program-->>RPC: Success

    Note over Crank,SQ: Stage 6: Match Orders (slot n+4)
    Crank->>Crank: Decision tree: Cache ready
    Crank->>RPC: Submit match_market_orders tx

    RPC->>Program: match_market_orders
    Program->>Cache: Load pre-computed account list
    Program->>Program: Load slab byte slices from accounts

    Program->>ME: Pass SlabSet + market orders
    Note over ME: Pure Rust library, no Solana knowledge

    loop For each market order or compatible batch
        ME->>ME: Check batching: same type, same dimension, no price target
        ME->>TrieSlab: Traverse trie (ask: 0 to 9, bid: 9 to 0)
        ME->>ME: At each node check delta_qty >= remaining
        ME->>ME: Descend to best price PriceNode
        ME->>BlockSlab: Read OrderBlock at next_match_offset
        ME->>ME: Consume OrderEntry in FIFO order
        ME->>ME: Full fill: mark consumed, next entry
        ME->>ME: Partial fill: reduce amounts, stop
        ME->>BlockSlab: Update block delta_quantity -= filled
        ME->>BlockSlab: Update block delta_quote -= filled
        ME->>PriceSlab: Update PriceNode deltas
        ME->>TrieSlab: Propagate deltas up path stack to root
        ME->>ME: If price level exhausted then flag is_active=0
        ME->>ME: Check CU budget: remaining less than safety margin?
        ME->>ME: Produce FillRecord per consumed entry
    end

    ME-->>Program: MatchResult + FillRecords
    Program->>SQ: Write fill records to SettlementQueue
    Program-->>RPC: Success
Loading

7. The Matching Process — Deep Dive

Zooming into what happens inside the matching engine during Stage 6. Trie traversal, entry consumption, and delta propagation at the data structure level.

sequenceDiagram
    participant ME as Matching Engine
    participant Trie as TrieNode Slab
    participant TLN as TrieLinkNode Slab
    participant Price as PriceNode Slab
    participant Block as OrderBlock Slab
    participant Stack as Path Stack
    participant Fills as Fill Records

    Note over ME,Fills: Market Buy 100 SOL: traverse ASK side (0 to 9)

    ME->>Trie: Read root TrieNode
    ME->>ME: root.delta_qty=500 >= remaining=100 PASS
    ME->>Stack: Push root address

    ME->>ME: Read root.trie_link.flags
    ME->>ME: bit 11 set: TrieLinkNodePointer
    ME->>TLN: Read TrieLinkNode at pointer
    ME->>ME: Traverse children in order 0 to 9

    ME->>Trie: Read child TrieNode(digit=1, depth=2)
    ME->>ME: child.delta_qty=300 >= remaining=100 PASS
    ME->>Stack: Push child address

    ME->>ME: Read child.trie_link.flags
    ME->>ME: bit 13 set: PriceNodePointer (leaf)
    ME->>Price: Read PriceNode(price=150)

    Note over ME,Fills: Arrived at best ask price: consume entries

    ME->>Price: Read next_match_offset = 3
    ME->>ME: Read order_block_pointer
    ME->>ME: Check pointer type: single OrderBlock
    ME->>Block: Read OrderBlock at pointer

    ME->>Block: Read entry[3]: qty=40, quote=6000
    ME->>ME: remaining=100, entry_qty=40: FULL FILL
    ME->>ME: remaining = 100 - 40 = 60
    ME->>Block: Mark entry[3] consumed
    ME->>Block: delta_qty -= 40, delta_quote -= 6000
    ME->>Fills: Write FillRecord(coord, qty=40, quote=6000, price=150, ask)

    ME->>Block: Read entry[4]: qty=60, quote=9000
    ME->>ME: remaining=60, entry_qty=60: FULL FILL
    ME->>ME: remaining = 60 - 60 = 0
    ME->>Block: Mark entry[4] consumed
    ME->>Block: delta_qty -= 60, delta_quote -= 9000
    ME->>Fills: Write FillRecord(coord, qty=60, quote=9000, price=150, ask)

    ME->>Price: Advance next_match_offset: 3 to 5

    Note over ME,Fills: Delta Propagation: bottom to top

    ME->>Price: delta_qty -= 100, delta_quote -= 15000
    ME->>Stack: Pop leaf TrieNode address
    ME->>Trie: leaf.delta_qty -= 100, leaf.delta_quote -= 15000
    ME->>Stack: Pop root address
    ME->>Trie: root.delta_qty -= 100, root.delta_quote -= 15000

    Note over ME,Fills: Order fully filled
    ME->>ME: Return MatchResult: remaining=0, stop=FullyFilled, fills=2
Loading

8. Settlement — Updating Balances

Stage 8 (slot n+5). Runs concurrently with Cleanup. Writes only to Ledger and AccountStatus accounts.

sequenceDiagram
    participant Crank
    participant Program
    participant SQ as SettlementQueue
    participant AIN as AddressIndexNode Slab
    participant OESN as OrderEntryStatusNode Slab
    participant OECLN as ChangeLogNode Slab
    participant BuyerAcct as Buyer AccountStatus
    participant SellerAcct as Seller AccountStatus

    Crank->>Program: Submit settlement tx

    Program->>SQ: Read fill records

    Note over Program,SellerAcct: Process Fill 1: Seller entry (40 SOL at $150)

    Program->>Program: Read FillRecord coord=(addr_ptr, status_ptr)
    Program->>AIN: Resolve addr_ptr to AddressIndexNode
    Note over AIN: owner = Seller pubkey
    Program->>OESN: Resolve status_ptr to OrderEntryStatusNode
    Program->>OESN: Update slot_update = current_slot
    Program->>OESN: Update flags.status = partial (still has qty left)
    Program->>OECLN: Create OrderEntryChangeLogNode
    Note over OECLN: type=partial_fill, qty_delta=-40, quote_delta=-6000
    Program->>SellerAcct: quote_amount += 6000 (received USDC)
    Program->>SellerAcct: quantity_amount -= 40 (sent SOL)

    Note over Program,SellerAcct: Process Fill 2: Seller entry (60 SOL at $150)

    Program->>OESN: Resolve status_ptr to OrderEntryStatusNode
    Program->>OESN: Update flags.status = closed (fully filled)
    Program->>OECLN: Create OrderEntryChangeLogNode
    Note over OECLN: type=full_fill, qty_delta=-60, quote_delta=-9000
    Program->>SellerAcct: quote_amount += 9000
    Program->>SellerAcct: quantity_amount -= 60
    Program->>AIN: num_open_entries -= 1

    Note over Program,SellerAcct: Credit the Buyer

    Program->>BuyerAcct: quantity_amount += 100 (received SOL)
    Program->>BuyerAcct: quote_amount -= 15000 (paid USDC)

    Program->>SQ: Mark fill records consumed
    Program-->>Crank: Success
Loading

9. Cleanup — Freeing Consumed Nodes

Stage 7 (slot n+6). Runs concurrently with Settlement. Writes only to Order Book slab accounts.

sequenceDiagram
    participant Crank
    participant Program
    participant SQ as SettlementQueue
    participant BlockSlab as OrderBlock Slab
    participant PriceSlab as PriceNode Slab
    participant TrieSlab as TrieNode Slab
    participant LinkSlab as TrieLinkNode Slab
    participant MC as MarketConfig

    Crank->>Program: Submit cleanup tx

    Program->>SQ: Read matched and cancelled entries

    Note over Program,MC: Fast Cleanup: empty nodes

    loop For each consumed OrderEntry
        Program->>BlockSlab: Check if OrderBlock fully consumed
        alt All 16 entries consumed
            Program->>BlockSlab: slab.delete(block_addr) push addr to stack
            Program->>PriceSlab: Update PriceNode
            Program->>PriceSlab: num_order_blocks_consumed += 1
            Program->>PriceSlab: Advance to next block if match cursor was here
        else Partially consumed
            Program->>Program: Skip, block still has live entries
        end
    end

    loop For each empty PriceNode (delta_qty == 0)
        Program->>PriceSlab: slab.delete(price_addr)
        Program->>TrieSlab: Read parent TrieNode
        Program->>TrieSlab: Update trie_link: remove child pointer
        Program->>TrieSlab: Update trie_link.flags: clear digit bit
        Program->>TrieSlab: Decrement trie_link.size

        alt TrieNode has 0 children left
            Program->>TrieSlab: Set is_active = 0 (bit 14)
            Program->>TrieSlab: slab.delete(trie_addr)
            Note over TrieSlab: All children implicitly inactive
        else TrieNode still has children
            Program->>TrieSlab: Update delta_qty and delta_quote
        end
    end

    loop For each orphaned TrieLinkNode
        Program->>LinkSlab: slab.delete(link_addr)
    end

    Note over Program,MC: Release Write-Lock
    Program->>MC: Write: SET WRITE-LOCK OFF
    Program->>SQ: Mark entries processed

    Program-->>Crank: Success
    Note over Crank: Pipeline batch complete
Loading

10. Cancel a Limit Order

Cancellation enters through Stage 1 with a cancel flag. Race conditions with fills are an open question (Q-001).

sequenceDiagram
    actor Trader
    participant WASM
    participant RPC
    participant Program
    participant MC as MarketConfig
    participant AccStatus as AccountStatus
    participant LOQ as LimitOrderQueue
    participant Agg as Aggregation
    participant TrieSlab as TrieNode Slab
    participant PriceSlab as PriceNode Slab
    participant BlockSlab as OrderBlock Slab
    participant SQ as SettlementQueue
    participant AIN as AddressIndexNode Slab
    participant OESN as OrderEntryStatusNode Slab

    Note over Trader,OESN: Stage 1: Cancel Request (slot n)

    Trader->>WASM: Cancel order XYZ
    WASM->>WASM: Build limit_order_queue instruction with cancel flag
    WASM->>WASM: Set cancel flag + order_entry_id
    Trader->>WASM: Sign
    WASM->>RPC: Submit tx

    RPC->>Program: limit_order_queue (cancel)
    Program->>MC: Read and validate market
    Program->>AccStatus: Read and validate ownership
    Program->>Program: Validate Owner.is_signer
    Program->>Program: Validate AccStatus.owner == Owner
    Program->>LOQ: Write cancel event with order_entry_id
    Program-->>RPC: Success

    Note over Trader,OESN: Stage 3: Aggregation picks up cancel (slot n+1)

    Program->>LOQ: Read cancel event from prior slot
    Program->>Agg: Write cancel into aggregated output

    Note over Trader,OESN: Stage 4: OB Update processes cancel (slot n+2)

    Program->>BlockSlab: Locate OrderEntry by ID
    Program->>BlockSlab: Zero the entry (tombstone)
    Program->>BlockSlab: Update OrderBlock deltas
    Program->>PriceSlab: Update PriceNode deltas
    Program->>TrieSlab: Propagate delta changes up trie path
    Program->>SQ: Write cancel event to SettlementQueue

    Note over Trader,OESN: Stage 8: Settlement processes cancel (slot n+5)

    Program->>AIN: Resolve coordinate to AddressIndexNode
    Program->>OESN: Update OrderEntryStatusNode: status = closed
    Program->>OESN: Create ChangeLogNode (type=cancel)
    Program->>AccStatus: Return locked funds to AccountStatus
    Program->>AIN: num_open_entries -= 1

    WASM-->>Trader: Order cancelled, funds returned
Loading

11. Withdraw Tokens

After settlement, the trader withdraws tokens back to their wallet.

sequenceDiagram
    actor Trader
    participant WASM
    participant RPC
    participant Program
    participant AccStatus as AccountStatus
    participant SPL as SPL Token Program
    participant Vault as Market Vault
    participant TraderATA as Trader Token Account

    Trader->>WASM: Withdraw 15000 USDC
    WASM->>WASM: amount = 15_000_000_000_000 (raw)
    Trader->>WASM: Sign
    WASM->>RPC: Submit withdraw tx

    RPC->>Program: withdraw instruction
    Program->>Program: Validate Owner.is_signer
    Program->>Program: Validate AccStatus.owner == Owner
    Program->>Program: Validate AccStatus.quote_amount >= amount
    Program->>Program: Validate no open orders using these funds

    Program->>AccStatus: quote_amount -= 15_000_000_000_000
    Program->>SPL: Transfer from Vault to TraderATA
    SPL->>Vault: Debit 15_000_000_000_000
    SPL->>TraderATA: Credit 15_000_000_000_000

    Program-->>RPC: Success
    RPC-->>WASM: Confirmed
    WASM-->>Trader: 15000 USDC withdrawn to wallet
Loading

12. Crank Lifecycle — Decision Tree

The crank is a continuous loop monitoring on-chain state and submitting the right transaction at the right time.

sequenceDiagram
    participant Crank as Crank (WASM Client)
    participant RPC as Solana RPC
    participant MC as MarketConfig
    participant LOQ as LimitOrderQueue
    participant MOQ as MarketOrderQueue
    participant Program as Solana Program

    loop Every 400ms (each slot)
        Crank->>RPC: getAccountInfo(MarketConfig)
        RPC-->>Crank: MarketConfig state

        Crank->>Crank: Read write-lock status

        alt Write-lock is ON
            Crank->>Crank: Skip: OB is being written to
            Note over Crank: Wait for cleanup to release lock
        else Write-lock is OFF
            Crank->>RPC: getAccountInfo(LimitOrderQueue)
            RPC-->>Crank: LOQ state

            alt LOQ has pending orders from prior slot
                Crank->>RPC: Submit limit_order_aggregation tx
                RPC->>Program: Stage 3 Aggregation
                Program-->>RPC: Success

                Crank->>RPC: Submit order_book_update tx
                RPC->>Program: Stage 4 OB Update (sets write-lock)
                Program-->>RPC: Success
            end

            Crank->>RPC: getAccountInfo(MarketOrderQueue)
            RPC-->>Crank: MOQ state

            alt MOQ has pending orders
                Crank->>RPC: Submit precompute_market_orders tx
                RPC->>Program: Stage 5 Pre-Compute
                Program-->>RPC: Success

                Crank->>RPC: Submit match_market_orders tx
                RPC->>Program: Stage 6 Match
                Program-->>RPC: Success

                par Settlement and Cleanup
                    Crank->>RPC: Submit settlement tx
                    RPC->>Program: Stage 8 Settlement
                    Program-->>RPC: Success
                and
                    Crank->>RPC: Submit cleanup tx
                    RPC->>Program: Stage 7 Cleanup (releases write-lock)
                    Program-->>RPC: Success
                end
            end
        end
    end
Loading

13. Full Trade: Limit Sell + Market Buy

Complete end-to-end. Alice sells 100 SOL at $150. Bob buys 100 SOL at market. Every account, every slot, every state change.

sequenceDiagram
    actor Alice
    actor Bob
    participant AW as Alice WASM
    participant BW as Bob WASM
    participant RPC
    participant Program
    participant MC as MarketConfig
    participant AliceAcct as Alice AccStatus
    participant BobAcct as Bob AccStatus
    participant LOQ as LimitOrderQueue
    participant MOQ as MarketOrderQueue
    participant Agg as Aggregation
    participant TrieSlab as TrieNode Slab
    participant PriceSlab as PriceNode Slab
    participant BlockSlab as OrderBlock Slab
    participant Cache as MarketOrderCache
    participant ME as Matching Engine
    participant SQ as SettlementQueue
    participant AIN as AddressIndex Slab
    participant OESN as OrderStatus Slab
    participant Crank

    Note over Alice,Crank: SLOT N: Order Placement

    Alice->>AW: Sell 100 SOL at $150
    AW->>AW: Pre-compute quote = 150 * 100 = 15000
    AW->>AW: Validate 15000 % 150 == 0
    AW->>AW: Validate 15000 % 100 == 0
    AW->>RPC: Submit limit_order_queue tx
    RPC->>Program: limit_order_queue (ask, 150, 100, 15000)
    Program->>MC: Read, valid
    Program->>AliceAcct: Read, qty_amount >= 100
    Program->>LOQ: Write order to ask queue
    Program-->>AW: Success

    Bob->>BW: Buy 100 SOL at market
    BW->>RPC: Submit market_order_queue tx
    RPC->>Program: market_order_queue (buy, no_limit, 100)
    Program->>MC: Read, valid
    Program->>BobAcct: Read, quote_amount >= needed
    Program->>MOQ: Write market order
    Program-->>BW: Success

    Note over Alice,Crank: SLOT N+1: Aggregation

    Crank->>RPC: Submit limit_order_aggregation tx
    RPC->>Program: limit_order_aggregation
    Program->>LOQ: Read and consume ask queue from slot N
    Program->>Agg: Write aggregated output (1 order at price 150)
    Program-->>Crank: Success

    Note over Alice,Crank: SLOT N+2: Order Book Update

    Crank->>RPC: Submit order_book_update tx
    RPC->>Program: order_book_update (create)
    Program->>MC: WRITE-LOCK ON
    Program->>Agg: Read aggregated orders
    Program->>TrieSlab: Insert TrieNode(1, depth=2)
    Program->>TrieSlab: Insert TrieNode(5, depth=1)
    Program->>TrieSlab: Set deltas qty=100, quote=15000
    Program->>PriceSlab: Insert PriceNode(price=150)
    Program->>PriceSlab: Set next_entry_offset=0, num_blocks_produced=1
    Program->>BlockSlab: Insert OrderBlock
    Program->>BlockSlab: Write entry[0] qty=100, quote=15000, coords
    Program->>BlockSlab: Set block deltas qty=100, quote=15000

    Note over Alice,Crank: Ledger: create OrderEntryStatusNode for Alice (status=open)
    Note over Alice,Crank: Ledger: find/create AddressIndexNode, num_open_entries += 1

    Program-->>Crank: Success

    Note over Alice,Crank: SLOT N+3: Pre-Compute

    Crank->>RPC: Submit precompute_market_orders tx
    RPC->>Program: precompute_market_orders
    Program->>MOQ: Read Bob market buy
    Program->>PriceSlab: Read, ask side has price 150
    Program->>BlockSlab: Read, block has entries
    Program->>Cache: Write account list for matching
    Program-->>Crank: Success

    Note over Alice,Crank: SLOT N+4: Matching

    Crank->>RPC: Submit match_market_orders tx
    RPC->>Program: match_market_orders
    Program->>Cache: Load account list
    Program->>ME: Pass SlabSet + Bob market buy (100 SOL)

    ME->>TrieSlab: Read root, delta_qty=100 >= 100
    ME->>TrieSlab: Descend TrieNode(1) then TrieNode(5) then PriceNode
    ME->>PriceSlab: Read PriceNode(150), next_match_offset=0
    ME->>BlockSlab: Read entry[0] qty=100, quote=15000
    ME->>ME: remaining=100, entry=100: FULL FILL
    ME->>BlockSlab: entry[0] consumed, block delta=0
    ME->>PriceSlab: PriceNode delta=0
    ME->>TrieSlab: TrieNode(5) delta=0, set is_active=0
    ME->>TrieSlab: TrieNode(1) delta=0, set is_active=0
    ME->>TrieSlab: root delta=0

    ME-->>Program: MatchResult filled=100, remaining=0
    Program->>SQ: Write FillRecord(Alice_coord, 100, 15000, 150, ask)
    Program-->>Crank: Success

    Note over Alice,Crank: SLOTS N+5 and N+6: Settlement + Cleanup (parallel)

    par Stage 8 Settlement (slot N+5)
        Crank->>RPC: Submit settlement tx
        RPC->>Program: settlement
        Program->>SQ: Read FillRecord
        Program->>AIN: Resolve Alice AddressIndexNode
        Program->>OESN: Update Alice OrderEntryStatusNode to closed
        Program->>OESN: Create ChangeLogNode(full_fill, 100, 15000)
        Program->>AIN: num_open_entries -= 1
        Program->>AliceAcct: quantity_amount -= 100 SOL
        Program->>AliceAcct: quote_amount += 15000 USDC
        Program->>BobAcct: quote_amount -= 15000 USDC
        Program->>BobAcct: quantity_amount += 100 SOL
        Program-->>Crank: Success
    and Stage 7 Cleanup (slot N+6)
        Crank->>RPC: Submit cleanup tx
        RPC->>Program: cleanup
        Program->>BlockSlab: Delete consumed OrderBlock
        Program->>PriceSlab: Delete empty PriceNode(150)
        Program->>TrieSlab: Delete TrieNode(5) and TrieNode(1)
        Program->>MC: WRITE-LOCK OFF
        Program-->>Crank: Success
    end

    Note over Alice,Crank: TRADE COMPLETE
    AW-->>Alice: Sold 100 SOL, received 15000 USDC
    BW-->>Bob: Bought 100 SOL, paid 15000 USDC
Loading

14. Partial Fill Continuation

When a market order cannot be fully filled at one price level, matching continues to the next. When CU budget runs low, the engine stops and the remaining amount re-enters the pipeline.

sequenceDiagram
    participant ME as Matching Engine
    participant Trie as TrieNode Slab
    participant Price as PriceNode Slab
    participant Block as OrderBlock Slab
    participant Stack as Path Stack
    participant Program

    Note over ME,Program: Market Buy 500 SOL: ask book has 200 at $150 and 300 at $152

    ME->>Trie: Traverse ask trie (0 to 9)
    ME->>Trie: Find best price $150
    ME->>Price: PriceNode(150), delta_qty=200
    ME->>Block: Consume entries FIFO

    loop Consume all entries at $150
        ME->>Block: entry qty=50: FULL FILL, remaining=450
        ME->>Block: entry qty=50: FULL FILL, remaining=400
        ME->>Block: entry qty=50: FULL FILL, remaining=350
        ME->>Block: entry qty=50: FULL FILL, remaining=300
    end

    ME->>ME: Price level $150 exhausted (delta=0)
    ME->>Trie: Set is_active=0 on $150 path
    ME->>ME: Propagate deltas up: -200 qty

    Note over ME,Program: Move to next price level

    ME->>Trie: Delta traverse up, find next subtree
    ME->>Trie: Find next best price $152
    ME->>Price: PriceNode(152), delta_qty=300
    ME->>Block: Consume entries FIFO

    loop Consume entries at $152
        ME->>Block: entry qty=100: FULL FILL, remaining=200
        ME->>Block: entry qty=100: FULL FILL, remaining=100
        ME->>Block: entry qty=100: FULL FILL, remaining=0
    end

    ME->>ME: Order fully filled across 2 price levels
    ME->>ME: Propagate deltas: -300 qty at $152 path

    ME-->>Program: MatchResult filled=500, remaining=0, fills=7
    Note over Program: 4 fills at $150 + 3 fills at $152

    Note over ME,Program: Alternative: CU Budget Hit

    ME->>ME: After consuming 3 entries check CU budget
    ME->>ME: remaining_budget less than CU_SAFETY_MARGIN
    ME-->>Program: MatchResult filled=300, remaining=200, stop=BudgetApproached

    Note over Program: Remaining 200 SOL re-enters pipeline
    Note over Program: Next batch picks up the unfilled portion
    Note over Program: Exact continuation mechanism is WIP (Q-014)

    Note over ME,Program: Alternative: Book Exhausted

    ME->>ME: No more price levels in trie with delta > 0
    ME-->>Program: MatchResult filled=300, remaining=200, stop=BookExhausted

    Note over ME,Program: Alternative: Price Target Hit

    ME->>ME: Next price level exceeds target_price constraint
    ME-->>Program: MatchResult filled=300, remaining=200, stop=PriceTargetHit
Loading

15. Concurrent Pipeline — Multi-Batch View

Multiple batches flowing through the pipeline simultaneously. Each stage writes to different accounts, so Sealevel runs them all in parallel within the same slot.

sequenceDiagram
    participant BA as Batch A
    participant BB as Batch B
    participant BC as Batch C
    participant SL as Sealevel Runtime

    Note over BA,SL: Slot N
    BA->>SL: Stage 1+2: Place orders (LOQ_A, MOQ_A)
    Note over SL: 1 stage active

    Note over BA,SL: Slot N+1
    BA->>SL: Stage 3: Aggregation (Agg_A)
    BB->>SL: Stage 1+2: Place orders (LOQ_B, MOQ_B)
    Note over SL: 2 stages parallel, disjoint accounts

    Note over BA,SL: Slot N+2
    BA->>SL: Stage 4: OB Update (TrieSlab, PriceSlab, BlockSlab, MC)
    BB->>SL: Stage 3: Aggregation (Agg_B)
    BC->>SL: Stage 1+2: Place orders (LOQ_C, MOQ_C)
    Note over SL: 3 stages parallel, disjoint accounts

    Note over BA,SL: Slot N+3
    BA->>SL: Stage 5: Pre-Compute (Cache_A, OB read-only)
    BB->>SL: Stage 4: OB Update (writes OB slabs)
    BC->>SL: Stage 3: Aggregation (Agg_C)
    Note over SL: 3 stages parallel
    Note over SL: Pre-compute uses OrderBookChangeLog not live slabs

    Note over BA,SL: Slot N+4
    BA->>SL: Stage 6: Match (SQ_A, OB slabs)
    BB->>SL: Stage 5: Pre-Compute (Cache_B)
    BC->>SL: Stage 4: OB Update
    Note over SL: 3 stages parallel

    Note over BA,SL: Slot N+5
    BA->>SL: Stage 8: Settlement (Ledger, AccountStatus)
    BB->>SL: Stage 6: Match (SQ_B, OB slabs)
    BC->>SL: Stage 5: Pre-Compute (Cache_C)
    Note over SL: 3 stages parallel

    Note over BA,SL: Slot N+6
    BA->>SL: Stage 7: Cleanup (OB slabs, MC unlock)
    BB->>SL: Stage 8: Settlement (Ledger)
    BC->>SL: Stage 6: Match (SQ_C)
    Note over SL: 3 stages parallel

    Note over BA,SL: Slot N+7
    BB->>SL: Stage 7: Cleanup
    BC->>SL: Stage 8: Settlement
    Note over SL: Batch A complete

    Note over BA,SL: Slot N+8
    BC->>SL: Stage 7: Cleanup
    Note over SL: Batch B complete, Batch C complete
Loading

Account Access Summary

Every pipeline stage and the accounts it touches. This is the disjointness guarantee that makes concurrent execution possible.

Stage Slot Writes To Reads From
1. Limit Order Queue n LimitOrderQueue, PriceQueue, PriceTrie, EntriesQueue, AddressIndexQueue, CoordinatesQueue MarketConfig, AccountStatus
2. Market Order Queue n MarketOrderQueue, MarketOrderPriceQueue, AddressIndexCache MarketConfig, AccountStatus
3. Aggregation n+1 LimitOrderAggregation LimitOrderQueue (prior slot)
4. OB Update n+2 MarketConfig (write-lock), TrieNode Slab, PriceNode Slab, OrderBlock Slab, OrderBookChangeLog LimitOrderAggregation
5. Pre-Compute n+3 MarketOrderCache MarketOrderQueue, OrderBookChangeLog, PriceNode Slab (read), OrderBlock Slab (read)
6. Match n+4 SettlementQueue, TrieNode Slab, PriceNode Slab, OrderBlock Slab (deltas) MarketOrderCache
7. Cleanup n+6 Order Book Slabs (delete nodes), MarketConfig (release lock) SettlementQueue
8. Settlement n+5 AddressIndexNode Slab, OrderEntryStatusNode Slab, ChangeLogNode Slab, AccountStatus SettlementQueue

Settlement writes to Ledger + AccountStatus. Cleanup writes to Order Book slabs + MarketConfig. Zero overlap: they run in parallel.


Order State Machine

Every order transitions through these states as it moves through the pipeline:

stateDiagram-v2
    [*] --> Submitted: User signs tx

    Submitted --> Queued: Stage 1 or 2 validates and writes to queue

    state LimitOrderPath {
        Queued --> Aggregated: Stage 3 groups by price
        Aggregated --> InOrderBook: Stage 4 inserts into slabs
        InOrderBook --> PartiallyMatched: Stage 6 partial fill
        InOrderBook --> FullyMatched: Stage 6 full fill
        InOrderBook --> CancelRequested: User submits cancel
        PartiallyMatched --> FullyMatched: Stage 6 subsequent fill
        PartiallyMatched --> CancelRequested: User submits cancel
        CancelRequested --> Cancelled: Stage 4 processes cancel
    }

    state MarketOrderPath {
        Queued --> Cached: Stage 5 pre-computes accounts
        Cached --> PartiallyFilled: Stage 6 partial fill
        Cached --> FullyFilled: Stage 6 full fill
        PartiallyFilled --> FullyFilled: Next batch continues
        PartiallyFilled --> Unfillable: Book exhausted or price target hit
    }

    FullyMatched --> Settled: Stage 8 updates ledger and balances
    Cancelled --> Settled: Stage 8 returns funds
    FullyFilled --> Settled: Stage 8 updates balances
    Unfillable --> Settled: Stage 8 returns remaining funds

    Settled --> CleanedUp: Stage 7 frees slab nodes
    CleanedUp --> [*]: Pipeline batch complete
Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment