Reference implementation of a matcher program for the Percolator prediction market protocol on Solana.
The Percolator risk engine delegates trade pricing to external matcher programs via Solana CPI. Each LP (liquidity provider) registers a matcher program when they join a market. When a user submits a trade, the risk engine:
- Calls the LP's matcher program via CPI with the trade request
- Reads back the execution price and fill size from the matcher context account
- Validates the response against the ABI spec
- Applies the trade to the risk engine state (solvency checks, position updates)
This architecture allows LP operators to use any pricing strategy — AMMs, CLOBs, RFQ, or custom algorithms — while the risk engine handles all safety invariants.
percolator-matcher/
├── matcher-abi/ # Shared CPI ABI types (no_std, no dependencies)
│ └── src/lib.rs # MatcherRequest, MatcherReturn, wire format
├── matcher-program/ # Reference AMM matcher (Solana BPF program)
│ └── src/
│ ├── lib.rs # Entrypoint + account validation
│ └── amm.rs # Reference pricing engine
├── Cargo.toml # Workspace root
└── README.md
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 1 | tag |
Always 0x00 |
| 1 | 8 | req_id |
Request nonce (must echo back) |
| 9 | 2 | lp_idx |
LP index in the slab |
| 11 | 8 | lp_account_id |
Unique LP account ID |
| 19 | 8 | oracle_price_e6 |
Oracle price × 10⁶ |
| 27 | 16 | req_size |
Requested size (i128) |
| 43 | 24 | reserved |
Must be zero |
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | abi_version |
Must equal 1 |
| 4 | 4 | flags |
VALID, PARTIAL_OK, REJECTED |
| 8 | 8 | exec_price_e6 |
Execution price × 10⁶ |
| 16 | 16 | exec_size |
Fill size (i128) |
| 32 | 8 | req_id |
Echoed nonce |
| 40 | 8 | lp_account_id |
Echoed LP ID |
| 48 | 8 | oracle_price_e6 |
Echoed oracle price |
| 56 | 8 | reserved |
Must be zero |
The included reference matcher implements a simple oracle-anchored AMM:
- Longs pay
oracle × (1 + spread_bps / 10000) - Shorts receive
oracle × (1 - spread_bps / 10000) - Default spread: 30 bps (0.30%)
- Configurable via the matcher context account's user-data region (bytes 64+)
| Offset | Size | Field | Default |
|---|---|---|---|
| 64 | 2 | spread_bps |
30 (0.30%) |
| 66 | 2 | max_fill_pct |
10000 (100%) |
# Build both crates
cargo build
# Build for Solana BPF deployment
cargo build-sbf --manifest-path matcher-program/Cargo.toml
# Run tests
cargo test- Fork this repository
- Replace
matcher-program/src/amm.rswith your pricing logic - The
price_trade()function receives aMatcherRequestand must return aMatcherReturn - Deploy to Solana and register with an LP on a Percolator market
Key constraints enforced by the risk engine:
abi_versionmust equal1req_id,lp_account_id, andoracle_price_e6must be echoed back unchangedexec_sizemust not exceedreq_sizein absolute valueexec_sizemust have the same sign asreq_sizeexec_price_e6must be non-zero for accepted tradesreservedmust be zeroFLAG_VALIDmust be set for acceptance- Zero-fill requires
FLAG_PARTIAL_OK
| Repository | Description |
|---|---|
| percolator | Core risk engine crate (Rust) |
| percolator-prog | Solana on-chain program (wrapper) |
| percolator-stake | Insurance LP staking program |
| percolator-sdk | TypeScript SDK for client integration |
| percolator-ops | Operations dashboard |
| percolator-mobile | Solana Seeker mobile trading app |
| percolator-launch | Full-stack launch platform (monorepo) |
Apache 2.0 — see LICENSE.