π Live demo Β Β·Β π Docs
On-chain perpetual-futures CLOB on Solana order matching at rollup speed, custody at L1 security. Devnet MVP deployed and verified on Solana devnet + the MagicBlock devnet Ephemeral Rollup.
Slipstream is an on-chain perpetual-futures exchange built around a central-limit order book (CLOB) β the same price-time-priority matching model real exchanges use, not an AMM. It tracks SOL/USD with leverage up to 20Γ, funding, and liquidations.
The hard problem it solves: a real CLOB needs thousands of fast, cheap order updates, which Solana's base layer (L1) can't host directly β but L1 can custody money safely. Slipstream splits the system:
- Order matching runs inside a MagicBlock Ephemeral Rollup (ER) at ~10 ms β fast, sponsored, ideal for high-frequency quoting.
- All value-bearing state (collateral, positions, the token vault, funding) stays on Solana L1, where it is never delegated and therefore never at risk from the ER.
The one safety fact that matters: delegation to the ER is capped, not unlimited. The 612 KB OrderBook (non-financial β order metadata only) is delegated forever. The only value-bearing account that's ever delegated is TradingCredit β a per-market allowance the user explicitly funds and caps (
fund_trading_credit), never their whole balance.UserAccount.free_collateral,Position, and the token vault stay on L1 and are never delegated. A misbehaving ER can at worst scramble order ordering or misuse a session's capped credit allowance β it can never reach the vault or a user's un-delegated balance.
| Capability | Status |
|---|---|
| Limit + market orders, price-time-priority matching in the ER | live |
| Margin Γ leverage (up to 20Γ), real notional/PnL accounting | live |
ER β L1 settlement into real Position accounts (FillLog pipeline) |
live |
| Partial close + slippage-bounded close-at-market | live |
| Stop-loss / take-profit trigger orders (keeper-executed on-chain) | live, keeper-cranked |
| Funding rate (8h interval, self-computed 30-min TWAP) | live, keeper-cranked |
| Liquidations (health factor, liq price) | live, keeper-cranked |
| Session keys (sign once, trade many β no popup per order) | live |
| Live Pyth price chart (SSE stream + real OHLC history) | live |
| Settled-trade history + system-status panel (SQLite fills indexer) | live |
| On-chain order book held in a single ~612 KB PDA | live |
CI (clippy -D warnings, mollusk program tests, tsc + eslint) |
green |
flowchart TB
subgraph FE["Frontend Β· Next.js"]
UI["Wallet Β· Margin Γ Leverage Order Form<br/>Live Pyth Charts Β· Order Book Β· Positions"]
end
subgraph ER["MagicBlock ER Β· ~10ms blocks"]
OB["OrderBook (612KB)<br/>delegated execution"]
TC["TradingCredit<br/>capped per-market allowance<br/>delegated during a session"]
end
subgraph L1["Solana L1"]
BASE["free_collateral Β· Vault<br/>Positions Β· Funding<br/>(never delegated)"]
end
KEEP["Keepers (pm2 bots)<br/>settlement Β· funding Β· liquidation Β· twap Β· expiry"]
UI -->|"/api/rpc/er (orders)"| OB
UI -->|"/api/rpc/base (positions, balances)"| BASE
BASE -->|"fund_trading_credit (capped)"| TC
OB -->|"commit via small FillLog"| BASE
KEEP --> OB
KEEP --> BASE
- Program (
programs/): written in Pinocchio (minimal, zero-dep Solana SDK). The 612 KB order book is one flat#[repr(C)]/Podaccount read via zero-copy slices and grown in 10 KB chunks (Solana's per-CPI growth cap). 40 instructions, including keeper-executed SL/TP triggers and a mark-price freshness gate that refuses to settle closes off a stale/dead price feed. - Settlement (
FillLogpipeline): because the 612 KB book can't be committed to L1 (size cap + a verified 10-commit-per-account limit), a tiny ~8 KB epoch-rotatable FillLog carries fills L1-ward:mirror_fills(ER) βcommit_fill_log(ERβL1) βsettle_from_log(L1). The book stays delegated forever, never committed. - Client SDK (
client/): PDA derivation, account decoders, instruction builders. - Keepers (
keepers/): off-chain bots that crank funding, liquidation, TWAP, expiry, and the settlement pipeline. - Frontend (
frontend/): Next.js app; routes all RPC through same-origin proxies to avoid CORS and stream live Pyth prices.
π Full technical deep-dive: docs/ β 8 docs covering the
architecture, PDA storage, ephemeral rollups, the settlement pipeline, margin/funding/
liquidation math, session keys, the problems-and-solutions tour, and a glossary.
The fastest way is the live demo at slipstream.ansht.tech. You do not need a wallet extension: signing in with Google or Apple creates an in-app wallet, and the in-app faucet funds it. See New-user walkthrough below for the exact click path (sign in β get test USDC β start trading β trade).
- Node 20+. No wallet extension needed β signing in with Google or Apple creates the in-app wallet. A devnet-set Phantom/Backpack extension also works if you prefer one.
- A dedicated devnet RPC in
BASE_RPC_UPSTREAMβ the public endpoint rate-limits hard enough that the faucet and balance reads fail without it. - (Only to rebuild the on-chain program: Rust + Solana CLI +
cargo build-sbf.)
cd frontend
npm install
npm run dev # http://localhost:3000The build reads live on-chain addresses from the committed deploy.json (copied into the
app by scripts/copy-manifest.mjs). No env vars are required to run against the live
devnet deployment. To point at a different RPC, set BASE_RPC_UPSTREAM / ER_RPC_UPSTREAM
(see frontend/README.md).
# Program: lint + unit/mollusk tests (build the .so first β the mollusk tests
# execute the real compiled program). This is exactly what CI runs (see
# .github/workflows/ci.yml) β the two -A flags are intentional, not omitted:
# clippy::too-many-arguments trips on a few internal helpers that are clearer
# flat than split, and unexpected_cfgs is pinocchio's own entrypoint! macro
# expansion, not this crate's code.
cargo clippy -p slipstream --locked -- -D warnings -A clippy::too-many-arguments -A unexpected_cfgs
cargo build-sbf --manifest-path programs/slipstream/Cargo.toml
cargo test --manifest-path programs/slipstream/Cargo.toml --locked # math/oracle unit tests
cargo test --manifest-path tests/unit/Cargo.toml --locked # mollusk tests
# Frontend production build (type-checks + compiles)
cd frontend && npm run buildcd keepers
cp .env.example .env # set BASE_RPC / ER_RPC / KEEPER_KEYPAIR
npm install
npm run funding # or: liquidation Β· twap Β· expiry Β· fill-log-keeperSource of truth is deploy.json. Current deployment:
| Address | |
|---|---|
| Program | 7qujfsb4ZPbQHYVZdqiXq1r8tVAMyyukX94obPqXbVwz |
| Market (SOL-PERP) | ECUp8pXzVLzxjVs8mtKBJma3mdcHf8zSC4cqPeBy8MPy |
| OrderBook | 83zMFL6cHjgXkQ7KRNcgtHaZ1fhyNgxhM8aMpPpEnMqe |
| Pyth SOL/USD feed | 7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE |
slipstream/
βββ programs/slipstream/ # On-chain program (Pinocchio, Rust) β 40 instructions
βββ client/ # TypeScript client SDK (PDAs, decoders, ix builders)
βββ keepers/ # Off-chain bots (flat src/*.ts): fill-log, funding,
β β # liquidation+triggers, twap, expiry, market-maker, taker
β βββ ecosystem.config.js # pm2 process definitions
β βββ data/fills.db # SQLite fills indexer (gitignored, keeper-written)
βββ frontend/ # Next.js trading UI (+ /api/rpc, /api/trades, /api/status)
βββ tests/unit/ # Rust unit + mollusk (in-SVM) program tests
βββ docs/ # 8 technical docs + architecture diagrams
βββ .github/workflows/ci.yml # clippy + mollusk tests + tsc/eslint
βββ deploy.json # Live on-chain addresses (source of truth)
Exactly what a brand-new user does to go from nothing to a live trade. Everything is devnet β no real money, and the tokens are worthless test tokens.
- Open the app at slipstream.ansht.tech and click Start trading (or Open the terminal).
- Sign in. Google, Apple, or a Solana wallet you already have. Signing in with Google or Apple creates a Phantom-secured in-app wallet β no extension, no seed phrase to write down. That wallet is the on-chain owner of everything below.
- Get test USDC. Click Get test USDC in the Wallet panel. The faucet mints devnet USDC and, if the wallet is short, tops it up with the small amount of SOL that network fees need. Fresh wallets have neither, so this step is not optional.
- Start trading. One click chains the whole setup: it initialises your account, deposits collateral into the L1 vault, funds a capped trading credit for SOL-PERP, delegates that credit to the Ephemeral Rollup, and authorises a session key. You sign each money-moving step β the app never holds a key that can move funds on its own.
- Trade. Use the order form: pick Margin ($), Leverage (1β20Γ), and a Limit price or Market. The form derives your position size. Orders are signed locally by the session key, so there is no wallet popup per order. They match in the ER instantly and show as a pending position.
- Watch it settle. A keeper mirrors your fill from the ER to L1 within a few seconds. Your Positions table then shows the real settled position with live PnL, health, and liquidation price.
- Withdraw. Close any open positions and cancel resting orders first β the program requires an idle account. Withdraw then unwinds the setup in reverse: undelegate from the rollup, wait for the base layer to take ownership back (this is asynchronous, so the UI polls), withdraw the trading credit, and withdraw collateral to your wallet.
Money flow, in one line:
wallet USDC β deposit β collateral (L1) β fund β capped credit β delegate β ER β trade β settle β Position (L1).The session key can only place and cancel orders. Every step that moves money requires the owner's signature β see
docs/06-session-keys.md.
| Property | Devnet MVP (actual) | Required for mainnet |
|---|---|---|
| Fund safety | OrderBook (non-financial) + a capped, user-funded TradingCredit allowance delegated; free_collateral/vault/Position never delegated |
Same boundary, plus fraud proofs / verifier |
| Fraud proofs | None | Required |
| Oracle model | Pyth-only fallback (Switchboard dead) | True dual-oracle + divergence + restricted mode |
| Oracle account binding | Not validated against market feeds | Must assert passed account == market feed |
| Switchboard On-Demand sigs | Not verified | Must verify |
| ER environment | Devnet only | N/A (no mainnet ER endpoint) |
| TWAP | Self-computed on-chain accumulator | Same |
