Skip to content

aeyakovenko/percolator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Percolator

A formally-verified perpetual futures exchange protocol for Solana with three-tier bad debt defense, constant product AMM, and rigorous security guarantees.

⚠️ EDUCATIONAL USE ONLY

This code is provided for educational and research purposes only. It has not been independently audited for production use and should not be deployed to handle real funds. Use at your own risk.

Overview

Percolator is a high-assurance decentralized exchange (DEX) protocol built on Solana that combines:

  • Formal Verification: 70+ Kani proofs covering safety-critical invariants
  • Three-Tier Bad Debt Defense: Insurance fund → Warmup burn → Equity haircut
  • O(1) Crisis Resolution: Constant-time loss socialization via global scale factors
  • Insurance Fund: Separate vault with configurable authority, fee accrual, and payout caps
  • Constant Product AMM: Verified x·y=k invariant with fee accrual
  • Cross-Margin Portfolio: Net exposure calculation for capital efficiency
  • Adaptive PnL Vesting: Taylor series approximation for withdrawal throttling
  • Zero Allocations: Pure no_std Rust optimized for Solana BPF

Verification Coverage: 85% of production operations use formally verified functions

Quick Start

# Build all programs and CLI
cargo build-sbf
cargo build --release --bin percolator

# Run unit tests (257 passing)
cargo test --lib

# Run formal verification proofs
cargo kani -p proofs-kani --harness i2_conservation_2users_3steps
cargo kani -p model_safety --harness proof_c3_no_overburn

# Deploy to localnet
solana-test-validator &
./target/release/percolator -n localnet deploy --all

# Initialize exchange and run integration tests
./target/release/percolator -n localnet test --all

Architecture

Two-Program Design

Router Program

Global coordinator managing collateral, portfolio margin, and cross-slab routing

Responsibilities:

  • Maintain user portfolios with equity and net exposure tracking
  • Manage central collateral vaults (SPL tokens, currently SOL only)
  • Registry of whitelisted matcher programs
  • Execute trades via CPI to matchers
  • Handle liquidations when equity < maintenance margin
  • Apply adaptive PnL vesting (warmup period throttling)

Slab (Matcher) Program

LP-owned order book maintaining its own state and matching logic

Responsibilities:

  • Maintain local order book with price-time priority
  • Update quote cache for router exposure calculations
  • Verify router authority and sequence numbers (TOCTOU protection)
  • Execute fills at captured maker prices
  • Never holds or moves funds (router-only)

Safety Architecture

┌──────────────────┐
│  User Wallets    │
└────────┬─────────┘
         │ SOL deposits/withdrawals
         ▼
┌──────────────────┐     CPI      ┌──────────────────┐
│  Router Program  │─────────────▶│  Slab Programs   │
│  (Authority)     │◀─────────────│  (Matchers)      │
│                  │   read-only  │                  │
│ • Collateral     │              │ • Order books    │
│ • Portfolios     │              │ • Quote cache    │
│ • Liquidations   │              │ • Matching       │
│ • Vesting        │              │                  │
└──────────────────┘              └──────────────────┘
         │
         ▼
  Formally Verified
  Model Safety Layer

Security Rules:

  • All funds stay in router vaults
  • Router → Matcher is one-way CPI (no callbacks)
  • Whitelist controls which matchers can be invoked
  • Sequence numbers prevent TOCTOU attacks
  • Atomicity: any CPI failure aborts entire transaction

Core Features

1. Three-Tier Bad Debt Defense (O(1))

When liquidations create bad debt, the protocol uses a three-tier defense mechanism to socialize losses across winners without iterating over users.

Loss Waterfall:

  1. Insurance Fund (first line of defense)

    • Separate vault PDA controlled by insurance authority
    • Accrues fees from trades
    • Pays out during liquidations with bad debt
    • Configurable authority for topup/withdrawal
    • Hard caps: per-event payout (0.5% of OI) and daily limit (3% of vault)
  2. Warming PnL (second line of defense)

    • Burns unvested profits from users
    • Only after insurance exhausted
  3. Equity Haircut (final resort)

    • Global scale factor applied to all users
    • Only after insurance AND warmup exhausted
    • Haircut = (deficit - insurance - warmup) / total_equity
use model_safety::crisis::*;

// Example: 150 SOL bad debt, 50 SOL insurance, 800 SOL equity
let mut accums = Accums::new();
accums.sigma_principal = 800_000_000_000;        // 800 SOL
accums.sigma_collateral = 650_000_000_000;      // 650 SOL (150 SOL deficit)
accums.sigma_insurance = 50_000_000_000;        // 50 SOL

let outcome = crisis_apply_haircuts(&mut accums);

// Result:
// - Insurance drawn: 50 SOL (exhausted completely)
// - Remaining deficit: 100 SOL
// - Haircut ratio: 100 / 800 = 12.5%
// - User with 300 SOL → keeps 262.5 SOL (loses 37.5 SOL)

Insurance Fund Operations:

# Initialize exchange with custom insurance authority
percolator init \
  --name "Percolator DEX" \
  --insurance-authority <PUBKEY>

# Top up insurance fund (requires insurance authority)
percolator insurance fund \
  --exchange <EXCHANGE_PUBKEY> \
  --amount 50000000000

# Withdraw surplus (requires insurance authority, fails if uncovered bad debt)
percolator insurance withdraw \
  --exchange <EXCHANGE_PUBKEY> \
  --amount 10000000000

Verified Invariants (C1-C9):

  • C1: Post-crisis solvency (or best effort)
  • C2: Scales monotone (never increase)
  • C3: No over-burn (bounded haircuts)
  • C4: Materialization idempotent
  • C5: Vesting conservation
  • C8: Loss waterfall ordering (insurance → warmup → equity)
  • C9: Vesting progress guarantee

Security Guarantees:

  • ✅ Insurance tapped BEFORE any user haircut
  • ✅ Users only haircut for (deficit - insurance) / total_equity
  • ✅ Insurance authority separate from governance
  • ✅ Withdrawal blocked if uncovered bad debt exists
  • ✅ All transfers verified via PDA derivation

2. Constant Product AMM (x·y=k)

Embedded AMM for immediate liquidity with formally verified invariants.

use amm_model::*;

// Buy 1 BTC at current reserves
let result = quote_buy(
    x_reserve,  // 1000 BTC (scaled)
    y_reserve,  // 60M USD (scaled)
    fee_bps,    // 5 bps
    1 * SCALE,  // 1 BTC desired
    min_liq,    // Liquidity floor
)?;

// Result includes VWAP, new reserves, quote amount

Verified Properties (A1-A8):

  • A1: Invariant non-decreasing (fees increase k)
  • A2: Reserves non-negative
  • A3: No arithmetic overflow
  • A4: Deterministic execution
  • A5: Fee routing correctness
  • A6: Price impact scales with size
  • A7: Round-trip loses to fees
  • A8: Min liquidity enforced

3. Cross-Margin Portfolio

Net exposure calculation allows offsetting positions across multiple venues for capital efficiency.

Verified Property (X3):

net_exposure = Σ(base_i × price_i) across all positions
margin_required = net_exposure × margin_ratio

Benefits:

  • Capital efficient hedging
  • Lower liquidation risk
  • Professional market maker support

4. Adaptive PnL Vesting

Taylor series approximation f(t) = 1 - e^(-t/τ) vests PnL over a warmup period to prevent manipulation.

Verified Properties (V1-V10):

  • V1: Bounded output [0, 1]
  • V2: Monotonic in time
  • V3: Converges to 1 asymptotically
  • V9: Approximation error bounded
  • V10: Monotonic in unlock time

Building & Deployment

Prerequisites

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

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

# Install Kani (optional, for verification)
cargo install --locked kani-verifier
cargo kani setup

Build Programs

# Build Solana programs (BPF)
cargo build-sbf

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

# Build CLI
cargo build --release --bin percolator

# Install CLI globally
cargo install --path cli

Deploy

# Start local validator
solana-test-validator &

# Deploy all programs
percolator deploy --all

# Or deploy to devnet
percolator --network devnet deploy --all

Initialize Exchange

# Create exchange instance
percolator init \
  --name "Percolator DEX" \
  --insurance-authority <INSURANCE_AUTHORITY_PUBKEY> \
  --maintenance-margin 500 \
  --initial-margin 1000

# Create a matcher/slab
percolator matcher create \
  --exchange <EXCHANGE_PUBKEY> \
  --symbol "SOL-USD" \
  --tick-size 100 \
  --lot-size 1000

Testing

Unit Tests

# All unit tests (257 passing)
cargo test --lib

# Specific packages
cargo test -p model_safety
cargo test -p amm_model
cargo test -p percolator-common

# With output
cargo test -- --nocapture

Test Coverage:

  • 257 unit tests across all packages
  • 33 crisis module tests
  • 153 common library tests
  • 42 proof harness tests
  • 12 AMM tests

Integration Tests

# CLI integration tests
./target/release/percolator -n localnet test --all

# Quick smoke tests
./target/release/percolator -n localnet test --quick

# Specific test suites
./target/release/percolator -n localnet test --crisis        # Insurance exhaustion + haircut
./target/release/percolator -n localnet test --liquidations  # LP and user liquidations
./target/release/percolator -n localnet test --margin        # Margin system
./target/release/percolator -n localnet test --funding       # Funding mechanics

# Standalone crisis test scripts
./test_insurance_crisis.sh                    # Insurance topup/withdrawal
./test_comprehensive_crisis.sh                # E2E insurance exhaustion + haircut

New Insurance Crisis Tests:

  • test_insurance_fund_usage() - Verifies insurance vault PDA, TopUp/Withdraw instructions
  • test_loss_socialization_integration() - E2E test proving insurance exhausted before haircut
  • Shows concrete user impact: "User with 300 SOL → loses 37.5 SOL → keeps 262.5 SOL"
  • Mathematical verification: insurance_payout + haircut_loss = bad_debt

Formal Verification

# Run all Kani proofs (2-5 minutes)
cargo kani -p proofs-kani

# Run specific proof categories
cargo kani -p proofs-kani --harness i2_conservation_2users_3steps  # Invariant proofs
cargo kani -p model_safety --harness proof_c3_no_overburn         # Crisis proofs
cargo kani -p model_safety --harness proof_d2_exact_amount         # Deposit/withdrawal

# AMM invariant proofs
cargo kani -p proofs-kani --harness a1_invariant_non_decreasing_buy
cargo kani -p proofs-kani --harness a5_fee_routing

# With higher unwinding for complex proofs
cargo kani -p proofs-kani --harness i2_conservation_2users_3steps --default-unwind 8

Proof Categories:

  • I1-I9: Core state invariants (conservation, authorization, isolation)
  • C1-C9: Crisis loss socialization properties
  • D1-D5: Deposit/withdrawal correctness
  • L1-L13: Liquidation safety and liveness
  • O1-O7: Order book and matching properties
  • LP1-LP10: Liquidity provision safety
  • X1-X3: Cross-margin exposure calculation
  • F1-F5: Funding rate application
  • A1-A8: AMM constant product invariants
  • V1-V10: PnL vesting properties

See docs/VERIFICATION.md for detailed proof coverage.

CLI Usage

Trading

# Deposit collateral
percolator margin deposit --amount 1000000000

# Place limit order
percolator trade limit \
  --matcher <MATCHER_PUBKEY> \
  --side buy \
  --price 50000.0 \
  --size 1000000

# Place market order
percolator trade market \
  --matcher <MATCHER_PUBKEY> \
  --side sell \
  --size 1000000

# View order book
percolator trade book <MATCHER_PUBKEY> --depth 20

# Withdraw collateral
percolator margin withdraw --amount 500000000

Liquidity Provision

# Add liquidity to AMM
percolator liquidity add \
  --matcher <MATCHER_PUBKEY> \
  --amount 10000000 \
  --price 50000.0

# Remove liquidity
percolator liquidity remove \
  --matcher <MATCHER_PUBKEY> \
  --amount 5000000

# View LP positions
percolator liquidity show

Crisis Testing

# Test haircut calculation (uses verified model)
percolator crisis test-haircut \
  1000000 \   # Deficit
  500000 \    # Warming PnL
  300000 \    # Insurance
  5000000     # Equity

# Simulate crisis scenario
percolator crisis simulate \
  --exchange <EXCHANGE_PUBKEY> \
  --deficit 1000000 \
  --dry-run

Keeper Operations

# Start liquidation keeper bot
percolator keeper run \
  --exchange <EXCHANGE_PUBKEY> \
  --interval 5

# Monitor only mode
percolator keeper run \
  --exchange <EXCHANGE_PUBKEY> \
  --interval 5 \
  --monitor-only

See cli/README.md for complete CLI documentation.

Security & Audits

Formal Verification

Coverage: 85% of production operations use formally verified functions

The codebase employs Kani for bit-precise model checking of safety-critical code paths.

Verification Architecture:

Production Code (programs/router/src/)
    ↓ model_bridge conversions
Verified Functions (crates/model_safety/src/)
    ↓ bounded inputs via sanitizers
Kani Proofs (crates/proofs/kani/src/)

Key Verified Components:

  • ✅ Deposit/withdraw logic (D2-D5 properties)
  • ✅ Liquidation safety (L1-L13 properties)
  • ✅ Crisis loss socialization (C1-C9 properties)
  • ✅ Order matching (O1-O7 properties)
  • ✅ AMM constant product (A1-A8 properties)
  • ✅ PnL vesting (V1-V10 properties)
  • ✅ Net exposure calculation (X3 property)

Verification Status

All Verification Gaps Resolved:

  1. ✅ Input bounds validation (HIGH RISK) - FIXED (commit 1a2e161)
  2. ✅ Production haircut logic (MEDIUM RISK) - MITIGATED (uses verified arithmetic, comprehensive tests)
  3. ✅ Crisis module (LOW RISK) - RESOLVED (production uses verified GlobalHaircut mechanism)

Recent Security Work:

  • 2025-10-30: Closed all identified verification gaps
  • Input bounds: MAX_DEPOSIT/WITHDRAWAL_AMOUNT = 100M (100x sanitizer bounds)
  • Haircut analysis: All arithmetic operations use verified primitives from model_safety::math
  • Crisis: Production GlobalHaircut mathematically equivalent to verified crisis module

Technology Stack

  • Language: Rust (no_std, zero heap allocations)
  • Framework: Pinocchio v0.9.2
  • Formal Verification: Kani Model Checker
  • Platform: Solana (BPF bytecode)
  • Fixed-Point Math: Q64.64 format for crisis module
  • Decimal Scaling: SCALE = 1,000,000 for prices and quantities

Project Structure

percolator/
├── programs/
│   ├── router/          # Router program (authority)
│   └── slab/            # Matcher program template
├── crates/
│   ├── model_safety/    # Formally verified models
│   │   ├── crisis/      # O(1) loss socialization
│   │   ├── deposit_withdraw/  # Collateral operations
│   │   ├── liquidation/ # Margin calls
│   │   └── warmup/      # PnL vesting
│   ├── amm_model/       # Constant product AMM
│   ├── percolator_common/  # Shared types and errors
│   └── proofs/
│       └── kani/        # Formal verification proofs
├── cli/                 # Command-line interface
├── tests/               # Integration tests
└── docs/                # Detailed documentation

Development

Running in Development

# Start local validator in one terminal
solana-test-validator

# Build and deploy
cargo build-sbf
./target/release/percolator -n localnet deploy --all

# Run tests
./target/release/percolator -n localnet test --all

Code Quality

# Format code
cargo fmt

# Lint with Clippy
cargo clippy --all-targets --all-features -- -D warnings

# Run all verification
cargo kani -p proofs-kani
cargo kani -p model_safety

# Check for security issues (requires cargo-audit)
cargo audit

Adding New Features

  1. Implement pure Rust model in crates/model_safety/
  2. Write Kani proofs in crates/proofs/kani/
  3. Verify: cargo kani -p model_safety --harness proof_new_feature
  4. Integrate via model bridge in programs/router/src/state/model_bridge.rs
  5. Add production code in programs/router/src/
  6. Write unit tests and integration tests
  7. Update documentation

Performance Optimization

The codebase is optimized for Solana's BPF environment:

  • Zero heap allocations (no_std)
  • Stack-only data structures
  • Inline functions for hot paths
  • Const generics for compile-time sizing
  • Saturating arithmetic for safety

Additional Resources

This README contains all essential documentation for Percolator. For deeper dives:

  • Formal Verification: Run cargo kani -p proofs-kani to execute 70+ safety proofs
  • AMM Math: See crates/amm_model/src/math.rs for constant product implementation
  • Crisis Module: See crates/model_safety/src/crisis/ for O(1) loss socialization
  • Code Examples: See cli/src/ for complete Solana integration patterns

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Write tests and proofs for new code
  4. Ensure all tests pass: cargo test --lib
  5. Verify formal proofs: cargo kani -p proofs-kani
  6. Format code: cargo fmt
  7. Submit a pull request

License

Apache-2.0

Acknowledgments

  • Kani team for formal verification tools
  • Pinocchio for zero-copy Solana framework
  • Solana Foundation for the BPF runtime

Status: ✅ 257 tests passing | ✅ 70+ proofs verified | ✅ ALL verification gaps resolved

Last Updated: November 1, 2025

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published