Skip to content

openSVM/percolator

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Percolator

A sharded perpetual exchange protocol for Solana, implementing the design from plan.md.

Architecture

Percolator consists of two main on-chain programs:

1. Router Program

The global coordinator managing collateral, portfolio margin, and cross-slab routing.

Program ID: RoutR1VdCpHqj89WEMJhb6TkGT9cPfr1rVjhM3e2YQr

State structures:

  • Vault - Collateral custody per asset mint
  • Escrow - Per (user, slab, mint) pledges with anti-replay nonces
  • Cap (Capability) - Time-limited, scoped debit authorization tokens (max 2 minutes TTL)
  • Portfolio - Cross-margin tracking with exposure aggregation across slabs
  • SlabRegistry - Governance-controlled registry with version validation

PDA Derivations:

  • Vault: [b"vault", mint]
  • Escrow: [b"escrow", user, slab, mint]
  • Capability: [b"cap", user, slab, mint, nonce_u64]
  • Portfolio: [b"portfolio", user]
  • Registry: [b"registry"]

2. Slab Program

LP-run perp engines with 10 MB state budget, fully self-contained matching and settlement.

Program ID: SLabZ6PsDLh2X6HzEoqxFDMqCVcJXDKCNEYuPzUvGPk

State structures:

  • SlabHeader - Metadata, risk params, anti-toxicity settings
  • Instrument - Contract specs, oracle prices, funding rates, book heads
  • Order - Price-time sorted orders with reservation tracking
  • Position - User positions with VWAP entry prices
  • Reservation - Reserve-commit two-phase execution state
  • Slice - Sub-order fragments locked during reservation
  • Trade - Ring buffer of executed trades
  • AggressorEntry - Anti-sandwich tracking per batch

PDA Derivations:

  • Slab State: [b"slab", market_id]
  • Authority: [b"authority", slab]

Key Features Implemented

✅ Memory Management

  • 10 MB budget strictly enforced at compile time
  • O(1) freelist-based allocation for all pools
  • Zero allocations after initialization
  • Pool sizes (tuned to fit within 10 MB):
    • Accounts: 5,000
    • Orders: 30,000
    • Positions: 30,000
    • Reservations: 4,000
    • Slices: 16,000
    • Trades: 10,000 (ring buffer)
    • Instruments: 32
    • DLP accounts: 100
    • Aggressor entries: 4,000

✅ Matching Engine

  • Price-time priority with strict FIFO at same price level
  • Reserve operation: Walk book, lock slices, calculate VWAP/worst price
  • Commit operation: Execute at captured maker prices
  • Cancel operation: Release reservations
  • Pending queue promotion: Non-DLP orders wait one batch epoch
  • Order book management: Insert, remove, promote with proper linking

✅ Risk Management

  • Local (slab) margin: IM/MM calculated per position
  • Global (router) margin: Cross-slab portfolio netting
  • Equity calculation with unrealized PnL and funding payments
  • Pre-trade margin checks
  • Liquidation detection

✅ Capability Security

  • Time-limited caps (max 2 minutes TTL)
  • Scoped to (user, slab, mint) triplet
  • Anti-replay with nonces
  • Remaining amount tracking
  • Automatic expiry checks

✅ Fixed-Point Math

  • 6-decimal precision for prices
  • VWAP calculations
  • PnL computation
  • Funding payment tracking
  • Margin calculations in basis points

✅ PDA Derivation Helpers

  • Router: Vault, Escrow, Capability, Portfolio, Registry PDAs
  • Slab: Slab State, Authority PDAs
  • Verification functions for account validation
  • Comprehensive seed management

✅ Instruction Dispatching

  • 6 instruction types: Reserve, Commit, Cancel, BatchOpen, Initialize, AddInstrument
  • Discriminator-based routing
  • Error handling for invalid instructions
  • Account validation framework ready

✅ Anti-Toxicity Infrastructure

  • Batch windows (batch_ms)
  • Delayed maker posting (pending → live promotion)
  • JIT penalty detection
  • Kill band parameters
  • Freeze levels configuration
  • Aggressor roundtrip guard (ARG) data structures

✅ BPF Build Support

  • Panic handlers for no_std builds
  • panic = "abort" configuration
  • Pinocchio integration for zero-dependency Solana programs

Test Coverage

53 tests passing across all packages:

percolator-common (27 tests)

  • ✅ VWAP calculations (single/multiple fills, zero quantity)
  • ✅ PnL calculations (long/short profit/loss, no change)
  • ✅ Funding payment calculations
  • ✅ Tick/lot alignment and rounding
  • ✅ Margin calculations (IM/MM, scaling with quantity/price)
  • ✅ Type defaults (Side, TimeInForce, MakerClass, OrderState, Order, Position)

percolator-router (7 tests)

  • ✅ Vault pledge/unpledge operations
  • ✅ Escrow credit/debit with nonce validation
  • ✅ Capability lifecycle (creation, usage, expiry)
  • ✅ Capability TTL capping (max 2 minutes)
  • ✅ Portfolio exposure tracking
  • ✅ Portfolio margin aggregation
  • ✅ Registry operations (add/validate slabs)

percolator-slab (19 tests)

  • ✅ Pool allocation/free operations
  • ✅ Pool capacity limits and reuse
  • ✅ Header validation and monotonic IDs
  • ✅ JIT penalty detection
  • ✅ Timestamp updates
  • ✅ Book sequence numbers
  • ✅ Reserve operation with max charge calculation
  • ✅ Margin requirement calculations
  • ✅ Slab size constraint (≤10 MB)

Note: PDA tests require Solana syscalls and are marked #[cfg(target_os = "solana")]. They will be tested in integration tests with Surfpool.

Building and Testing

Build

# Build all programs (libraries)
cargo build

# Build in release mode
cargo build --release

# Build specific package
cargo build --package percolator-slab

Testing

# Run all tests
cargo test

# Run only library tests
cargo test --lib

# Run tests for specific package
cargo test --package percolator-common
cargo test --package percolator-router
cargo test --package percolator-slab

# Run specific test
cargo test test_vwap_calculation

# Run tests with output
cargo test -- --nocapture

# Run tests in release mode (faster)
cargo test --release

Build for Solana BPF

# Install Solana toolchain (if not already installed)
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"

# Build BPF programs
cargo build-sbf

# Build specific program
cargo build-sbf --manifest-path programs/slab/Cargo.toml
cargo build-sbf --manifest-path programs/router/Cargo.toml

Surfpool Integration

Surfpool provides a local Solana test validator with mainnet state access for realistic integration testing.

Setup Surfpool

# Clone surfpool
git clone https://github.com/txtx/surfpool
cd surfpool

# Install dependencies
npm install

# Start local validator
npm run validator

Integration Test Structure

Create tests/integration/ directory for surfpool-based tests:

// tests/integration/test_reserve_commit.rs
use surfpool::prelude::*;
use percolator_slab::*;
use percolator_router::*;

#[surfpool::test]
async fn test_reserve_and_commit_flow() {
    // Initialize test environment
    let mut context = SurfpoolContext::new().await;

    // Deploy programs
    let router_program = context.deploy_program("percolator_router").await;
    let slab_program = context.deploy_program("percolator_slab").await;

    // Initialize slab state (10 MB account)
    let slab_pda = derive_slab_pda(b"BTC-PERP", &slab_program.id());
    context.create_account(&slab_pda, 10 * 1024 * 1024, &slab_program.id()).await;

    // Initialize router accounts
    let vault_pda = derive_vault_pda(&usdc_mint, &router_program.id());
    // ... setup vault, escrow, portfolio

    // Test reserve operation
    let reserve_ix = create_reserve_instruction(/* ... */);
    context.send_transaction(&[reserve_ix]).await.unwrap();

    // Verify reservation created
    let slab_state = context.get_account::<SlabState>(&slab_pda).await;
    assert!(slab_state.reservations.used() > 0);

    // Test commit operation
    let commit_ix = create_commit_instruction(/* ... */);
    context.send_transaction(&[commit_ix]).await.unwrap();

    // Verify trade executed
    assert_eq!(slab_state.trade_count, 1);
}

Running Integration Tests

# Start surfpool validator (terminal 1)
cd surfpool && npm run validator

# Run integration tests (terminal 2)
cargo test --test integration

# Run specific integration test
cargo test --test integration test_reserve_and_commit_flow

Example Test Scenarios

  1. Order Matching

    • Place limit orders on both sides
    • Execute market order
    • Verify VWAP calculation and position updates
  2. Reserve-Commit Flow

    • Reserve liquidity for aggregator order
    • Verify slices locked correctly
    • Commit at reserved prices
    • Check trades executed at expected prices
  3. Cross-Slab Portfolio

    • Open positions on multiple slabs
    • Verify router aggregates exposures
    • Check cross-margin calculation
  4. Capability Security

    • Create time-limited cap
    • Use cap to debit escrow
    • Verify expiry enforcement
  5. Anti-Toxicity

    • Post pending order
    • Open batch window
    • Verify promotion after epoch
    • Test JIT penalty application
  6. Liquidation

    • Open underwater position
    • Trigger liquidation
    • Verify position closure and PnL settlement

Design Invariants (from plan.md)

Safety:

  1. Slabs cannot access Router vaults directly
  2. Slabs can only debit via unexpired, correctly scoped Caps
  3. Total debits ≤ min(cap.remaining, escrow.balance)
  4. No cross-contamination: slab cannot move funds for (user', slab') ≠ (user, slab)

Matching:

  1. Price-time priority strictly maintained
  2. Reserved qty ≤ available qty always
  3. Book links acyclic and consistent
  4. Pending orders never match before promotion

Risk:

  1. IM monotone: increasing exposure increases margin
  2. Portfolio IM ≤ Σ slab IMs (convexity not double-counted)
  3. Liquidation triggers only when equity < MM

Anti-Toxicity:

  1. Kill band: reject if mark moved > threshold
  2. JIT penalty: DLP orders posted after batch_open get no rebate
  3. ARG: roundtrip trades within batch are taxed/clipped

Current Status

✅ Completed

  • Core data structures (Router & Slab)
  • Memory pools with O(1) freelists
  • Order book management (insert, remove, promote)
  • Reserve operation (lock slices, calculate VWAP)
  • Commit operation (execute trades at maker prices)
  • Risk calculations (equity, IM/MM, liquidation checks)
  • Capability system (time-limited scoped debits)
  • Fixed-point math utilities (VWAP, PnL, margin)
  • Compile-time size constraints (10 MB enforced)
  • PDA derivation helpers (all account types)
  • Instruction dispatching framework
  • BPF build support (panic handlers, no_std)
  • Comprehensive unit tests (53 tests passing)

🚧 In Progress

  • Integration tests with Surfpool
  • Property-based invariant testing
  • BPF deployment and CU benchmarks

📋 TODO

  • Anti-toxicity mechanism integration (kill band, ARG enforcement)
  • Funding rate updates (time-weighted calculations)
  • Liquidation execution (position closure, PnL settlement)
  • Router orchestration (multi-slab reserve/commit atomicity)
  • Instruction handler implementations (account validation, parsing)
  • Account initialization helpers
  • Client SDK (TypeScript/Rust)
  • CLI tools for LP operations
  • Documentation and examples

Technology Stack

  • Framework: Pinocchio v0.9.2 - Zero-dependency Solana SDK
  • Testing: Surfpool - Local Solana test validator with mainnet state
  • Language: Rust (no_std, zero allocations, panic = abort)

References

License

Apache-2.0


Status: Core infrastructure complete ✅ | 53 tests passing ✅ | Ready for integration testing 🚀

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Makefile 52.1%
  • Rust 45.9%
  • DTrace 2.0%