Phoenix DEX Maker Rebates: Building a Market-Making Bot on Solana
Build a Phoenix Solana market making bot: crankless on-chain order book mechanics, maker rebate economics, quote freshness, and the latency that decides P&L.
Phoenix settles fills the moment they match. There's no crank to turn, no permissionless keeper you have to bribe with priority fees to process your queue — the order book lives fully on-chain and executes atomically inside the transaction that touches it. That single design choice changes how you build a market-making bot on Solana, and it changes the rebate math in ways that OpenBook v2 doesn't.
If you've written MM code against Serum or OpenBook, throw out your event-consumer loop. Phoenix has no event queue to consume. Fills post to the ledger at instruction time, so the "did my order fill?" question is answered by watching account state and transaction logs, not by cranking a queue and reconciling later.
What "crankless" actually buys you
On Serum-style books, a resting order that gets hit doesn't credit your wallet immediately. The match lands in an event queue, and someone — usually you, or a shared crank bot — has to submit a separate transaction to process those events before balances update. That's extra latency, extra fees, and a reconciliation headache when the crank falls behind under load.
Phoenix removes that entire stage. When a taker crosses your quote, the match, the token transfer, and the fee accounting all happen in one atomic step. Practically, that means:
- Your filled inventory is spendable in the next slot, not after a crank round-trip.
- There's no queue backlog to monitor, so your "stale fill" edge cases disappear.
- Free funds vs. locked funds is a clean read off your seat's on-chain state.
The tradeoff is that everything is heavier at the instruction level. A Phoenix PlaceLimitOrder does real book-walking on-chain, so your compute-unit budget matters. Batch your cancels and replaces into a single transaction with CancelMultipleOrdersById plus a fresh place, and set a realistic CU limit — I've seen naive quote refreshes get silently dropped because the default 200k CU ceiling wasn't enough for a multi-level replace on a busy market.
The rebate economics, concretely
Phoenix charges taker fees and can pay maker rebates, and the split is set per-market by governance rather than being a flat protocol constant. On the liquid pairs (SOL/USDC being the obvious one), the taker fee is in the single-digit-basis-point range and a portion routes back to makers. Don't hardcode a number — read the market's fee parameters from its on-chain header at startup and re-check on a schedule, because a market that pays 0 rebate today can be adjusted.
Here's the mental model that keeps you solvent. Your edge per round-trip is:
edge = half_spread_captured + maker_rebate - adverse_selection - inventory_carry
The rebate is the only term that's positive and (roughly) deterministic. Everything else is a fight. Adverse selection — getting filled precisely when the market is about to move against you — is what quietly eats MM P&L, and no rebate saves you if your quotes are stale when a taker with better information arrives. So the rebate is a floor, not a strategy. Treat it as the thing that makes marginal quotes worth resting, not as the reason to quote at all.
A quick worked example. Say SOL/USDC pays a 1 bp maker rebate and you're quoting a 4 bp full spread (2 bp each side). If you round-trip $50k of notional and capture the spread cleanly, that's roughly $20 from the spread plus $5 from rebates. Two adverse fills where the mid moves 3 bp against you before you re-quote wipes out $30. The rebate didn't save that trade — quote freshness would have. This is why latency and MM quality are the same problem, not two problems.
Quote freshness is a networking problem
Your fills are only as good as your ability to cancel before you get picked off. On Solana that means transaction landing, and transaction landing is where most MM bots quietly bleed. A cancel that doesn't land in time is an adverse fill you invited.
Three things move the needle here, in order of impact:
Priority and QoS. Getting your cancel-replace to the leader ahead of the taker is partly a fee-market problem and partly a connection-quality problem. If you're not already routing through stake-weighted QoS, that's the single biggest landing-rate win available; the mechanics are covered in depth in how stake-weighted QoS decides which transactions the leader actually accepts.
QUIC connection health. Solana's TPU uses QUIC, and under contention validators throttle connections that misbehave. A bot that opens too many streams or hits stake-based limits gets its transactions silently dropped, which for an MM shows up as inexplicable stuck quotes. The failure modes and how to avoid them are laid out in why QUIC throttling drops bot transactions.
Faster market data. You can't refresh a quote you haven't priced yet. Pulling fills and book changes off a low-latency shred feed instead of waiting for confirmed RPC gets you a head start on re-quoting; the ShredStream approach to reading fills before the block is confirmed is what serious desks use.
None of this is Phoenix-specific, but Phoenix's atomic fills make it unforgiving: because there's no crank delay softening the timeline, a slow cancel gets converted into a real fill immediately.
A minimal quote loop
The shape of a Phoenix MM loop, stripped to essentials:
while running:
book = read_market_state(market_pubkey) # ladder + your seat
mid = fair_value(book, hedge_venue_price) # your pricing, not just book mid
skew = inventory_skew(seat.base_free) # push quotes to flatten inventory
bid = mid - half_spread - skew
ask = mid + half_spread - skew
ixs = [
cancel_all_for_seat(seat),
place_limit(Side.Bid, bid, size),
place_limit(Side.Ask, ask, size),
]
tx = build_tx(ixs, cu_limit=350_000, priority_fee=dynamic_fee())
send_via_swqos(tx)
The details that separate a demo from something you'd run with real size: inventory_skew should widen and shift, not just shift, as you get longer or shorter; dynamic_fee should scale with observed contention on the specific slot leader; and fair_value should never be the raw book mid on a thin market, or you'll quote yourself into a corner during a sweep. Hedging your delta on a deeper venue is what lets you quote tighter than your standalone risk tolerance would allow.
Where Phoenix fits — and where it doesn't
Phoenix is a genuinely good venue for a central-limit-order-book strategy on the majors, and the crankless design removes a whole class of operational pain. But it's a book, not a bonding curve, so it's the wrong tool for new-launch flow. If your target is fresh tokens, that's sniper and Pump.fun bundling territory, which are different beasts entirely. Cross-venue mispricings between Phoenix and the AMMs are their own opportunity — that's an MEV and arbitrage problem, and it pairs naturally with a maker book because you already have the inventory and the fills.
The unglamorous truth is that most of the work in a profitable Phoenix MM bot isn't the quoting logic — it's the low-latency infrastructure and data plane underneath it. Colocation, healthy QUIC connections, a fast fill feed, and a fee policy tuned to the leader schedule matter more than shaving another basis point off your spread model.
If you want a Phoenix market-making bot built with the rebate economics and landing-rate engineering handled properly, that's exactly what we do on the Solana market-maker side.
Need a bot like this built?
We design, build and run trading bots on Solana, Hyperliquid and Polymarket.
Start a projectMore from the blog
Public vs Paid RPC: How to Run a Fair Benchmark
A fair comparison of public and paid RPC endpoints must account for quotas, workload, freshness and support guarantees.
Read articleRPC Benchmark Percentiles Explained: p50, p95 and p99
Why averages hide the latency spikes that break trading bots, wallets and production blockchain applications.
Read articleHyperliquid REST vs WebSocket Benchmark: What to Measure
A benchmark plan for Hyperliquid market data that separates request latency from streaming freshness and recovery.
Read article