Security

Perk handles other people's money. The security work reflects that responsibility. This document covers what we did, how, and why.

All code is open source under the MIT license: github.com/kai-builds-ai/perk-protocol-public


Formal Verification

The protocol's arithmetic and state transitions are verified using Kani, a Rust model checker. Kani exhaustively explores all possible inputs within defined bounds — it doesn't sample, it proves.

Proofs cover seven categories:

CategoryWhat It Verifies
ArithmeticFloor/ceil division, mul/div, signed operations, fee math — no overflow, no rounding errors that favor the wrong party
Safety / ConservationDeposits, withdrawals, trades, and liquidations conserve vault balance. Funding cannot mint tokens. Capital never goes negative.
InvariantsState machine properties hold after every operation. Aggregates (total capital, total PnL) stay consistent.
LivenessThe system makes progress — resets finalize, bankruptcy paths route correctly, dust is cleared
FundingFunding rate computation, clamping, settlement, K-delta correctness
Margin & LiquidationEquity calculations, maintenance/initial margin checks, liquidation deficit computation
Engine functionsSettlement, profit conversion, OI tracking — end-to-end correctness

These proofs run against the actual Rust code in engine/, not a simplified model.


Fuzz Testing

Adversarial fuzz testing generates random sequences of operations (deposits, trades, liquidations, funding cranks, oracle updates) and checks invariants after each:

  • Vault balance ≥ sum of all deposits minus all withdrawals
  • No user's deposited capital goes negative
  • Aggregate tracking (total OI, total capital, total PnL) stays consistent
  • No panics, no overflows, no undefined behavior

Audit Methodology

Seven internal review rounds across the on-chain program, SDK, cranker, and frontend. These are development team reviews, not independent third-party audits:

RoundScopeMethod
1On-chain engine (vAMM, risk, funding)Line-by-line review, invariant analysis
2Instructions (all user-facing)Attack surface mapping, input validation
3SDK + crankerIntegration correctness, serialization, error handling
4Red teamAdversarial attack scenarios against the full stack
5PerkOracle (on-chain + cranker)Oracle-specific attack vectors
6FrontendTransaction construction, state management, UX safety
7Post-integrationFull system review after all components wired together

Each round follows the same process: review → findings → fixes → re-review → sign-off.

Red Team Scenarios

The red team audit specifically tested:

  • Flash loan → oracle manipulation → profit extraction
  • Stale price exploitation (oracle goes down, attacker trades at favorable stale price)
  • Liquidation manipulation via oracle sandwich
  • vAMM peg update exploitation
  • Dust deposit/withdrawal attacks
  • Overflow in position math at extreme values
  • Trigger order gaming (front-running execution)

The Percolator

Perk's risk engine is a full port of Anatoly Yakovenko's Percolator — the risk engine designed by Solana's co-founder for perpetual futures.

During the porting process, we identified and reported an issue in the original Percolator codebase (Issue #22): the liquidation path didn't correctly reset the warmup slope, which could allow a position to retain stale warmup state after liquidation. This was part of standard due diligence when adapting the code to our environment.

The fix is implemented in Perk's engine and verified by Kani proofs.


Safety Rails

Circuit Breaker

If the oracle detects abnormal price movement (deviation from EMA exceeding the configured threshold), the oracle rejects the update. This effectively pauses the market — no trades execute on prices that look wrong.

The circuit breaker is configurable per oracle:

  • Disabled (0) for memecoins where extreme moves are normal
  • 5% for major tokens
  • 1% for stablecoins

Oracle Security

Multiple layers protect against oracle manipulation:

LayerProtection
Multi-source aggregationMedian of 2+ independent sources (Jupiter, Birdeye)
Outlier rejectionSources deviating beyond the configured threshold (default: 1%) from median are excluded
Staleness checkPrices older than 15 seconds are rejected
Confidence intervalHigh-spread prices are flagged
Rate limitingMax 1 oracle update per Solana slot
Price bandingConfigurable per-update rate-of-change limits
Sliding window3x band over 50-slot window catches sustained manipulation
Freeze mechanismAdmin can immediately halt any oracle
Fail-closedOracle failure → market pause. Never use a bad price.

Insurance Fund

Each market has an independent insurance fund:

  • Funded by 50% of liquidation fees
  • Absorbs bad debt before socialization kicks in
  • Epoch-capped at 30% of balance per epoch (prevents drainage)
  • Dynamic floor — insurance can't be fully depleted in a single event

Warmup Window

New unrealized profit enters a warmup period (~400 seconds) before it becomes withdrawable. This prevents:

  • Oracle manipulation → instant profit extraction
  • Flash loan attacks that create and cash out paper profit in one block

Global Pause

The protocol admin can emergency-pause the entire protocol. When paused:

  • No new positions, no deposits
  • Withdrawals and position closes still work (users can always exit)

This is a last-resort safety mechanism, not a regular operational tool.


Key Separation

No single wallet controls everything:

WalletCan DoCannot Do
AdminPause protocol, freeze oracles, update configAccess vaults, post prices
Oracle crankerPost price updatesAccess vaults, pause protocol, admin actions
Liquidation crankerExecute liquidations, crank fundingAccess vaults, post prices, admin actions
Fee collectionReceive protocol feesAny protocol actions

Compromise of the oracle cranker means bad prices (detectable, freezable) but not stolen funds. Compromise of the liquidation cranker means nothing — it has no special privileges beyond what any user has.


Open Source

All code is public, all code is auditable:

  • On-chain program: Rust/Anchor, deployed from verified build
  • SDK: TypeScript, published as perk-protocol
  • Cranker: TypeScript, included in the repository
  • Frontend: Next.js, source available

Repository: github.com/kai-builds-ai/perk-protocol-public

License: MIT


On-Chain Verification

The deployed program is verified via OtterSec:

FieldValue
Program3L72e4b8wKJ8ReMpLUeXxVNrRGpiK6m4VYxeSnecpNW2
Build toolsolana-verify (Docker reproducible build)
Status✅ Verified
Anchor0.32.1
Solana2.3.0

Anyone can independently verify the deployed bytecode matches the public source code using solana-verify.