Master Solana Program Audits Step by Step.

Here's the deal: Auditing Solana programs isn't some mystical art-it's a grind you can learn step by step, especially if you're comfy with Rust and Anchor. I've done a bunch of these, and honestly, it's like being a detective for code that handles real money. One slip up, and poof-millions gone, like that $320M Wormhole mess. But you can master it. We'll walk through it practically, from setup to shipping a report that'll make devs sweat.

Solana's blazing fast, right? Transactions zip by at thousands per second, fees hover around 0.000005 SOL per signature. But that speed means exploits hit hard and quick. Programs are Rust based on chain logic, often using Anchor framework for sanity. The thing is, without audits, you're begging for reentrancy, missing signer checks, or account confusion. In my experience, 80% of bugs are dumb stuff like not verifying ownership-accounts have an owner field that screams "hey, is this my program's turf?" Skip it, and attackers drain funds. Sound familiar? You'll spot these fast once you're in the groove.

Okay, potential pitfalls upfront: Solana's parallel execution loves DoS via compute limits (max ~1.4M compute units per tx). And PDAs (program derived addresses) are king-mess up seeds, and boom, wrong authority.

Get Your Setup Locked In First

Don't skip this. Auditors live or die by their tools.
  • Grab Solana CLI: sh -c "$(curl -sSfL https://release.solana.com/stable/install)". Testnet deploy? solana config set --url devnet.
  • Anchor: cargo install --git https://github.com/coral xyz/anchor anchor cli --locked. It's your Rust wrapper-macros like #[account] enforce checks.
  • Rust toolchain: rustup install 1.75 or whatever's stable. Solana wants specific versions.
  • IDE: VS Code with Rust Analyzer. Add sol azy later for quick recaps-runs cargo run -- recap and spits a Markdown overview of instructions, signers, writables. Game changer for triage.

Deploy a test program: anchor init mytest && anchor build && anchor deploy. Costs like 0.01 SOL on devnet. Now you're cooking.

Step 1: Nail the Scope Like a Pro

Every audit starts here. Grab the repo, whitepaper, IDL (Anchor's JSON interface). Ask: What's this program do? DeFi? NFT mint? List integrations-SPL tokens? External CPIs (cross program invocations)?

And here's a quick table for scoping questions I always hit devs with:
QuestionWhy It MattersRed Flags
Purpose & flows?Maps expected vs. actual behaviorVague answers = hidden logic bombs
Dependencies?Spot third party risksUnpinned SPL versions
Admin keys?Centralization killsSingle upgrade authority
Test coverage?Proves they thought aheadNo fuzz tests

In my experience, skip this and you're auditing blind. Set goals: No unauthorized access. Data integrity. Asset safety. Document it-takes 30 mins, saves days.

Quick Scope Checklist

  1. Read README, tests, client code.
  2. Graph instructions via anchor idl parse.
  3. Flag high risk: Token transfers, ownership changes.

Manual Review: Where the Magic (and Headaches) Happen

Look, tools are great, but eyes on code first. Clone the repo. Open in VS Code.

Start with instruction handlers. Anchor's #[program] module-each pub fn is an entrypoint. Check signers: #[account(mut, signer)]? Good. Missing? Attacker skips auth.

Common gotchas I hunt:

  • Missing signer checks: Always ctx.accounts.user.issigner. Or use Anchor's initpayer.
  • Account confusion: Verify account.owner == program_id. Helius calls this a top vuln-lets fakes slip in.
  • Reentrancy: Solana's single threaded per account, but CPIs can loop. No recursive calls without invariants.
  • Arithmetic overflows: Rust's checked_add/sub. Anchor enforces, but vanilla Rust? Nah.
  • DoS via timestamps: Blockhash timestamps manipulable-don't rely for critical logic.

Pro tip: Use sol azy recap. It pulls #[derive(Accounts)], lists writables without constraints. Writable sans seeds/has_one? Dig deep.

And run through every CPI: invoke(&ix, &accounts)? Validate targets.

Short sentences for emphasis: Check seeds. Verify bumps. Zero data on close.

Static & Dynamic Analysis-Automate the Boring Stuff

Now tools shine. Static: Scan source without running.

  • anchor test validator: anchor test. Hits unit tests.
  • Slab or Cargo audit: cargo audit for deps vulns.
  • Custom: Grep for "unchecked" math, "invoke_signed" without seeds.

Dynamic: Deploy to local validator. solana test validator. Tx simulate: solana program deploy --program id keypair target/deploy/program.so.

Edge cases? Pump invalid inputs. Watch compute: Over 1.4M units? DoS city.

Fuzz It Hard

Fuzzing's your bestie for crashes.
  1. Install honggfuzz or Anchor's built in.
  2. anchor test --skip local validator with fuzzer flag.
  3. Target inputs: Amounts (u64 max), PDAs with bad seeds.
  4. Analyze: Crashes on realloc? Bad.

I usually fuzz 10k iterations. Finds overflows quick. Fix? Add require!(amount < u64::MAX / 2, ErrorCode::Overflow).

Attack Sims: Play the Bad Guy

Okay, time to hack your own code. Ethical, duh. Sim reentrancy: CPI back to self? Set nonce, check state invariants before/after.

Flash loans? Solana's got 'em via Jupiter. Borrow huge, manipulate oracle, repay. Test: Duplicate modes in pools (Halborn found this in Huma-yield calc wrong).

  • Missing SPL verification: token::ID check.
  • Admin privs: Two step transfer? Pending owner field, confirm before swap.
  • Gas/Compute DoS: Loops on arrays? Cap lengths.

Tool: Custom scripts with @solana/web3.js. Fire 100 txs/sec at devnet. Watch failures.

Permissions & Checklist Cross Check

Permissions first. Role based access? #[account(has_one = authority)]. Admin risks? Multisig better than solo.

Now, your audit checklist. I print this bad boy:
  1. Code quality: Dead code? Magic numbers?
  2. Known vulns: Reentrancy, overflows, front running.
  3. Error handling: Every require! has custom code.
  4. Solana besties: Rent exempt? Close accounts return lamports.
  5. Upgrades: Buffer for BPF loader v2.

Cross off. Miss one? Report screams.

Write the Damn Report

No fluff. Structure: Exec summary, then findings by severity.

Severities like Halborn: Critical (9-10: fund loss), High (7-8.9), etc. Score with CVSS ish: Impact x Likelihood.

Example finding: High: Missing Ownership Check Account passed to transfer, no owner == programid. Attacker swaps fake account, drains 100% funds. Fix: Add require!(account.owner == ctx.programid, ErrorCode::InvalidOwner).

List all: Critical first. Then remediations. End with risk summary post fixes.

Post Audit: Verify & Iterate

Devs fix? Retest everything. Re run fuzz, manual. Final deploy sim on testnet.

Issues? Common: They half ass fixes. Force full re audit. In my experience, 2-3 rounds normal.

Follow up: Recommend 6-month re audit or post upgrade. Tools evolve-Anchor updates break stuff.

Advanced Tricks I Swear By

Master Anchor macros deep. #[account(seeds = [&[b"vault"], authority.().asref()], bump)]? Verifies PDA uniquely. Constraints like constraint = authority.() == ctx.accounts.user.().

Memory: Realloc? Check invariants post resize. Sol azy flags these.

Teams? Two independent reviews, like Vibranium. Cuts blind spots.

And for big leagues: Integration tests. Mock SPL, fire real txs.

Potential nightmare: Vanilla Solana (no Anchor). Manual deserialization-anchorlang::AccountDeserialize or bust. Prone to discriminator mismatches.

Tool Comparison Quickie

ToolBest ForCostGotcha
Anchor TestUnit/dynamicFreeLocal only
Sol azyRecon overviewFreeAnchor only
HonggfuzzFuzzingFreeSetup time
SlabStatic patternsFreeFalse positives

Practice Projects to Level Up

Don't theory this. Audit open repos.

  1. Huma Finance Solana programs (Halborn report public-reproduce findings).
  2. Build toy vault: Deposit/withdraw. Intentionally bug it (no signer), audit fix.
  3. Fork DEX, sim flash attack.
  4. Join Discord auditors (YouTube bootcamps mention 'em).

Time per audit? Small program: 20-40 hours. Complex DeFi: 100+. Bill $5k-50k easy once pro.

Stuck? Why overflows? Rust panics on wraparound-use checked_mul. Permissions fuzzy? Trace every writable.