What is DLOB?
DLOB (Decentralized Limit Order Book) is an in-memory representation of all resting limit orders on the Drift Protocol. It enables fast order matching and cross detection for keeper bots.Unlike traditional orderbooks that live on a centralized server, DLOB is maintained locally by each keeper bot based on on-chain state synchronized via gRPC.
- In-Memory: Stored in RAM for microsecond-level query performance
- Eventually Consistent: Updated via gRPC events as on-chain state changes
- Market-Agnostic: Tracks all perpetual and spot markets simultaneously
- Cross Detection: Primary purpose is finding profitable order matches
Purpose and Benefits
Why DLOB is Essential
Without DLOB:- Would need to scan all on-chain user accounts every slot
- Query time: ~100ms+ per market for RPC calls
- Would miss most opportunities due to latency
- Expensive in terms of RPC usage and costs
- Query time: ~10-100μs for cross detection
- No RPC calls during main loop
- Enables sub-slot reaction time
- Scales to hundreds of markets and thousands of orders
Use Cases
Filler Bot:- Auction Crosses: Find resting orders that cross with auction orders
- Swift Fills: Match Swift orders against resting liquidity
- Limit Uncrossing: Find resting limit orders that cross each other
- AMM Opportunities: Identify when vAMM wants to provide liquidity
- Maker Queries: Find best resting orders to fill liquidated positions
- Top Maker Selection: Get optimal liquidity for
liquidate_perp_with_fill - Market Depth: Assess available liquidity before attempting liquidation
Core Data Structures
Order Representation
Orders in DLOB are stored asL3Order (Level 3 - full order details):
Orderbook Organization
The DLOB organizes orders hierarchically:- Orders grouped by market, side, and price level
- Price levels sorted for efficient matching
- Orders within price level maintain insertion order (FIFO)
- Fast lookups by user or order ID
Updating DLOB State
DLOBNotifier
TheDLOBNotifier processes gRPC events and updates DLOB:
Event Types
Account Updates:- User account changes (orders placed, filled, cancelled)
- Market account changes (AMM state updates)
- Triggers auction price recalculation
- Updates time-based order states (expiration)
Update Flow
- Receive gRPC Account Update
- Parse Account Data: Deserialize user account
- Compare to Previous State: Detect what changed
- Emit DLOBEvent: Notify DLOB of specific change
- DLOB Processes Event: Update internal data structures
Updates are processed asynchronously, so DLOB state may briefly lag on-chain state by a few milliseconds.
Cross Detection
Finding Auction Crosses
Auction orders have dynamic prices that improve over time:- Get All Auction Orders: Filter orders by market and type
- Calculate Auction Prices: Use current slot to compute price for each auction
- For Each Auction Order:
- Determine crossing region (e.g., auction buy at 27.40)
- Query DLOB for resting orders in that region
- Return makers that cross, ordered by best price
- Check AMM Opportunities: Determine if vAMM wants to participate
- Return Results: List of (taker_order, maker_crosses) pairs
Finding Swift Order Crosses
Swift orders are matched against all resting liquidity:- Create TakerOrder: Convert Swift order params to DLOB taker format
- Determine Direction: Long taker crosses resting asks, short crosses bids
- Query Price Levels: Get all resting orders that price-match
- Calculate Fill Amounts: Determine how much can be filled at each level
- Return Makers: List of crossing makers with fill amounts
Crossing Regions
TheCrossingRegion determines which price levels to query:
- Auction starts at oracle price, improves upward
- Current auction price: $27.50
- Crossing region:
Above { price: 27500000000 } - Query: Resting asks at $27.50 or higher
- Market order buys at best available price
- Direction: Long (buying)
- Crossing region:
Above { price: 0 }(crosses all asks) - Query: All resting asks, starting from lowest price
Order Matching and Priority
Price-Time Priority
DLOB respects standard orderbook priority:-
Price Priority: Better prices matched first
- Long taker: Lower ask prices first
- Short taker: Higher bid prices first
-
Time Priority: Within same price level, FIFO
- Earlier orders filled before later orders
- Maintained by insertion order in data structure
Top Maker Queries
For liquidations, the bot queries the best available makers:- Query Top Makers: Get best resting short orders (asks)
- Select Makers: Choose top N makers that can fill 10 SOL
- Build Transaction: Include maker accounts in
liquidate_perp_with_fill - Execute: Drift protocol matches liquidation against makers on-chain
- Prefer makers with best prices (lowest cost for liquidator)
- Consider multiple makers to ensure full fill
- Respect protocol limits (max 4-6 maker accounts per transaction)
- Balance gas cost vs. execution quality
Real Implementation Details
Memory Efficiency
DLOB must handle thousands of orders efficiently: Optimization Techniques:- Orders stored by reference to avoid copying
- Price levels use efficient tree structures (BTreeMap)
- Inactive orders removed immediately
- Old slots garbage collected
Consistency Guarantees
DLOB is eventually consistent with on-chain state: Consistency Characteristics:- Updates arrive via gRPC within ~10-50ms of on-chain change
- Order may briefly appear after it’s filled on-chain
- Bot must handle “order already filled” errors gracefully
- Critical: Always verify state on-chain before assuming success
The DLOB’s eventual consistency is acceptable because transactions always validate state on-chain. The DLOB is an optimization for opportunity detection, not the source of truth.
Handling Stale Orders
Orders can become invalid between cross detection and execution: Mitigation Strategies:-
Slot Limiter: Avoid repeated attempts on same order (util.rs:28)
- Fresh State Checks: Query DriftClient for latest state before transaction
- Graceful Error Handling: Treat “order not found” as competition, not bot error
- Metrics Tracking: Monitor stale order rate to detect DLOB lag issues
Performance Characteristics
Query Performance:find_crosses_for_auctions: O(A * log(O) * M)- A = number of auction orders
- O = number of resting orders per market
- M = number of makers per cross
find_crosses_for_taker_order: O(log(O) * M)get_top_makers: O(log(O) + M)
- Single market auction cross detection: ~50-200μs
- All markets auction cross detection: ~500μs-2ms
- Swift order cross detection: ~10-50μs
These latencies are negligible compared to network latency (~10-50ms) and slot time (~400ms), making DLOB the performance bottleneck is virtually impossible.
Liquidator-Specific Usage
Liquidator bots use DLOB differently than fillers:Finding Liquidity for Liquidations
When a liquidatable user is found:- Finds largest perp position
- Queries DLOB for top makers (asks for longs, bids for shorts)
- Builds
liquidate_perp_with_filltransaction - Uses atomic on-chain matching against makers
Liquidity Assessment
Before attempting a liquidation, assess if sufficient liquidity exists:- Must balance liquidation reward vs. execution cost
- Partial liquidations are possible but increase complexity
- Deep liquidity enables larger, more profitable liquidations
Best Practices
For Filler Bots
-
Filter Crosses Before Execution:
- Use slot limiter to avoid repeated attempts
- Remove orders with insufficient remaining size
- Verify auction price still valid
-
Handle Partial Fills Gracefully:
- DLOB may show cross, but maker filled by competitor
- Expect
actual_fills < expected_fills - Track metrics to optimize maker selection
-
Monitor DLOB Update Lag:
- High lag indicates gRPC subscription issues
- Correlate with increased “order not found” errors
- May need to reconnect or switch gRPC endpoints
For Liquidator Bots
-
Query Multiple Makers:
- Single maker may not have enough size
- Multiple makers increase fill probability
- Balance maker count vs. transaction size
-
Consider Maker Reliability:
- Some makers may have invalid accounts
- Track which makers consistently fail
- May want to maintain maker blacklist
-
Fallback to AMM:
- If DLOB liquidity insufficient, use vAMM
- Trade worse execution for guaranteed fill
- Essential for time-sensitive liquidations
General Best Practices
-
Never Trust DLOB Alone:
- Always verify on-chain state before critical decisions
- DLOB is an optimization, not source of truth
- Build resilience to stale data
-
Profile Query Performance:
- Measure cross detection latency
- Identify performance bottlenecks
- Optimize hot paths in main loop
-
Test with Realistic Data:
- Populate test DLOB with market-like order distribution
- Verify cross detection correctness
- Test edge cases (empty orderbook, single order, etc.)
The DLOB is the competitive advantage of keeper bots. Fast, accurate cross detection enables capturing opportunities before competitors.