A Solana central-limit order book (CLOB) with a DODO-style quadratic PMM fallback — built on Pinocchio (no Anchor) and delegated to MagicBlock ephemeral rollups for ~10 ms execution.
FluxDEX is an exchange-oriented Solana program that combines a price-time-priority order book with a proactive market maker (PMM) fallback. The CLOB matches orders when they cross; the PMM provides oracle-referenced liquidity via a quadratic pricing curve when no resting counterparty exists.
Custody and durable state live on Solana L1. The order book can be delegated to a MagicBlock ephemeral rollup for low-latency, gasless session trading, then committed and undelegated back to L1 — with vault custody never leaving the main chain.
⚠️ NOT PRODUCTION READY. This code has not had a professional security audit. Do not use with real funds.
Most on-chain venues are either a pure AMM (high slippage, impermanent loss) or a pure CLOB (no fallback liquidity when the book is thin). FluxDEX runs both:
- CLOB as primary — price-time priority matching against resting orders.
- PMM as fallback — an oracle-anchored quadratic curve fills when the book can't.
- MagicBlock delegation — the orderbook executes inside an ephemeral session for ~10 ms blocks and gasless, session-key-signed trades.
- Zero-copy, no Anchor —
bytemuck::Podaccount structs over Pinocchio; tiny CU footprint (e.g.place_order≈ 14k CU,match_orders≈ 7k CU). - Python-validated math — the PMM curve is specified and tested in Python first, exported as JSON vectors, then ported to Rust.
+----------------------------------+
| Solana L1 (durable) |
|----------------------------------|
| Market config + PMM/oracle params|
| Vault custody (base + quote PDAs)|
| Orderbook account (CLOB state) |
| Fee accounting + authority/pause |
+----------------+-----------------+
|
delegate / commit / undelegate (MagicBlock DLP)
|
+----------------v-----------------+
| MagicBlock Ephemeral Rollup |
|----------------------------------|
| ~10 ms block time |
| gasless session-key transactions |
| CLOB matching (price-time) |
+----------------+-----------------+
|
no CLOB match?
v
+----------------------------------+
| PMM Engine (quadratic DODO) |
|----------------------------------|
| P = i·(1 − k + k·(B₀/B)²) |
| Pyth oracle price (raw-parsed) |
+----------------------------------+
The full layered system design — from the trader's wallet down to atomic settlement:
| Layer | Responsibility | Key elements |
|---|---|---|
| L1 — User | Wallet connection + transaction signing | Trader connects wallet, signs txs |
| L2 — Frontend | Consumer-grade trading UI | /trade, /markets, /portfolio routes; OrderBook, PlaceOrder, Portfolio, MarketStats, LatencyTimer — React · Vite · TailwindCSS · Wallet Adapter · Solana Web3.js · MagicBlock SDK |
| L3 — RPC / Data | Realtime on-chain data | RPC endpoint, WebSocket subscriptions, account-change notifications |
| L4 — Smart contract (Pinocchio) | Zero-overhead Solana program with manual account validation | initialize_market, place_order, cancel_order, delegate_orderbook, match_orders, settle_trade, undelegate_orderbook (+ admin ixs); owner + discriminator checks, PDA canonical bump stored, CPI pattern enforced |
| L6 — MagicBlock ephemeral rollup | ~10 ms blocks, gasless session txs | Delegated orderbook PDA locked on L1 while the ER is active; session executor with gasless session keys → CLOB matching engine (price-time priority, crit-bit tree, O(log n)): cross? YES → atomic fill, NO → PMM fallback |
| L8 — PMM pricing engine | Oracle-referenced quadratic fallback | Price = Oracle × (1 + k × skew) — oracle price in, inventory skew, effective price out |
| Pyth oracle | External price feed | SOL/USDC feed + confidence interval |
| L10 — Settlement | Atomic delivery-vs-payment via SPL Token CPI | SPL Token program CPI transfer (buyer receives), PDA-owned token vaults (unlock escrow), atomic buyer + seller settlement (seller receives), CCTP V2 cross-chain USDC |
| Layer | Technology |
|---|---|
| On-chain program | Rust 2024, Pinocchio 0.11 (no Anchor) |
| Serialization | bytemuck (zero-copy account state) + wincode (instruction args) |
| Token CPIs | pinocchio-token, pinocchio-associated-token-account, transfer_checked |
| Oracle | Pyth V2 price accounts, parsed from raw bytes (no pyth-sdk dependency) |
| Rollup / sessions | MagicBlock Delegation Program + gpl-session |
| Tests | LiteSVM integration suite |
| Reference math | Python 3.10+ (quadratic PMM + JSON test vectors) |
| Frontend | React 18, Vite, TypeScript, TailwindCSS, Solana Wallet Adapter, MagicBlock SDK |
| CI | GitHub Actions (fmt, clippy -D warnings, SBF build + cargo test) |
accel-FluxDEX/
├── src/ # On-chain program (Pinocchio)
│ ├── lib.rs # entrypoint + instruction dispatch
│ ├── instruction.rs # discriminators, arg structs, account contexts
│ ├── processor.rs # all 14 instruction handlers
│ ├── state.rs # Market / Order / Orderbook (zero-copy)
│ ├── error.rs # FluxDexError (37 variants)
│ ├── oracle.rs # Pyth price-account parsing & validation
│ ├── pmm.rs # quadratic PMM math (Rust port)
│ └── magicblock.rs # delegation / undelegate-callback CPIs
├── prototype/ # Python PMM reference + test-vector generator
│ ├── pmm_math.py # marginal price, integral, solver, regression
│ ├── cli.py # interactive CLI (tables, ASCII curve, calc)
│ ├── test_vectors.py # emits JSON vectors → prototype/vectors/
│ └── vectors/ # pricing / integral / swap / slippage / regression
├── tests/
│ ├── flux_dex_tests.rs # LiteSVM integration suite (95 tests)
│ └── fixtures/ # delegation_program.so, session_program.so
├── app/ # React + Vite + TS frontend
├── docs/ # PRD, TDD (source of truth), epics, screenshots
├── deploy/deploy-devnet.sh # devnet deploy helper
├── justfile # build / test / lint / pmm task runner
└── Cargo.toml
The program dispatches on a single leading discriminator byte (plus an 8-byte discriminator reserved for the MagicBlock undelegate callback).
| # | Discriminator | Instruction | Purpose |
|---|---|---|---|
| 0 | INIT_MARKET |
initialize_market |
Create market PDA + base/quote vaults |
| 1 | PLACE_ORDER |
place_order |
Place a bid/ask (optional session-key account) |
| 2 | CANCEL_ORDER |
cancel_order |
Cancel a resting order, refund escrow |
| 3 | DELEGATE_ORDERBOOK |
delegate_orderbook |
Hand the orderbook to the ephemeral rollup |
| 4 | UNDELEGATE_ORDERBOOK |
undelegate_orderbook |
Request return of the orderbook to L1 |
| 5 | UPDATE_ORDERBOOK |
update_orderbook |
Reconcile session-diff state on L1 |
| 6 | MATCH_ORDERS |
match_orders |
Crank: match crossing orders (optional oracle) |
| 7 | SETTLE_TRADE |
settle_trade |
Atomically move tokens + accrue fees |
| 8 | SET_MARKET_PARAMS |
set_market_params |
Tune fee, PMM k/B₀, oracle limits |
| 9 | PROPOSE_AUTHORITY |
propose_authority |
Step 1 of two-step authority rotation |
| 10 | ACCEPT_AUTHORITY |
accept_authority |
Step 2 (timelocked) — new authority accepts |
| 11 | WITHDRAW_FEES |
withdraw_fees |
Authority withdraws accumulated quote fees |
| 12 | SET_PAUSE |
set_market_pause |
Halt/resume trading (recovery paths stay open) |
| 13 | CANCEL_AUTHORITY_PROPOSAL |
cancel_authority_proposal |
Abort a pending rotation |
| — | 8-byte callback | handle_undelegate_callback |
DLP CPI returning the orderbook to L1 |
All account structs are #[repr(C)], bytemuck::Pod, with every multi-byte
field stored as a little-endian [u8; N] array (alignment 1, no padding). Typed
values are read/written through getters. See src/state.rs and docs/TDD.md §4.
| Account | Discriminator | Size | Notes |
|---|---|---|---|
Market |
1 |
265 B | authority, mints, vaults, fee, PMM params, cached oracle price, session expiry, two-step authority + timelock, accumulated fees, pause flag |
Order |
2 |
128 B | trader, side, price, quantity, status |
Orderbook |
3 |
43 B header | fixed header + dynamic tail of order entries |
The program was hardened in dedicated audit passes (commits #68/#69). Highlights:
#![deny(clippy::unwrap_used)]crate-wide — no panics in handler paths.- Checked arithmetic everywhere; overflow checks on in release profile.
- Per-instruction account validation: exact account counts, signer checks, writable checks, real program-ID checks, and duplicate mutable account guards (e.g. vaults must differ and can't double as settlement destinations).
- SPL
transfer_checked(validates mint + decimals) for every token movement. - Oracle price validation: configurable max confidence ratio (default 5%) and
max staleness (default 60 s); price is cached in
Market. - Two-step, timelocked authority rotation; pausable trading with fund-recovery
paths (
withdraw_fees) left open even when paused.
Despite this, the code is unaudited. Treat all of the above as defense-in-depth, not a guarantee.
Quadratic DODO pricing curve (full derivation in docs/TDD.md and prototype/README.md):
Marginal price:
P = i · (1 − k + k · (B₀/B)²) when B > B₀ (base excess → price drops)
P = i / (1 − k + k · (B/B₀)²) when B < B₀ (base deficit → price rises)
Integral (average fill price):
ΔQ = i · ΔB · (1 − k + k · B₀² / (B₁ · B₂))
Quadratic solver (quote → base):
a·ΔB² + b·ΔB + c = 0
Regression target (IL recovery):
ΔB = (√(B₀² − (B₀² − B²)(1 − k)) − B₀) / k
The Python reference (prototype/pmm_math.py) emits JSON vectors consumed by the
Rust port in src/pmm.rs.
- Rust (stable) — via rustup. Toolchain pinned in
rust-toolchain.toml. - Solana CLI — provides
cargo build-sbf. Install from anza.xyz. - Node.js 18+ — for the frontend in
app/. - Python 3.10+ — for the PMM prototype and vector generation.
- just (optional) —
cargo install just.
cargo build-sbf # → target/deploy/flux_dex.so
# or: just buildThe LiteSVM suite loads the compiled target/deploy/flux_dex.so, so you must
build the SBF artifact first (CI does exactly this):
cargo build-sbf # rebuild whenever src/ changes
cargo test # 95 integration tests + unit tests
⚠️ cargo testdoes not rebuild the.so. If you editsrc/and forget to re-runcargo build-sbf, tests run against a stale binary and fail withInvalidAccountCount(error 28). Always rebuild first.
cd app
cp .env.example .env # configure RPC + program ID
npm install
npm run dev # http://localhost:5173
npm test # 22 vitest testscargo build-sbf
./deploy/deploy-devnet.sh # uses ~/.config/solana/id.json
./deploy/deploy-devnet.sh ~/.config/solana/devnet.json # custom deployerDevnet program ID: 3onsNSU7Q8v5yZ14wTY9DnNHr76WSxwjfnD1jrDyZAPc
(deploying with your own program keypair yields your own ID.)
React + Vite + TypeScript + TailwindCSS trading interface.
- Pages — Landing, Markets, Trade, Portfolio (
react-router-dom). - Wallet —
@solana/wallet-adapter-reactconnection + UI. - MagicBlock — session-key management and delegation via
@magicblock-labs/ephemeral-rollups-sdkandgum-react-sdk(src/lib/magicblock.ts,src/hooks/useSession.ts). - Deposits — CCTP V2 cross-chain USDC deposit flow (
src/lib/cctp.ts,useDeposit.ts,DepositModal.tsx). - Data hooks —
useMarketData,useOrderBook,useWallet,useDeposit.
Environment variables (app/.env.example):
| Variable | Description | Default |
|---|---|---|
VITE_SOLANA_CLUSTER |
devnet | mainnet-beta | localnet |
devnet |
VITE_RPC_ENDPOINT |
Override RPC endpoint (recommended in prod) | cluster public URL |
VITE_MAGIC_ROUTER_ENDPOINT |
MagicBlock Magic Router endpoint | devnet router |
VITE_FLUXDEX_PROGRAM_ID |
Deployed program ID | devnet ID above |
| Command | Description |
|---|---|
just build |
Build the SBF program (cargo build-sbf) |
just test |
Run the test suite |
just lint |
cargo fmt --all + clippy (-D warnings -D unwrap_used) |
just check |
fmt-check + clippy (CI parity) |
just pmm |
PMM CLI — tables + ASCII curve + interactive calculator |
just pmm-table / just pmm-curve / just pmm-interactive |
Individual PMM views |
just pmm-vectors |
Regenerate JSON test vectors |
just deploy-devnet |
Deploy to devnet |
just all |
check + test + regenerate vectors |
Run just --list for the full set.
# On-chain program (build .so first!)
cargo build-sbf && cargo test
# Frontend
cd app && npm test
# Python PMM reference
just pmm # interactive CLI
just pmm-vectors # regenerate JSON vectorsCI (.github/workflows/ci.yml) runs three jobs on every push/PR to main:
fmt (cargo fmt --check), clippy (-D warnings -D clippy::unwrap_used),
and test (installs the Solana CLI, runs cargo build-sbf, then cargo test).
docs/TDD.md— technical design and source of truth (PMM math, state layout, instruction interface, security model).src/instruction.rs— the full instruction/account ABI.prototype/pmm_math.py— the PMM reference implementation.docs/prd.md— product requirements and open questions.
- Epic 1 — Foundation — scaffolding,
state.rs,error.rs, CI/CD ✅ - Epic 2 — Smart contract — all 14 instruction handlers + security hardening ✅
- Epic 3 — Frontend — React/Vite trading interface ✅
- Epic 4 — Integration — MagicBlock delegation, Pyth oracle, CCTP V2, deployment 🚧
See docs/epics/ for the full ticket breakdown.
Apache 2.0 — see LICENSE.




