percli
CLI toolkit for the Percolator risk engine — simulate, test, and operate perp markets on Solana.
This software has not been audited by a third-party security firm. Use at your own risk. The authors accept no liability for loss of funds.
Install
Pre-built binary (Linux, macOS):
|
From source (requires Rust):
With on-chain Solana commands:
With live Pyth oracle feeds:
Pre-built binaries for all platforms are also available on the releases page.
Quick Start
No setup required — generate a scenario, run it, and inspect the output:
# Generate a starter scenario
# Run the simulation
# Run with verbose deltas
# Output as JSON (for scripts and pipelines)
Commands
| Command | Description | Example |
|---|---|---|
sim |
Run a TOML scenario file | percli sim scenario.toml --verbose |
step |
Execute a single operation on saved state | percli step --state engine.json deposit alice 100000 |
query |
Read-only queries on engine state | percli query --state engine.json vault |
inspect |
Validate a scenario without running it | percli inspect scenario.toml |
init |
Generate a scenario template | percli init --template liquidation |
agent |
Run an external process as a trading agent | percli agent run --config agent.toml |
chain |
Interact with on-chain Solana program | percli chain deploy |
keeper |
Auto-crank and auto-liquidate on-chain | percli keeper --interval 10 |
completions |
Generate shell completions | percli completions zsh |
Simulation Options
# Step-by-step — print state after each operation
# Override parameters without editing the file
# Disable conservation checks
Interactive State Management
Build up engine state incrementally with step and inspect it with query:
# Initialize state with deposits
# Update oracle and execute a trade
# Query the result
Available query metrics: summary, vault, haircut, conservation, accounts, equity, margin, position.
Scenarios
Scenarios are TOML files that define market parameters and a sequence of operations:
[]
= "Basic Two-Party Trade"
[]
= 500 # 5%
= 1000 # 10%
[]
= 1000
[[]]
= "deposit"
= "alice"
= 100_000
[[]]
= "trade"
= "alice"
= "bob"
= 50
= 1000
[[]]
= "assert"
= "conservation"
Bundled Scenarios
| Scenario | What it tests |
|---|---|
basic-trade.toml |
Two-party trade, 10% price move, equity changes |
liquidation-cascade.toml |
High-leverage position, 50% crash, cascading liquidation |
haircut-stress.toml |
Multiple traders, extreme price move, haircut activation |
insurance-depletion.toml |
Catastrophic loss, insurance absorption, conservation proof |
funding-drift.toml |
Funding rate impact over 500 slots with steady price |
Run all bundled scenarios:
for; do ; done
Agent Mode
Spawn any process (Python, Node, Bash) as a trading agent. percli feeds it NDJSON tick data with full engine snapshots; the agent responds with actions.
# Generate a starter agent config
# Run the agent
# Dry run — validate config without spawning the process
Example: Liquidation Bot (Python)
=
break
continue
=
Protocol
Agents communicate via NDJSON on stdin/stdout:
- Init —
{"type": "init", "params": {...}, "accounts": [...], "snapshot": {...}} - Tick (per price update) —
{"type": "tick", "tick": 1, "oracle_price": 1050, "snapshot": {...}} - Response (agent → percli) —
{"actions": [{"op": "liquidate", "account": "alice"}, ...]} - Done —
{"type": "done", "ticks": 100, "elapsed_s": 1.2}
Available actions: deposit, withdraw, trade, liquidate, settle, noop.
Price feeds can be inline TOML arrays, CSV files, stdin, or live Pyth oracle streams (requires --features pyth).
Pyth Live Feed
Stream real-time prices from Pyth Network into agent mode:
[]
= "pyth"
= "https://api.mainnet-beta.solana.com"
= "H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG" # SOL/USD
= 2000
= 500
See examples/agent-pyth.toml for a complete config.
On-Chain (Solana)
The chain feature adds commands for interacting with a deployed Percolator market on Solana.
Deposits and withdrawals move real SPL tokens (e.g. USDC) between user wallets and a PDA-controlled vault. The crank instruction reads oracle prices directly from a Pyth Network price feed account on-chain.
# Deploy a new market
# Deposit (SPL token transfer from user to vault)
# Trade between two accounts
# Crank — reads price from Pyth oracle on-chain
# Withdraw (SPL token transfer from vault to user, margin-checked)
# Liquidate and settle
# Query on-chain state
Global options: --rpc <url>, --keypair <path>, --program <pubkey>.
The on-chain program (percli-program) is an Anchor 1.0 program that wraps the Percolator engine in a Solana PDA. See Anchor.toml for deployment config.
Keeper Bot
The keeper command watches an on-chain market, cranks Pyth oracle updates, and liquidates undercollateralized accounts:
# Keeper with Pyth oracle feed (required)
The keeper loops: read market state, submit crank tx (which reads the Pyth price on-chain), liquidate anyone below maintenance margin, sleep, repeat.
Requires --features chain.
Playground
Try percli in your browser at kamiyoai.github.io/percli — no install required. Edit TOML scenarios and see simulation results instantly via WebAssembly.
What is Percolator?
Percolator is a risk engine for perpetual futures that replaces ADL queues with two deterministic mechanisms:
H (haircut ratio) — When the vault is stressed, every profitable account sees the same pro-rata scaling on withdrawable profit. No queue priority, no first-come advantage. Capital deposits are always protected.
A/K (side indices) — When a leveraged account goes bankrupt, the opposing side absorbs the residual through global position scaling (A) and PnL socialization (K). No account is singled out. Settlement is O(1) per account.
Together: no user can withdraw more than exists, no user is singled out for forced closure, and markets always self-heal through a deterministic three-phase reset — no admin intervention, no governance votes.
See Tarun Chitra, Autodeleveraging: Impossibilities and Optimization for the theoretical foundation.
Architecture
kamiyoai/percli (workspace)
├── src/ # percolator — upstream risk engine (no-std, formally verified)
├── crates/
│ ├── percli-core/ # engine wrapper, scenario runner, agent protocol
│ ├── percli/ # CLI binary (sim, step, query, agent, chain)
│ ├── percli-chain/ # Solana RPC client commands
│ ├── percli-program/ # Anchor on-chain program
│ └── percli-wasm/ # WebAssembly build
├── web/ # browser playground (GitHub Pages)
├── scenarios/ # bundled TOML test scenarios
├── examples/ # agent examples (Python, Bash)
├── tests/ # upstream Kani formal verification proofs
└── scripts/ # development utilities
Security
The core risk engine (percolator) is formally verified with Kani proofs and continuously fuzz-tested with proptest. All arithmetic uses checked operations; #![forbid(unsafe_code)] is enforced in the engine crate.
The on-chain Anchor program validates:
- Account ownership — market accounts must be owned by the program
- Oracle authenticity — price feeds must be owned by the Pyth v2 program
- Discriminator + size checks — all market accounts are validated before access
- SPL token constraints — mint, owner, and vault PDA seeds are verified by Anchor
- Checked price conversion — Pyth exponent handling uses checked arithmetic with bounded exponent range
This software has not been audited by a third-party security firm. If you discover a vulnerability, please report it privately via GitHub Security Advisories rather than opening a public issue.
Contributing
See CONTRIBUTING.md for development setup, testing, and PR guidelines.
License
Apache-2.0 OR MIT — see LICENSE.