Skip to main content
Solana programs are compiled binaries running on-chain. When you interact with a protocol, you’re trusting that the deployed binary matches the open-source code you can read. Most protocols ask you to take their word for it. We don’t. Every layer of the Percolator protocol is independently verifiable:
1

Verifiable builds

The exact same Docker container and locked dependencies produce the exact same binary every time. CI publishes the SHA-256 hash — you can reproduce it yourself.
2

On-chain comparison

Dump the deployed program from Solana, hash it, and compare. If the hashes match, the code you read is the code that runs.
3

SDK audit

The TypeScript SDK that builds your transactions has been verified byte-for-byte against the Rust source — every instruction tag, every account ordering, every encoding.
4

Formal verification

143 Kani model-checking proofs verify the risk engine’s safety invariants mathematically, not just by testing.

What is an SBF Build?

Solana programs compile to SBF (Solana Bytecode Format) — a variant of eBPF designed for the Solana runtime. The compiled .so file is what gets deployed on-chain and executed by validators. The problem: Rust builds are not deterministic across machines. Different OS versions, toolchains, or dependency resolution can produce different binaries from the same source code. This means you can’t just cargo build on your laptop and compare. The solution: verifiable builds use a pinned Docker image with an exact Rust version, exact Solana tools, and a locked Cargo.lock to guarantee the same source always produces the same bytes. If the hashes match, the deployed program is byte-for-byte identical to the open-source code.

Verified Builds

Percolator Program

Latest CI run — click to see build logs and artifact hash

Matcher Program

Latest CI run — click to see build logs and artifact hash

Percolator Program

Repositorypurpletrade/percolator-prog
Docker imagesolanafoundation/solana-verifiable-build:1.18.9
Rust1.75.0
Branchverifiable-build
Artifactpercolator-prog-sbf-1.18.9 (72.5 KB)
SHA-256bf68c6359fd0ecb2cf245c19ee0ccf10fcdb42b54f4c81d6772d10e1586b5cad

Matcher Program

Repositorypurpletrade/percolator-match
Docker imagesolanafoundation/solana-verifiable-build:2.3.0
Branchverifiable-build
Artifactpercolator-match-sbf-2.3.0 (12.6 KB)
SHA-256a2d5aef57b91b6895079a138f849471bd58b9fd0ae4a643f1ce069c794dba073

What the CI Does

Each verified build workflow runs these steps inside GitHub Actions:
  1. Checkout — Clone the verifiable-build branch with full history
  2. Docker build — Spin up solanafoundation/solana-verifiable-build (pinned version), install the exact Rust toolchain
  3. Compilecargo-build-sbf --force-tools-install --sbf-out-dir target/deploy -- --locked ensures the Cargo.lock is respected exactly
  4. Hashshasum -a 256 produces the deterministic SHA-256 of the .so binary
  5. Upload — The artifact (.so + .sha256) is published to GitHub Actions for anyone to download
The --locked flag is critical — it prevents Cargo from resolving newer dependency versions that could change the output.

Verify It Yourself

# Clone and build the percolator program
git clone https://github.com/purpletrade/percolator-prog
cd percolator-prog && git checkout verifiable-build

docker run --rm -v $(pwd):/work -w /work --platform linux/amd64 \
  solanafoundation/solana-verifiable-build:1.18.9 \
  cargo-build-sbf --force-tools-install --sbf-out-dir target/deploy -- --locked

shasum -a 256 target/deploy/percolator_prog.so
# Expected: bf68c6359fd0ecb2cf245c19ee0ccf10fcdb42b54f4c81d6772d10e1586b5cad
# Then compare against the on-chain binary
solana program dump <PROGRAM_ID> onchain.so
shasum -a 256 onchain.so
# If these match → the deployed code IS the open-source code
A scripts/verify.sh helper in the repo does this in one command.
You can also use solana-verify for automated verification: solana-verify verify-from-repo --program-id <ID> --url https://github.com/purpletrade/percolator-prog

Upstream Transparency

Both repositories include an upstream-sync.yml CI workflow that checks for divergence from Anatoly Yakovenko’s original source. Every change we make is visible in the commit history:

Security Metadata

Both programs embed solana-security-txt in the on-chain binary — contact info, source repo, and security policy discoverable directly from explorers. Programs are verified on OtterSec and display green verification badges on Solscan:

Formal Verification

The risk engine (purpletrade/percolator) is verified using Kani model checking143 proofs that mathematically verify safety invariants:

Conservation

No value created from nothing. Deposits + insurance = withdrawable capital + positions.

Isolation

No cross-account contagion. One account’s state cannot corrupt another’s.

No Over-Withdrawal

Users cannot extract more than deposited capital plus earned PnL.
CategoryProofsWhat it verifies
Matcher ABI validation13Rejects malformed matcher responses
Owner/signer enforcement5Only account owner can act, admin burn disables ops
CPI identity binding2LP matcher program/context must match registration
Edge cases & boundaries100+Overflow, sign, i128::MIN, reserved field checks

SDK Source Audit

The TypeScript SDK at src/lib/percolator/ has been verified instruction-by-instruction against the Rust source at aeyakovenko/percolator-prog.
CategoryVerifiedStatus
Instruction tags21/21Verified
Data encoding21/21Verified
Account orderings21/21Verified
PDA derivation2/2Verified
Error codes25/25Verified
Slab layout4/4 structsVerified
TagSDK constantRust instruction
0IX_TAG.InitMarketInitMarket
1IX_TAG.InitUserInitUser
2IX_TAG.InitLPInitLP
3IX_TAG.DepositCollateralDepositCollateral
4IX_TAG.WithdrawCollateralWithdrawCollateral
5IX_TAG.TradeCpiTradeCpi
6IX_TAG.KeeperCrankKeeperCrank
7IX_TAG.PushOraclePricePushOraclePrice
8IX_TAG.SetOracleAuthoritySetOracleAuthority
9IX_TAG.UpdateAdminUpdateAdmin
10IX_TAG.UpdateConfigUpdateConfig
11IX_TAG.CloseAccountCloseAccount
12IX_TAG.SetMatcherSetMatcher
13IX_TAG.CloseSlabCloseSlab
14IX_TAG.SettleFundingSettleFunding
15IX_TAG.LiquidateLiquidate
16IX_TAG.UpdateFundingRateUpdateFundingRate
17IX_TAG.ReallocSlabReallocSlab
18IX_TAG.SetFeeReceiverSetFeeReceiver
19IX_TAG.WithdrawFeesWithdrawFees
20IX_TAG.ToggleTradingToggleTrading
Tag 21 (AdminForceCloseAccount) exists in the Rust source but is intentionally omitted from the SDK as it is an admin-only emergency function.
Every instruction’s data payload verified against the Rust decode functions. All little-endian with exact byte offsets:
  • u8, u16, u32, u64: Standard LE integers
  • i64, i128: Signed integers (twos complement, LE)
  • u128: 16-byte LE (prices in PushOraclePrice)
  • [u8; 32]: Raw pubkey bytes (UpdateAdmin, SetOracleAuthority)
Each instruction’s accounts verified against process_instruction in percolator.rs. Example for TradeCpi:
[0] slab (writable)
[1] user (signer)
[2] vault_authority (PDA)
[3] token_vault (writable)
[4] user_token_account (writable)
[5] oracle_account
[6] token_program
[7] matcher_program
[8] lp_pda
All 21 instruction account orderings match.
Vault authority:
Rust:   Pubkey::find_program_address(&[b"vault", slab_key.as_ref()], program_id)
SDK:    PublicKey.findProgramAddressSync([Buffer.from("vault"), slab.toBuffer()], programId)
LP PDA:
Rust:   find_program_address(&[b"lp", slab.key.as_ref(), &lp_idx.to_le_bytes()], program_id)
SDK:    PublicKey.findProgramAddressSync([Buffer.from("lp"), slab.toBuffer(), idxBuf], programId)
        where idxBuf = u16 little-endian
CodeErrorMapped
0InvalidInstructionYes
1InvalidSlabMagicYes
2InvalidSlabVersionYes
3InvalidSlabBumpYes
4InvalidSlabLenYes
5SlabFullYes
6AccountNotFoundYes
7AccountAlreadyExistsYes
8InsufficientCollateralYes
9InsufficientMarginYes
10MaxLeverageExceededYes
11InvalidOraclePriceYes
12OracleStaleYes
13TradingPausedYes
14UnauthorizedYes
15EngineUnauthorizedYes
16–25(various)Yes
26InvalidConfigParamOmitted (admin-only)
27HyperpTradeNoCpiDisabledOmitted (internal)
StructOffsetSizeMatch
SlabHeader072 bytesYes
MarketConfig72320 bytesYes
EngineState392VariableYes
Account slotsAfter engine240 bytes eachYes
Checked against #[repr(C)] layout rules with alignment and padding.

Methodology

  1. Read the complete Rust source (percolator.rs, ~4,400 lines)
  2. Extract every instruction’s decode logic, account ordering, and data format
  3. Compare line-by-line against the TypeScript SDK (instructions.ts, accounts.ts, slab.ts, pda.ts, errors.ts)
  4. Confirm byte-level compatibility for all encoded data

Source References

percolator-prog

Core program — verified builds, security.txt, formal proofs

percolator-match

LP matcher — verified builds, vAMM implementation

Original source

Canonical source by Anatoly Yakovenko

Risk engine

Formally verified library — 143 Kani proofs