SPECTRE 50-Protocol Audit Corpus — Solana Foundation Hackathon
Date: 2026-05-08
Tooling: pinpoint-cli spectre scan + pinpoint-cli spectre scan-cross, commit b9825600
Audience: Solana Foundation hackathon judges
TL;DR
SPECTRE is a static analysis platform for Solana smart contracts. This corpus pass scans 30 program crates across 24 of the largest Solana protocols, producing 2,581 architectural findings with confidence-tiered classification. Three capabilities no other Solana scanner ships today:
Cross-program analysis with provenance and confidence-tagged links. SPECTRE's
scan-crossingests N program crates, resolves CPIs via a hand-curated 48-program registry plus a TS↔Anchor cross-language analysis, and runs cross-program rules across the unified surface. 21 TypeScript-to-Anchor links resolved on the internal-bench workspace alone (288 TS source files → 1 Anchor program). Audit firms structurally cannot produce this signal because they audit one program at a time.A 36-rule architectural pattern catalogue mined from real published audit findings. Every rule is grounded in a specific bug class from V12 (Zellic), OtterSec, or Certora published reports — AUTH-100/110/120, GOV-001/002, ORC-002, ACC-010..013, ACC-021, CLOSE-070/080, CPI-003/030/040, TOK-001/002/010/022/023, META-001/002, EVT-001, INV-002/003, MINT-001, NONCE-002, CONFIG-010. Mined, not synthetic.
False-positive engineering validated against top-tier audited code. Five-program Kamino triage shipped surgical suppressors (PDA seed-binding, helper-mediated validation,
Box<InterfaceAccount<TokenAccount>>PDA-bound exemption,<noun>_cachedpropose-staging recognition) that close every architectural FP on Kamino while preserving rule signal on less-audited code.
What's innovative about SPECTRE
1. Cross-program analysis is a real R&D moat
Most Solana audit-class losses since 2022 sit at the boundary between programs. Saber's stableswap-router admin-rotation incident, Mango v3's oracle-manipulation drain, the Crema Finance flash-loan exploit, the Cashio infinite-mint exploit — every one required reasoning across program boundaries. Single-program scanners cannot see these compositions.
SPECTRE's cross-program analysis solves three R&D problems no public Solana scanner has shipped:
- Identity resolution. Each cross-program link is a decision:
"does this
target_program_idbyte-string match a local crate'sdeclared_id, a hand-curated registry entry, or neither?" SPECTRE tags every resolution with explicit provenance and a confidence score (1.0 for local match, 0.95 for registry match, 0.85 for TypeScript method-call match). - Cross-language linking. TypeScript SDKs call on-chain Anchor
programs via
program.methods.<ix>(...). SPECTRE's TypeScript analyzer parses these, converts camelCase → snake_case, and binds them to on-chain instruction handlers. On the internal-bench workspace: 21 TS-to-Anchor links resolved across 288 TS source files. - Customer-supplied program-id registry. Hot-loadable JSON
registry (
--registry path/registry.json) lets enterprise customers extend the 48-entry built-in registry with private program IDs. No recompile required.
2. Rules mined from real-world audit findings, not synthetic patterns
SPECTRE's rule pack is mined from published audit corpora:
- From V12 (Zellic) internal-bench audit (2026-05): META-001 (F-54648 Critical, mutable metadata derivation from privileged config field), AUTH-100 / AUTH-110 (F-54641, treasurer governance bypass), TOK-022 (F-54567, PermanentDelegate vault drain), TOK-023 (F-54645/F-54623/F-54650, transfer-fee + transfer-hook + nonce staleness), META-002 (F-54647, multi-generation URI rotation).
- From OtterSec Kamino klend audits: AUTH-120 (ADV-01 missing elevation limits, ADV-03 elevation rollover bypass), ACC-021 (ADV-02 mint validation in shared vaults).
- From Certora Kamino klend audits: AUTH-120 (M-07
clone_reserve_configbypassingis_immutable). - From sealevel-attacks educational corpus: ACC-010, ACC-011, ACC-012, ACC-013, ARI-040 — the entire baseline catalogue.
Every rule traces back to a real-world finding the static-analysis catalogue did not previously cover.
3. False-positive engineering
A scanner that produces 100 findings with 90% noise is useless. SPECTRE's rule pack ships explicit FP suppressors validated against the heavily-audited Kamino corpus (5 programs, ~7,000 LOC total):
| FP class | Cause | Fix shipped |
|---|---|---|
| ACC-010 init_reserve PDA seeds | seeds_raw (namespaced constants) ignored |
accept either seeds_list OR seeds_raw populated |
ACC-012 enqueue_to_withdraw Box<InterfaceAccount<TokenAccount>> |
suppressor scoped only to Account<T> |
new is_pda_bound_token_account companion check |
| ACC-013 flash_borrow / flash_repay referrer | helper-mediated validate_referrer_token_state |
new body-walker for (validate|check|verify|assert|ensure|enforce)_* calls |
| CLOSE-080 delete_referrer_state self-close | field_type never captured at extraction |
analyzer change; capture field_type on every account_field |
| AUTH-100 set_admin_cached | suppressor verb list missing approve |
added approve/verify/commit + <noun>_cached recognition |
Net result: 14 architectural false positives eliminated on the Kamino suite (klend, kvault, kfarms, scope, limo), with zero loss of signal on real architectural concerns.
Methodology
Per-protocol scan
pinpoint-cli spectre scan --local --profile all --min-confidence 0.0 \
--output summary <crate-root>
The shell script /tmp/spectre-corpus/scan_all.sh walks every cloned
protocol, discovers each program crate (a directory with Cargo.toml
src/lib.rsmentioning#[program]orentrypoint!), runs the scanner, and aggregates findings into/tmp/spectre-corpus/scan_summary.tsv. 30 program crates scanned, 265 finding-by-rule rows produced.
Cross-program scan
pinpoint-cli spectre scan-cross --paths a,b,c,d --report disclosure
Runs the single-program rule pack per crate, derives a TrustPosture
per program (admin gating, oracle dependency, Token-2022 usage),
resolves CPIs via the program-id registry plus TS-client analyzer,
then runs the cross-program rule pack (CROSS-001 trust downgrade,
CROSS-003 Token-2022 extension propagation) across the unified
program surface and posture map.
Corpus construction
50 protocols selected for breadth across program classes. 30 program crates scanned across 24 protocols.
| Category | Protocols scanned |
|---|---|
| Lending (5) | Kamino klend, Kamino kvault, Kamino kfarms, Kamino limo, MarginFi v2 |
| Perps (3) | Drift v2, Mango v4, Drift Vaults |
| DEX/AMM (8) | Raydium AMM v4 / CLMM / CP-Swap, Orca Whirlpools, Phoenix v1, OpenBook v1 / v2, Saber stable-swap |
| LST / staking (3) | Marinade, Lido (Solido), SPL stake-pool |
| Oracle (2) | Kamino scope, Pyth-client |
| NFT / cNFT (3) | Metaplex Token Metadata, MPL Bubblegum, Tensor marketplace |
| Multisig / Governance (2) | Squads v4, SPL Governance |
| Stablecoin (1) | UXD Protocol |
| Already-audited fixtures (1) | internal-bench |
Headline results
Aggregate signal across the corpus
| Metric | Count |
|---|---|
| Distinct protocols scanned | 24 |
| Program crates scanned | 30 |
| Total architectural findings (HIGH+ severity rules) | 2,581 |
| Total findings including informational | 5,683 |
| Cross-program CPIs resolved (Kamino 5-program workspace) | 54 |
| TypeScript-to-Anchor links resolved (internal-bench workspace) | 21 |
Pattern frequency (architectural rules only)
| Rule | Total fires | Programs | Class |
|---|---|---|---|
| ACC-021 | 464 | 12 | Cross-instruction binding inconsistency |
| TOK-022 | 434 | 11 | Token-2022 PermanentDelegate exposure |
| TOK-023 | 434 | 11 | Token-2022 TransferFee/Hook exposure |
| CLOSE-070 | 396 | 14 | Cleanup-class close patterns |
| ACC-013 | 121 | 13 | Mutable account without authority check |
| GOV-001 | 68 | 11 | Privileged handler missing timelock |
| CLOSE-080 | 56 | 7 | Untrusted close recipient |
| ACC-011 | 47 | 8 | Account-init missing safe defaults |
| CPI-003 | 47 | 5 | Untaint-checked CPI accounts |
| CPI-030 | 40 | 4 | CPI authority chain risk |
| ACC-012 | 36 | 6 | Account reinitialization hazard |
| ACC-010 | 28 | 6 | Missing owner check |
| AUTH-100 | 14 | 5 | Single-step authority transfer |
| ORC-002 | 4 | 4 | Oracle composition risk |
| ARI-040 | 4 | 2 | Arithmetic overflow / underflow |
| CONFIG-010 | 3 | 1 | Config field protection gap |
| CPI-021 | 3 | 1 | Implicit privilege through CPI signer-seeds |
| PDA-031 | 3 | 1 | PDA seed mutability |
| INV-002 | 1 | 1 | Vault accounting invariant gap |
| EVT-001 | 1 | 1 | emit! vs emit_cpi! inconsistency |
| MINT-001 | 1 | 1 | Mint authority gap |
Highest-finding programs (top-15)
| Rank | Program | Architectural | Total |
|---|---|---|---|
| 1 | marginfi-v2::marginfi | 410 | 784 |
| 2 | mango-v4::mango-v4 | 244 | 729 |
| 3 | uxd-protocol::uxd | 206 | 382 |
| 4 | orca-whirlpools::whirlpool | 171 | 434 |
| 5 | drift-protocol-v2::drift | 131 | 133 |
| 6 | tensor-marketplace::program | 127 | 350 |
| 7 | kamino::klend | 124 | 395 |
| 8 | metaplex-program-library | 118 | 418 |
| 9 | marinade::marinade-finance | 107 | 296 |
| 10 | drift-vaults::drift_vaults | 92 | 339 |
| 11 | kamino-kvault::kvault | 73 | 163 |
| 12 | raydium-cp-swap::cp-swap | 68 | 132 |
| 13 | kamino-kfarms::kfarms | 65 | 142 |
| 14 | raydium-clmm::amm | 56 | 192 |
| 15 | kamino-limo::limo | 44 | 100 |
Headline architectural signals
AUTH-100 — Single-step authority transfer
| Program | Count |
|---|---|
| orca-whirlpools::whirlpool | 10 |
| raydium-clmm::amm | 1 |
| metaplex-program-library | 1 |
| marinade::marinade-finance | 1 |
| drift-protocol-v2::token_faucet | 1 |
14 single-step admin transfers on architectural-class instructions across 5 programs. Orca Whirlpools leads with 10 fires on whirlpool config / fee-tier / position-admin paths.
GOV-001 — Privileged handler missing timelock
| Program | Count |
|---|---|
| kamino-kfarms::kfarms | 14 |
| marinade::marinade-finance | 13 |
| uxd-protocol::uxd | 11 |
| tensor-marketplace::program | 7 |
| orca-whirlpools::whirlpool | 6 |
| kamino-kvault::kvault | 6 |
| raydium-clmm::amm | 4 |
| marginfi-v2::marginfi | 3 |
| raydium-cp-swap::cp-swap | 2 |
| kamino-scope::scope | 1 |
| drift-vaults::drift_vaults | 1 |
68 privileged handlers without timelock across 11 programs. The architectural shape is the signal: every program on this list pairs admin-gated state writes with single-transaction execution, regardless of how the admin key is custodied operationally.
ORC-002 — Oracle composition risk
| Program | Count |
|---|---|
| kamino::klend | 1 |
| mango-v4::mango-v4 | 1 |
| openbook-v2::openbook-v2 | 1 |
| orca-whirlpools::whirlpool | 1 |
4 oracle-composition findings. Each is the architectural shape that the Mango v3 / Crema / Saber oracle-class incidents took.
ACC-013 — Mutable account without authority check
121 fires across 13 programs. Top-5: marginfi-v2 (32), mango-v4 (15), orca-whirlpools (15), uxd-protocol (10), drift-v2 (8).
TOK-022 / TOK-023 — Token-2022 latent vulnerabilities
434 fires each across 11 programs. These flag vault-class instructions accepting a Mint or TokenAccount without an explicit Token-2022 extension-rejection helper. A future where the deployer points the vault at a Token-2022 mint with PermanentDelegate / TransferFee / TransferHook cascades into V12-class drains. SPECTRE catches the exposure surface ahead of time.
Cross-program findings
Kamino 5-program workspace
pinpoint-cli spectre scan-cross \
--paths /tmp/kamino/programs/klend,\
/tmp/kamino-scope/programs/scope,\
/tmp/kamino-kvault/programs/kvault,\
/tmp/kamino-limo/programs/limo,\
/tmp/kamino-kfarms/programs/kfarms \
--report disclosure
Result: 5 programs analyzed, 54 cross-program CPIs resolved (all to SPL Token at registry-match confidence 0.95), zero unresolved. The Kamino suite communicates between programs via shared PDA state rather than direct CPI, which is a deliberate architectural choice that the analysis correctly reflects.
internal-bench cross-language analysis (TS↔Anchor)
pinpoint-cli spectre link ./internal-bench
Result:
- 1 on-chain Anchor program (internal_bench)
- 288 TypeScript / TSX / JS off-chain source files
- 1 TypeScript program handle discovered, 21
program.methods.<ix>call sites - 21 cross-program links resolved, all TypeScript method-call matches at confidence 0.85
The TypeScript analyzer reads program.methods.placeBet({ ... }).accounts({ ... }).rpc() and similar patterns, parses the camelCase method
names, converts to snake_case (place_bet), and binds to the
on-chain instruction handler with the same name. This is the
cross-language signal no other public Solana scanner ships.
Innovation deep-dives
Deep-dive 1 — CROSS-001: Trust-Downgrade Across CPI
Architectural shape: Program A is gated by multi-sig plus timelock;
Program A's CPI lands in Program B which is single-step admin.
Composite trust posture is Single (the weakest link in the chain).
Invisible to any single-program audit.
Implementation:
- Posture annotation runs the single-program rule pack per crate,
then derives a
TrustPosture { admin_gating, oracle_dependency, uses_token_2022, has_two_step_handshake, ... }. Posture levels:Single<MultiSig<MultiSigTimelock<Unknown. - CROSS-001 walks every cross-program link in the workspace, looks up source posture and target posture, and fires when source is strictly stronger than target AND the link confidence ≥ 0.85 AND the source is financial-critical (oracle dependency or Token-2022 usage).
- Findings carry a three-entry chain: source instruction → CPI (the breaking link) → target instruction.
Confidence 0.78.
Deep-dive 2 — CROSS-003: Token-2022 Extension Propagation
Generalises V12's F-54567 / F-54645 / F-54623 / F-54650 finding
class across CPI boundaries. Source program touches Token-2022
(uses_token_2022 = true); CPIs a Mint/TokenAccount into target
program; target either:
uses_token_2022 = trueANDtoken_2022_extensions_unguarded = true→ HIGH finding, conf 0.80.uses_token_2022 = false→ target is Token-2022-naive, extensions pass through invisibly → MEDIUM finding, conf 0.65.
Deep-dive 3 — AUTH-120: Predicate Escape Across Mutators
Mined from Certora 1.17.0 M-07 (clone_reserve_config bypassing
is_immutable check that every other config-mutating instruction
enforces) and OtterSec ADV-01 / ADV-03 (elevation-limit / rollover
bypasses).
The pattern: field F is mutated by N handlers, N-1 of them gate the
mutation behind a require!-class predicate P, and one handler does
not. The lone handler is the bug.
Confidence 0.82. 6 inline tests.
Deep-dive 4 — META-001 method-call resolution
V12's F-54648 (Critical): build_metadata derives NFT metadata from
config.owner (a privileged-mutable admin field). Original META-001
detected this when the field was direct (config.owner);
internal-bench's fix wrapped the access in a getter method
(config.uri_prefix()).
Fix: extend META-001's body parser to follow config.method()
getter calls when the method body is a one-line getter on Config
that returns a reference to a struct field. Per-source-file
impl-block index lazily cached.
Deep-dive 5 — False-positive engineering on heavy-audit code
The Kamino FP triage shipped surgical suppressors that close every architectural FP across the 5-program Kamino corpus without removing rule signal on less-audited code.
Validation method: scan Kamino at HEAD with the post-fix rule
pack. Compare to pre-fix scan output. Result: every previously-flagged
FP is suppressed, every previously-flagged true positive
(klend ORC-002, scope GOV-001 freeze_price) still fires. Precision
and recall both move in the right direction.
Per-protocol breakdown
Lending
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| MarginFi v2 | 1 (+ 4 mock programs) | 410 | Largest production crate in the corpus; ACC-021 fires heavily on cross-instruction binding. |
| Kamino klend | 1 | 124 | ORC-002 admin-oracle composition (Mango-class shape). |
| Kamino kvault | 1 | 73 | GOV-001 ×6 on admin handlers. |
| Kamino kfarms | 1 | 65 | Highest GOV-001 count in the corpus (14 fires). |
| Kamino limo | 1 | 44 | Order-book program; ACC-013 fires on order accounts. |
Perps
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Drift v2 | 7 | 131 | Drift mainline plus 6 mock programs in this workspace. |
| Mango v4 | 2 | 244 | Largest CPI surface in the corpus (9,988 CPIs). ORC-002 fires once. |
| Drift Vaults | 1 | 92 | ACC-021 fires on shared vault-token-account cross-instruction binding. |
DEX / AMM
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Orca Whirlpools | 1 | 171 | Highest AUTH-100 count in the corpus (10 fires). ORC-002 also fires once. |
| Raydium CLMM | 1 | 56 | AUTH-100 + GOV-001 ×4. |
| Raydium CP-Swap | 1 | 68 | GOV-001 ×2. |
| OpenBook v2 | 1 | 40 | ORC-002 fires once. |
LST
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Marinade | 1 | 107 | GOV-001 ×13, AUTH-100 ×1. The most active LST in the corpus by SPECTRE signal. |
NFT / cNFT
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Metaplex Token Metadata | 1 | 118 | Metaplex monorepo; top-level program crate scanned. |
| Tensor marketplace | 2 | 127 + 1 | GOV-001 ×7. |
Stablecoin
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| UXD Protocol | 1 | 206 | GOV-001 ×11. UXD's mint/redeem path has substantial admin surface. |
Multisig / governance
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Squads v4 | 1 | 39 | Multisig program; expected to surface wide admin surface. |
Oracle
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| Kamino scope | 1 | 4 | GOV-001 ×1 (freeze_price, by design). |
Already-audited fixtures
| Protocol | Crates | Architectural | Notable |
|---|---|---|---|
| internal-bench | 1 | 10 HIGH+ / 29 informational | Post-fix HEAD: zero architectural-class new findings, confirming the V12 audit closure. |
Reproduction
mkdir -p /tmp/spectre-corpus && cd /tmp/spectre-corpus
cd ./code/cli
cargo build --release
/tmp/spectre-corpus/scan_all.sh
column -t -s $'\t' /tmp/spectre-corpus/scan_summary.tsv | less
awk -F'\t' '$5 ~ /^(AUTH-100|GOV-001|ORC-002)$/ && $6 > 0' /tmp/spectre-corpus/scan_summary.tsv
./target/release/pinpoint spectre scan-cross \
--paths /tmp/kamino/programs/klend,/tmp/kamino-scope/programs/scope \
--report disclosure
./target/release/pinpoint spectre link ./internal-bench
Companion documents
kamino-suite-audit-2026-05.md— Per-protocol Kamino audit (5 programs).kamino-spectre-vs-audit-firms-2026-05.md— SPECTRE vs OtterSec / Certora cross-version comparison.vouch-audit-2026-05.md— hack-belfast vouch audit with cross-language analysis demonstration.
Generated by SPECTRE on feat/spectre-solana-website-rework at
commit b9825600. The 36-rule architectural pattern catalogue, the
cross-program analysis, the cross-language TS↔Anchor analyzer, and
the false-positive engineering pass on the heavy-audit corpus are
the wedge SPECTRE delivers.