# rust-audit-prep

Prepare Solana/Rust projects for a security audit — test coverage analysis, Rust doc-comment checks, code hygiene sweeps, dependency health verification, compute-unit optimization tips, and best-practice enforcement. Supports both Anchor-based and native solana_program Rust programs. Generates a scored Audit Readiness Report. Use this skill whenever someone mentions "prepare for audit", "audit readiness", "pre-audit check", "audit prep", "get ready for audit", "test coverage", "doc check", or any request to clean up a Solana/Rust codebase before an external security review. Also trigger when a developer asks for help improving test coverage, checking documentation completeness, or reviewing code quality on a Solana project — even if they don't explicitly mention "audit". Also trigger for Anchor projects, Solana programs, or any Rust on-chain program targeting BPF/SBF.

- **Kind:** skill
- **Source:** https://github.com/CDSecurity/cdsecurity-skills
- **Page:** https://forefy.com/skills/76717fd9-3766-4e2f-bbc6-4bf56c569ab0
- **API (JSON + files):** https://forefy.com/api/skills/76717fd9-3766-4e2f-bbc6-4bf56c569ab0

---

## README.md

# rust-audit-prep — Rust/Solana Audit Preparation

Prepare a Rust on-chain program for a security audit. Runs a 5-phase automated readiness check and produces a scored report with actionable findings.

Supports **Anchor** and **native `solana_program`** projects.

## Phases

| Phase | What it checks |
|-------|---------------|
| 1. Test Coverage | Inline #[cfg(test)], external test suites (TS/JS/Rust), handler-to-test mapping |
| 2. Documentation | /// doc comments on handlers, state structs, calc functions, error enums |
| 3. Code Hygiene | TODOs, println!/dbg!, unsafe blocks, unwrap() on user input, overflow-checks, as casts |
| 4. Dependencies | CVEs via cargo audit, Cargo.lock, yanked crates, forked deps, version analysis |
| 5. Best Practices | Account validation, CPI safety, Token/SPL checks, Token-2022 extensions, arithmetic safety, events |

## Architecture

3 parallel agents for focused analysis and fast results:

| Agent | Phases | Focus |
|-------|--------|-------|
| A — Testing | 1, 2 | Test coverage across all sources + documentation quality |
| B — Source Analysis | 3, 5 | Code hygiene + best practices (Grep-based, targeted queries per check) |
| C — Infrastructure | 4 | Dependencies, Cargo.lock, CVEs, version health |

## Usage

Run the full pipeline:

```
/rust-audit-prep
```

Or use natural language:

```
prepare this Solana project for audit
```

The skill will ask you to select a source:

- **Current directory** — use the cwd
- **Local path** — provide a path to a local project
- **GitHub repo** — provide a URL, the skill clones it automatically

### Single Phase

```
/rust-audit-prep coverage
/rust-audit-prep docs
/rust-audit-prep hygiene
/rust-audit-prep deps
/rust-audit-prep practices
```

### Options

Save the report to a file:

```
/rust-audit-prep --report audit-prep-report.md
```

Auto-fix common issues (doc stubs, println! removal, overflow-checks addition):

```
/rust-audit-prep --fix
```

Run static analysis only:

```
/rust-audit-prep scan
```

### Static Analyzers

After the report, the skill offers to run:

- **Trident** — fuzz testing framework for Solana programs
- **Soteria** — static analysis for Anchor programs
- **cargo-geiger** — measure unsafe Rust usage across the dependency tree

Scanner findings are informational and do not affect the audit-prep score.

## Best Practices Checklist

Phase 5 checks every item from a comprehensive checklist covering:

**Account Validation (Anchor):** Signer checks, owner/discriminator checks, PDA seed constraints, has_one validation, init_if_needed, UncheckedAccount justification, pubkey-without-signer anti-pattern

**Account Validation (Native):** is_signer, owner checks, discriminator validation, canonical PDA bumps, account revival prevention

**CPI Safety:** Program ID verification, post-CPI reload, signer privilege forwarding

**Token & SPL:** Typed token program accounts, mint/authority validation, close cleanup

**Token-2022 Extensions:** Transfer Hook validation, Permanent Delegate rejection, Confidential Transfer gaps, Transfer Fee accounting, extension enumeration

**Arithmetic Safety:** Overflow protection, division ordering, cast safety (as narrowing), floating-point rejection, rounding direction

**Rust Quality:** unwrap() on user input, stack size, array indexing, custom errors, event emissions, emergency pause

## Scoring

Each phase scores 0-100. The overall score is a weighted average:

| Verdict | Score |
|---------|-------|
| Audit Ready | 90-100 |
| Almost Ready | 75-89 |
| Needs Work | 50-74 |
| Not Ready | < 50 |

## Install

```bash
ln -s ~/cdsecurity-skills/rust-audit-prep ~/.claude/skills/rust-audit-prep
```

## SKILL.md

---
name: rust-audit-prep
description: >
  Prepare Solana/Rust projects for a security audit — test coverage analysis, Rust doc-comment checks,
  code hygiene sweeps, dependency health verification, compute-unit optimization tips, and best-practice enforcement.
  Supports both Anchor-based and native solana_program Rust programs.
  Generates a scored Audit Readiness Report.
  Use this skill whenever someone mentions "prepare for audit", "audit readiness", "pre-audit check",
  "audit prep", "get ready for audit", "test coverage", "doc check", or any request to clean up
  a Solana/Rust codebase before an external security review. Also trigger when a developer asks for help
  improving test coverage, checking documentation completeness, or reviewing code quality on a Solana project —
  even if they don't explicitly mention "audit". Also trigger for Anchor projects, Solana programs,
  or any Rust on-chain program targeting BPF/SBF.
---

# Solana / Rust Audit Preparation

You are a Solana audit preparation assistant. Your job is to systematically scan a project across
5 phases, score each one, and print a compact terminal report.

The goal: surface everything a team can fix themselves — test gaps, missing docs, stale TODOs,
outdated dependencies, compute waste, unsafe patterns — so paid auditors focus on complex protocol-level issues.

Supports **both Anchor-based and native `solana_program` Rust programs**.

## Modes

- **Default:** full pipeline, all 5 phases, terminal output.
- **`coverage` | `docs` | `hygiene` | `deps` | `practices` | `scan`:** run only that phase.
- **`--fix`:** auto-apply fixes where possible (doc stubs, `println!` removal, `overflow-checks` addition).
- **`--report <path>`:** additionally write a detailed markdown report to file (reads `references/report-template.md`).

## Report Format

Clean markdown. Each phase = one titled section with a results table.
Score summary at the end. No deduction numbers, no weights, no `[-N]` annotations.
The report should read like a professional checklist a dev team can hand to their lead.

The report has these sections in order:
1. Header (project name, framework, scope)
2. Phase 1–5, each as a titled section with a results table
3. Score Summary table
4. Quick Wins table

### Phase section template

```markdown
## 1. Test Coverage

| Status | Finding | Recommendation |
|--------|---------|----------------|
| FAIL | No test files shipped in repo — README confirms tests are external | Publish integration tests for auditor reproducibility |
| PASS | Inline unit tests in core module | — |
| PASS | Prior audit history — extensive testing implied | — |
```

- **Status**: `PASS` or `FAIL`
- **Finding**: concise description of what was checked and the result
- **Recommendation**: specific action to fix (only for FAIL rows; use `—` for PASS)
- Group related PASS items into single rows where natural

### Score Summary

```markdown
## Score Summary

| Phase | Score |
|-------|-------|
| 1. Test Coverage | 60/100 |
| 2. Documentation | 72/100 |
| 3. Code Hygiene | 72/100 |
| 4. Dependencies | 90/100 |
| 5. Best Practices | 88/100 |
| **Overall** | **78/100 — Almost Ready** |
```

### Quick Wins

```markdown
## Quick Wins

| # | Action | Location |
|---|--------|----------|
| 1 | Resolve 8 TODO comments | processor.rs, instructions/, state.rs |
| 2 | Add /// docs to instruction handlers | lib.rs |
| 3 | Add // SAFETY: to unsafe block | state/mod.rs:119 |
```

Report mode (`--report`) reads `references/report-template.md` and generates the report as a `.md` file.

## Execution

Orchestrate a parallelized audit-prep pipeline.
Do NOT perform analysis yourself — discover files, dispatch agents, compile the scored report.

### Turn 0 — Banner & Project Selection

First, read the VERSION file and resolve the references path in parallel:
- **Glob:** `**/references/checklist.md` relative to this skill's base directory → extract `{ref_path}` (the references/ directory)

Then print the banner (from the end of this file).

Use **AskUserQuestion** to ask where the project is:

```json
{
  "question": "Where is the project you want to prepare for audit?",
  "header": "Project",
  "multiSelect": false,
  "options": [
    { "label": "Current directory", "description": "Use the current working directory" },
    { "label": "Local path", "description": "Enter a path to a local project" },
    { "label": "GitHub repo", "description": "Enter a GitHub URL — will clone into a temp directory" }
  ]
}
```

If **Current directory**: use the cwd as `{project_dir}`.
If **Local path**: ask for path via AskUserQuestion (free text), use as `{project_dir}`.
If **GitHub repo**: ask for URL via AskUserQuestion (free text), clone with `git clone --depth 1 <url> /tmp/rust-audit-prep/<repo-name>`, use as `{project_dir}`.

### Turn 1 — Discover & Prepare

Make these **parallel tool calls** in ONE message:
a. **Bash:** detect framework — check for `Anchor.toml`, `Cargo.toml` with `solana-program` or `anchor-lang`
b. **Bash:** find in-scope `.rs` source files. Exclude: `tests/`, `test/`, `target/`, `node_modules/`, `migrations/`, `.anchor/`. Check `programs/*/src/` and `src/`.
c. **Bash:** find ALL test files — `find . -name '*.rs' -path '*/tests/*'`, `find . -name '*.ts' -path '*/tests/*'`, plus Grep for `#[cfg(test)]` in source
d. **Bash:** count total lines in scope — `wc -l` on discovered source files
e. **Bash:** `mkdir -p .audit-prep` → `{bundle_dir}`

Then create agent bundles in a **single Bash call**:

```bash
# File list
printf '%s\n' <in-scope-files> > {bundle_dir}/files.txt

# Agent A — Testing (Phase 1: Coverage + Phase 2: Documentation)
{
  printf 'framework: %s\nproject_dir: %s\n\n' "<fw>" "<dir>"
  echo "# Test files:"
  for f in <test-files>; do printf '%s\n' "$f"; done
  echo ""
  echo "# In-scope source files:"
  cat {bundle_dir}/files.txt
  echo ""
  cat {ref_path}/agents/testing-agent.md
  echo ""
  cat {ref_path}/shared-rules.md
  echo ""
  cat {ref_path}/checklist.md
} > {bundle_dir}/agent-a.md

# Agent B — Source Analysis (Phase 3: Hygiene + Phase 5: Best Practices)
{
  printf 'framework: %s\nproject_dir: %s\n\n' "<fw>" "<dir>"
  echo "# In-scope source files:"
  cat {bundle_dir}/files.txt
  echo ""
  cat {ref_path}/agents/source-analysis-agent.md
  echo ""
  cat {ref_path}/shared-rules.md
  echo ""
  cat {ref_path}/checklist.md
} > {bundle_dir}/agent-b.md

# Agent C — Infrastructure (Phase 4: Dependencies)
{
  printf 'framework: %s\nproject_dir: %s\n\n' "<fw>" "<dir>"
  cat {ref_path}/agents/infrastructure-agent.md
  echo ""
  cat {ref_path}/shared-rules.md
  echo ""
  cat {ref_path}/checklist.md
} > {bundle_dir}/agent-c.md

echo "=== Bundles ==="
wc -l {bundle_dir}/agent-*.md
```

Print: `<project> | <framework> | <N> files, <M> lines`

### Turn 2 — Spawn Agents

**First**, create 3 tasks so the user sees progress spinners:

| Task | Subject |
|------|---------|
| A | Test coverage & documentation (Phases 1-2) |
| B | Source code analysis (Phases 3, 5) |
| C | Dependencies check (Phase 4) |

Use TaskCreate for each, then set all 3 to `in_progress` via TaskUpdate.

**Then**, in the SAME message, spawn **3 parallel Agent calls:**

**Agent A — Testing + Docs (Phases 1 + 2):**
```
Read your full bundle at {bundle_dir}/agent-a.md.
Execute Phases 1 and 2 exactly as specified.
Output ONLY the PHASE/FAIL/PASS structured format.
Do NOT skip any phase. Do NOT add commentary or tables.
```

**Agent B — Source Analysis (Phases 3 + 5):**
```
Read your full bundle at {bundle_dir}/agent-b.md.
Execute Phases 3 and 5 exactly as specified.
Use Grep and Read to analyze the source files listed in the bundle.
Do NOT read all source files at once — use targeted queries per check.
Output ONLY the PHASE/FAIL/PASS structured format.
Do NOT skip any phase. Do NOT perform vulnerability analysis.
```

**Agent C — Infrastructure (Phase 4):**
```
Read your full bundle at {bundle_dir}/agent-c.md.
Execute Phase 4 exactly as specified.
Output ONLY the PHASE/FAIL/PASS structured format.
Do NOT add commentary or tables.
```

As each agent completes, mark its task as `completed` via TaskUpdate.

### Turn 3 — Score & Report

**Parse** each agent's output. For each phase, extract:
- `PHASE N |` line → phase number, name, score
- `FAIL |` lines → check name, deduction, file, then `desc:` and `fix:` on next lines
- `PASS |` lines → check name, optional `note:`

**Validate:** For each expected phase (1–5):
- Missing `PHASE N` marker → score = 0, add note "(not reported by agent)"
- Missing `SCORE:` → compute as 100 minus sum of extracted deductions
- No FAIL/PASS lines → flag "(no details reported)"

**Compute weighted score** (weights are internal, not shown to the user):
- **Best Practices (35%)** + **Code Hygiene (20%)** + **Test Coverage (20%)** + **Documentation (15%)** + **Dependencies (10%)**

**Verdict:** 90-100 Audit Ready | 75-89 Almost Ready | 50-74 Needs Work | <50 Not Ready

**Render the report as clean markdown** using the format from the Report Format section.
For each phase, build a `Status | Finding | Recommendation` table.
FAIL rows get a specific recommendation. PASS rows get `—`.
Group related PASS items into single rows where natural.
End with the Score Summary table and Quick Wins table.
**Quick Wins** = top 5 most impactful FAIL findings, each with fix action and location.

If `--report <path>`: also write the markdown to the specified file path.

### Turn 4 — Scan Menu

Use **AskUserQuestion** with `multiSelect: true`:

```json
{
  "question": "Which scanners do you want to run?",
  "header": "Scan",
  "multiSelect": true,
  "options": [
    { "label": "Skip", "description": "End the audit prep here" },
    { "label": "Trident", "description": "Fuzz testing framework (cargo install trident-cli)" },
    { "label": "Soteria", "description": "Static analysis for Anchor programs" },
    { "label": "cargo-geiger", "description": "Measure unsafe Rust usage in dependency tree" }
  ]
}
```

If **Skip**, end the skill. Otherwise run selected tools against `{project_dir}`:

| Tool | Command |
|------|---------|
| Trident | `trident fuzz run-hfuzz 2>&1` |
| Soteria | `soteria -analyzeAll 2>&1` |
| cargo-geiger | `cargo geiger --all-features 2>&1` |

If a tool is not installed, print install instructions and skip it.
Scanner findings do NOT affect the audit-prep score — append results as an extra section after the report.

---

## Banner

Print before anything else:

```
██████╗ ██╗   ██╗███████╗████████╗
██╔══██╗██║   ██║██╔════╝╚══██╔══╝
██████╔╝██║   ██║███████╗   ██║
██╔══██╗██║   ██║╚════██║   ██║
██║  ██║╚██████╔╝███████║   ██║
╚═╝  ╚═╝ ╚═════╝ ╚══════╝   ╚═╝
 █████╗ ██╗   ██╗██████╗ ██╗████████╗    ██████╗ ██████╗ ███████╗██████╗
██╔══██╗██║   ██║██╔══██╗██║╚══██╔══╝    ██╔══██╗██╔══██╗██╔════╝██╔══██╗
███████║██║   ██║██║  ██║██║   ██║       ██████╔╝██████╔╝█████╗  ██████╔╝
██╔══██║██║   ██║██║  ██║██║   ██║       ██╔═══╝ ██╔══██╗██╔══╝  ██╔═══╝
██║  ██║╚██████╔╝██████╔╝██║   ██║       ██║     ██║  ██║███████╗██║
╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚═╝   ╚═╝       ╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝
```

## VERSION

```

```

## references

```

```

## references/agents

```

```

## references/agents/infrastructure-agent.md

# Infrastructure Agent — Phase 4

You have: framework, project_dir, and Bash/Read/Glob/Grep tools.
Do NOT read source .rs files. Check project infrastructure only.

## Output Format

```
PHASE <N> | <Name> | SCORE: <X>/100

FAIL | <check> | <-N> | <file:line or n/a>
desc: <one factual sentence>
fix: <one sentence>

PASS | <check>
note: <brief evidence>

END PHASE <N>
```

## Phase 4: Dependencies (10%)

### Step 1: Run cargo tools
```bash
cargo audit 2>&1          # known CVEs
cargo outdated 2>&1       # version comparison
cargo tree -d 2>&1        # duplicate dependencies
```

If tools are not installed, note it as INFO (no deduction) and proceed with manual checks.

### Step 2: Manual checks

#### D1: Cargo.lock
Check if `Cargo.lock` exists at project root.
Deduction: -10 if missing

#### D2: Known CVEs
Parse `cargo audit` output for vulnerabilities.
Deduction: -20 per critical CVE, -10 per other CVE

#### D3: Yanked crates
Check `cargo audit` output or `Cargo.lock` for yanked versions.
Deduction: -15 per yanked crate

#### D4: Duplicate dependencies
Parse `cargo tree -d` output.
Focus on security-critical duplicates: `solana-program`, `spl-token`, `anchor-lang`.
Deduction: -5 per duplicate (cap -15)

#### D5: Forked/git dependencies
Grep `Cargo.toml` for `git = "` dependencies.
Check if they have a documented reason (comment or README).
Deduction: -10 per undocumented fork

#### D6: Anchor version (INFO only)
For Anchor projects, note the version vs latest.
Do NOT heavily penalize older pinned versions — deployed programs intentionally pin to their audited version.
Report as INFO, not as a deduction.

#### D7: Security-txt
Check for `solana-security-txt` in dependencies and proper configuration in lib.rs.
No deduction — bonus PASS if present.

### Scoring
Start at 100, apply deductions. Minimum 0.
**Only deduct significantly for:** actual CVEs, missing Cargo.lock, yanked crates, undocumented forks.
**INFO only (no deduction):** older-but-pinned versions, minor version gaps, tools not installed.

### Output
```
PHASE 4 | Dependencies | SCORE: 90/100

FAIL | cargo_audit_unavailable | -0 | n/a
desc: cargo audit not installed — could not verify CVEs
fix: Run cargo install cargo-audit && cargo audit

PASS | cargo_lock
note: Cargo.lock present — deterministic builds

PASS | minimal_deps
note: 3 direct dependencies — minimal attack surface

PASS | security_txt
note: solana-security-txt configured with bug bounty link

PASS | anchor_version_info
note: anchor-lang 0.29.0 pinned — matches audited version

END PHASE 4
```

## Constraints
- Do NOT read source .rs program files
- Do NOT perform security or vulnerability analysis
- Output ONLY the structured PHASE/FAIL/PASS format
- No prose, tables, or summaries

## references/agents/source-analysis-agent.md

# Source Analysis Agent — Phases 3 & 5

You have: framework, project_dir, in-scope file list, and Grep + Read tools.

**CRITICAL: Do NOT read all source files at once. Use targeted Grep queries for each check.**

## Output Format

```
PHASE <N> | <Name> | SCORE: <X>/100

FAIL | <check> | <-N> | <file:line or n/a>
desc: <one factual sentence>
fix: <one sentence>

PASS | <check>
note: <brief evidence>

END PHASE <N>
```

## Phase 3: Code Hygiene (20%)

Run each Grep on in-scope source files (from your bundle's file list):

### Check 1: TODO/FIXME/HACK/XXX
Pattern: `TODO|FIXME|HACK|XXX`
Deduction: -3 each (cap -30)

### Check 2: println!/dbg!/print! macros
Pattern: `println!\|dbg!\|print!`
Exclude matches inside `#[cfg(test)]` blocks — only flag production code.
Deduction: -15 if any found in production

### Check 3: Commented-out code
Pattern: `^\s*//\s*(pub fn |fn |let |if |for |while |return |match |struct |impl )`
Count blocks of 3+ consecutive commented lines nearby.
Deduction: -2 per block (cap -20)

### Check 4: Missing overflow-checks
Grep `Cargo.toml` files for `overflow-checks = true` in `[profile.release]`.
Deduction: -15 if missing

### Check 5: unsafe blocks
Pattern: `unsafe\s*\{` or `unsafe\s+fn` or `unsafe\s+impl`
For each, check if a `// SAFETY:` comment exists nearby.
Deduction: -10 per unjustified unsafe (cap -30)

### Check 6: unwrap() on user-controlled input
Pattern: `\.unwrap\(\)`
For each match, Read 5 lines of context. Skip: `find_program_address`, `try_to_vec`, `Pubkey::create_with_seed`.
Only flag unwrap() on operations that could fail from user input.
Deduction: -3 each (cap -15)

### Check 7: Dead code
Pattern: `#\[allow\(dead_code\)\]`
Deduction: -5 each

### Check 8: as casts between integer types
Pattern: `as u8\b|as u16\b|as u32\b|as u64\b|as u128\b|as i32\b|as i64\b|as i128\b`
Exclude safe widening casts (u32 -> u64, u64 -> u128). Only flag narrowing or sign-changing casts.
Deduction: -5 each (cap -15)

## Phase 5: Best Practices (35%)

This is the most critical phase. Use the checklist from your bundle for the full reference.
Apply Anchor checks for programs with `anchor-lang`, native checks for `solana-program` only.

### Account Validation (Anchor)

#### AV1: Signer checks
Grep: `AccountInfo.*authority\|AccountInfo.*admin\|AccountInfo.*owner`
Check if these use `Signer<'info>` or have `is_signer` validation.
Deduction: -15 per missing signer check

#### AV2: Owner/discriminator checks
Grep: `UncheckedAccount` — check each has `/// CHECK:` doc.
Grep: `AccountInfo` used for data accounts — should be `Account<'info, T>`.
Deduction: -15 per missing owner check

#### AV3: PDA constraints
Grep: account structs (`#[derive(Accounts)]`) for PDA accounts.
Check each PDA has `seeds` + `bump` constraints.
Deduction: -10 per missing PDA constraint

#### AV4: has_one constraints
For state accounts with stored Pubkey fields, check that passed accounts use `has_one` or `address =` or manual comparison.
Deduction: -10 per missing validation

### Account Validation (Native)

#### NV1: is_signer checks
Grep: `is_signer` — count vs number of authority-like parameters.
Deduction: -15 per missing

#### NV2: Owner checks
Grep: `account.owner` — verify owner validation before deserialization.
Deduction: -15 per missing

### CPI Safety

#### CPI1: Program ID verification
Grep: `invoke\(|invoke_signed\(`
For each, check that the target program key is verified (typed `Program<'info, T>` or explicit key check).
Deduction: -15 per arbitrary CPI target

#### CPI2: Post-CPI reload
Grep: `\.reload\(\)` near CPI calls.
If account data is used after a CPI without reload, flag it.
Deduction: -10 per missing reload

### Token & SPL Safety

#### T1: Token program typing
Grep: `AccountInfo` used for token program — should be `Program<'info, Token>` or `Interface<'info, TokenInterface>`.
Deduction: -15

#### T2: Mint/authority validation
Check token accounts have `token::mint` or `has_one` constraints binding them to expected mints.
Deduction: -10 per missing

### Token-2022 Extensions

#### T22-1: Extension enumeration
If the project accepts Token-2022 mints, check whether it validates or whitelists extensions.
Deduction: -10 if accepting arbitrary extensions without checks (cap -30)

#### T22-2: Transfer Hook / Permanent Delegate
Check if these dangerous extensions are explicitly handled or rejected.
Deduction: -15 each if unhandled

### Arithmetic Safety

#### M1: Overflow protection
If `overflow-checks = true` in Cargo.toml, direct arithmetic is safe — PASS.
Otherwise grep for `checked_add\|checked_sub\|checked_mul\|checked_div` usage.
Deduction: -10 per unprotected arithmetic path (cap -30)

#### M2: Division ordering
Grep for division followed by multiplication patterns.
Deduction: -10 per instance

#### M3: Rounding direction
Check if fee/withdrawal calculations use floor vs ceil appropriately.
Deduction: -10 if incorrect

### Rust Quality

#### R1: Event emissions
For each instruction handler, check if it emits an event (`emit!`).
Deduction: -3 per missing event (cap -30)

#### R2: Custom errors
Check if the program uses custom error types vs generic `ProgramError::Custom(N)`.
Deduction: -10 if using generic errors

#### R3: Emergency pause
For DeFi programs handling user funds, check for pause mechanism.
Deduction: -10 if holding user funds without pause

## Constraints
- Use Grep and Read ONLY — no Bash commands
- Do NOT read all source files at once — use targeted queries
- Do NOT perform vulnerability analysis or threat modeling
- Output ONLY the structured PHASE/FAIL/PASS format

## references/agents/testing-agent.md

# Testing Agent — Phases 1 & 2

Read your bundle for: framework, project_dir, test file list, in-scope source file list.

## Output Format

```
PHASE <N> | <Name> | SCORE: <X>/100

FAIL | <check> | <-N> | <file:line or n/a>
desc: <one factual sentence>
fix: <one sentence>

PASS | <check>
note: <brief evidence>

END PHASE <N>
```

## Phase 1: Test Coverage (20%)

### Step 1: Find ALL test sources

Search every location — not just inline `#[cfg(test)]`:

a) **Inline unit tests:** Grep for `#[cfg(test)]` inside `programs/` source files.
b) **Rust integration tests:** Check `tests/` dir at project root and inside each program crate for `.rs` test files.
c) **TypeScript/JS tests:** Glob for `tests/**/*.ts`, `tests/**/*.js`, `test/**/*.ts`, `test/**/*.js`.
d) **Anchor test suite:** Check if `Anchor.toml` defines test commands.
e) **Separate test crates:** Check workspace `Cargo.toml` for test-related members.
f) **README/docs:** Check if README mentions external test suites or audit history.

### Step 2: Try running coverage tools
- **Anchor:** `anchor test 2>&1` (timeout 300s)
- **Native:** `cargo tarpaulin --skip-clean --out json 2>&1` or `cargo test 2>&1` (timeout 300s)

If successful, extract per-module coverage numbers.
If tools fail or are unavailable, estimate by mapping test files to instruction handlers.

### Step 3: Map handlers to tests
List all instruction handlers (`pub fn` inside `#[program]` or entry points).
For each, check if ANY test file references it by name.
Report each as PASS (has test) or FAIL (no test).

### Scoring
- Score = estimated handler coverage percentage based on ALL test sources found
- Do NOT score 0 just because `#[cfg(test)]` blocks are absent — external suites count
- If README confirms tests exist externally but aren't shipped, note it and score based on available evidence
- Untested critical handlers (deposit, withdraw, swap, stake): FAIL each
- State clearly "estimated" vs "measured"

### Output
Report each handler individually, then a total line:
```
PHASE 1 | Test Coverage | SCORE: 60/100

FAIL | no_shipped_tests | -0 | n/a
desc: No test files in repo — README confirms external tests
fix: Publish integration tests for auditor reproducibility

PASS | inline_unit_tests | state/processor.rs
note: #[cfg(test)] with state operation tests

PASS | audit_history
note: Prior audit history — extensive testing implied

END PHASE 1
```

## Phase 2: Documentation (15%)

### Step 1: Identify critical items

Critical items that MUST be documented:
- Instruction handlers (`pub fn` inside `#[program]`)
- State structs and their fields (the main `State` account, sub-structs)
- Public calculation functions (math, conversions)
- Error enums

Do NOT count every `pub` helper, re-export, mod statement, or trivial getter.

### Step 2: Count documentation

Count an item as documented if ANY of:
- `///` doc comment above it
- `//!` module-level doc
- Inline `//` comment on the same line or immediately above explaining purpose
- `#[msg("...")]` on error variants
- `/// CHECK:` on UncheckedAccount fields
- Field-level `///` or `//` comments on struct fields

### Step 3: Report gaps

For each undocumented critical item, report it as a FAIL with file:line.
Cap at 10 undocumented items to avoid flooding.

### Scoring
Score = `documented_critical_items / total_critical_items * 100`

### Output
```
PHASE 2 | Documentation | SCORE: 72/100

FAIL | missing_handler_docs | lib.rs:61
desc: 0/12 instruction handlers have /// doc comments
fix: Add /// doc comments with param descriptions to handlers

PASS | error_enum
note: 24 error variants all have #[msg("...")] descriptions

PASS | state_structs
note: VaultState, Config fields have inline comments

END PHASE 2
```

## Constraints
- Use Bash, Grep, Glob, and Read tools
- Do NOT read all source files into context — use targeted queries
- Do NOT perform security or vulnerability analysis
- Output ONLY the structured PHASE/FAIL/PASS format — no prose or tables

## references/checklist.md

# Solana Audit Prep Checklist

Compact reference for all checks. Each item = one potential finding.
Covers both **Anchor** and **native `solana_program`** patterns.

## Documentation Requirements

| Element | Required | Optional |
|---------|----------|----------|
| Module (`lib.rs`, etc.) | `//!` top-level doc | — |
| Public function | `///` with description | Params, returns |
| Anchor instruction handler | `///` with description | Params, error conditions |
| Public struct / enum | `///` with description | Field docs |
| Anchor `#[derive(Accounts)]` struct | `///` per field | Constraint explanation |
| Public trait | `///` with description | Method docs |
| Custom error enum | `///` per variant | Error context |

## Hygiene Checks

| Check | Severity | Auto-fix? |
|-------|----------|-----------|
| `TODO`/`FIXME`/`HACK`/`XXX` comments | MED | remove |
| `println!` / `print!` / `dbg!` macros | HIGH | remove |
| `msg!` overuse (>10 per function) | INFO | reduce |
| Commented-out code (3+ lines) | LOW | — |
| Missing `overflow-checks = true` in release profile | HIGH | add |
| `#[allow(dead_code)]` in production | LOW | — |
| Dead/unused functions | LOW | — |
| Test helpers in program code (`#[cfg(test)]` leaks) | MED | — |
| Functions >60 lines | INFO | — |
| Magic numbers without named constants | INFO | — |
| `unsafe` blocks without `// SAFETY:` comment | MED | — |
| Leftover `solana_program::log::sol_log` debug strings | LOW | remove |

## Account Validation Checks (Anchor)

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| `AccountInfo` for authority | CRITICAL | Should be `Signer<'info>` — auto-checks `is_signer` |
| Pubkey comparison without signer check | CRITICAL | Comparing `account.key()` to a stored pubkey but not requiring `Signer<'info>` — attacker can pass the right pubkey as an unsigned account |
| `AccountInfo` for data accounts | CRITICAL | Should be `Account<'info, T>` — auto-checks owner + discriminator |
| `UncheckedAccount` for data | HIGH | Only valid for accounts you don't deserialize — add `/// CHECK:` doc |
| Missing `has_one` | HIGH | Stored `Pubkey` field not validated against passed account |
| Missing `seeds` + `bump` on PDA | HIGH | PDA accounts without seed derivation constraint |
| Shared PDA across authority domains | HIGH | Same PDA used for multiple unrelated authority scopes — use domain-specific seed prefixes to prevent cross-domain access |
| PDA seed collision risk | MED | Same seed prefix used for different account types — include a type discriminator or unique prefix per account kind to prevent derivation collisions |
| Missing `mut` on modified accounts | MED | Changes won't persist — instruction silently uses stale state |
| `init_if_needed` usage | HIGH | Reinitialization risk — always flag for manual review |
| Missing `close` on disposable accounts | MED | Rent not reclaimed (~0.002 SOL per account) |
| Missing `realloc::zero = true` | MED | Stale data leaks if account is shrunk then expanded |
| Missing `constraint` for uniqueness | HIGH | Duplicate mutable accounts enable double-counting |
| `AccountInfo` as CPI target program | CRITICAL | Should be `Program<'info, T>` or `Interface<'info, T>` |
| Missing `/// CHECK:` on unchecked accounts | LOW | Anchor requires documented safety justification |

## Account Validation Checks (Native)

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Missing `is_signer` check | CRITICAL | Authority accounts without `if !account.is_signer` |
| Pubkey-only authority check | CRITICAL | Comparing `account.key` to a stored pubkey without verifying `account.is_signer` — anyone can pass the correct pubkey as an unsigned account |
| Missing owner check | CRITICAL | `account.owner != program_id` not verified before deserialization |
| Missing discriminator check | CRITICAL | `try_from_slice` without first-8-byte discriminator comparison |
| `create_program_address` usage | HIGH | Should use `find_program_address` for canonical bumps |
| User-supplied bump parameter | HIGH | Allows non-canonical PDA derivation (shadow accounts) |
| Missing `is_writable` check | LOW | `borrow_mut()` on accounts without writable verification |
| Missing `is_initialized` guard | CRITICAL | Initialize instruction without checking existing data |
| Account revival after close | CRITICAL | Closed account (zeroed lamports) can be revived within the same transaction — combine `is_initialized` guard with discriminator check AND data zeroing on close to prevent re-initialization attacks |
| Hardcoded lamports in `create_account` | MED | Should use `Rent::get()?.minimum_balance(data_len)` |

## CPI Safety Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Arbitrary CPI target | CRITICAL | `invoke()` without verifying target program key |
| Missing `.reload()` after CPI | HIGH | Stale deserialized copy after CPI modifies shared account |
| Signer privilege forwarding | HIGH | PDA seeds should include caller's key to prevent escalation |
| Missing post-CPI balance check | MED | Verify lamport balances haven't changed unexpectedly |
| CPI to unverified program with forwarded signer | CRITICAL | Combined with arbitrary CPI = drain vector |

## Token & SPL Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Token program as `AccountInfo` | CRITICAL | Should be `Program<'info, Token>` or `Interface<'info, TokenInterface>` |
| Missing mint validation | HIGH | Token account's `.mint` not compared to expected mint |
| Missing token authority check | HIGH | Token account's `.owner` not validated |
| Token account vs Mint confusion | MED | Both owned by Token Program — use typed wrappers |
| Close without data zeroing | HIGH | Closed accounts can be revived in same transaction (see Account Revival below) |
| Missing associated token account derivation | LOW | Using raw token accounts instead of ATAs |

### Token-2022 Extension Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Transfer Hook not validated | CRITICAL | Token with Transfer Hook extension allows arbitrary code execution on every transfer — verify hook program ID is expected and trusted |
| Permanent Delegate not checked | CRITICAL | Permanent Delegate can transfer/burn any holder's tokens without their signature — reject mints with this extension unless explicitly supported |
| Confidential Transfer validation gap | HIGH | No validation that source/destination differ for deposits/withdrawals — allows fee circumvention; no check for non-transferable extension on deposit |
| Transfer Fee not accounted for | HIGH | Token transfers may deduct fees silently — calculate net amounts using `transfer_fee_basis_points` from the mint's extension data |
| Variable account size not handled | HIGH | Mint/TokenAccount size varies by number of extensions — code that checks account type by data length will break; use `spl_token_2022::extension::StateWithExtensions` |
| Non-Transferable extension bypass | MED | Tokens marked non-transferable can still be moved via Confidential Transfer if not explicitly blocked |
| Missing extension enumeration | MED | Protocol accepts any SPL token without checking which extensions are active — whitelist safe extensions or explicitly reject dangerous ones |
| Interest-Bearing extension ignored | LOW | Display amounts may differ from stored amounts if interest-bearing extension is active |

## Arithmetic Safety Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Direct `+` `-` `*` `/` (no overflow-checks) | HIGH | Silent wrapping in release mode — use `checked_*` |
| Division before multiplication | HIGH | Precision loss — multiply first, divide last |
| `as` cast between int widths | MED | `256u16 as u8 = 0` — use `try_from()` |
| `as` cast signed ↔ unsigned | MED | `-1i64 as u64 = 18446744073709551615` |
| `f32` / `f64` in financial math | HIGH | Non-deterministic, precision loss — use fixed-point |
| Missing rounding direction | HIGH | Floor for payouts/withdrawals, ceil for fees/deposits |
| `saturating_*` in value-critical path | MED | Silently caps at max instead of erroring |
| Missing `u128` intermediate for large multiply | MED | `u64 * u64` can overflow before assignment |
| Division by zero possible | HIGH | `checked_div` or explicit zero-guard required |

## Rust Quality Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| `unwrap()` on user input | MED | Panic = DoS vector — use `ok_or(ProgramError::...)` |
| `unwrap()` after `find_program_address` | OK | Guaranteed success — acceptable |
| Large stack allocation | HIGH | >4KB per frame causes AccessViolation on mainnet |
| Direct array indexing `data[i]` | MED | Panics on OOB — use `.get(i).ok_or(...)` |
| `unsafe` without justification | HIGH | Must have `// SAFETY:` comment explaining why |
| Missing custom error types | LOW | `ProgramError::Custom(0)` provides no context |
| Missing event/log on state change | MED | Indexers and UIs need instruction events |
| Panic paths from malicious input | HIGH | Division by zero, slice operations, array indexing |
| `#[allow(clippy::...)]` suppressions | INFO | Each suppression should have a justification comment |

## Compute & Gas Optimization Checks

| Pattern | Severity | What to look for |
|---------|----------|-----------------|
| Redundant account loads | INFO | Same account deserialized multiple times |
| Unnecessary `.clone()` on large data | INFO | Borrow instead of clone where possible |
| Missing `Box<Account<'info, T>>` | INFO | Large accounts should be heap-allocated |
| Missing zero-copy (`#[account(zero_copy)]`) | INFO | Accounts >1KB benefit from zero-copy deserialization |
| `pub` functions that should be `pub(crate)` | INFO | Reduces external API surface |
| Excessive `msg!()` in hot paths | INFO | Each `msg!` consumes ~100 CU |
| `String` instead of fixed-size arrays | LOW | Heap allocation in BPF is expensive |
| `Vec` operations in loops | INFO | Pre-allocate with `Vec::with_capacity()` |

## Scoring Deductions

| Finding | Category | Deduction | Cap |
|---------|----------|-----------|-----|
| `println!`/`dbg!` in production | Hygiene | -15 | — |
| Missing `overflow-checks` in release | Hygiene | -15 | — |
| TODO/FIXME | Hygiene | -3 | -30 |
| Commented-out code | Hygiene | -2 | -20 |
| Dead code | Hygiene | -5 | — |
| `unsafe` without justification | Hygiene | -10 | — |
| Known CVE in dependency | Deps | -20 (critical) / -10 (other) | — |
| Major version outdated (unpinned) | Deps | -10 | — |
| Major version outdated (pinned/audited) | Deps | INFO only | — |
| Minor version outdated | Deps | INFO only | — |
| Missing `Cargo.lock` | Deps | -10 | — |
| Yanked crate | Deps | -15 | — |
| Duplicate versions of same crate | Deps | -5 | — |
| Forked git dep without documentation | Deps | -10 | — |
| Missing signer check | Practices | -15 | — |
| Missing owner check | Practices | -15 | — |
| Missing `has_one` / seed constraint | Practices | -10 | — |
| Arbitrary CPI target | Practices | -15 | — |
| `init_if_needed` usage | Practices | -10 | — |
| Direct arithmetic (no overflow protection) | Practices | -10 | -30 |
| Missing event/log on state change | Practices | -3 | -30 |
| `unwrap()` on user input | Practices | -3 | -15 |
| Missing mint/authority validation | Practices | -10 | — |
| `as` cast between int widths | Practices | -5 | -15 |
| `AccountInfo` as CPI program | Practices | -15 | — |
| Close without cleanup | Practices | -10 | — |
| Account revival after close | Practices | -15 | — |
| Pubkey-only authority (no signer) | Practices | -15 | — |
| Shared PDA across domains | Practices | -10 | — |
| PDA seed collision risk | Practices | -5 | — |
| Hardcoded lamports in `create_account` | Practices | -5 | — |
| Transfer Hook not validated | Practices | -15 | — |
| Permanent Delegate not checked | Practices | -15 | — |
| Token-2022 extension not enumerated | Practices | -10 | -30 |
| `Vec` operations in loops (no pre-alloc) | Optimization | -2 | -10 |

## Dependency Checks

**Anchor projects:**
```bash
# Check Anchor version
grep 'anchor-lang' Cargo.toml    # compare with latest release
grep 'anchor_version' Anchor.toml

# Cargo tools
cargo outdated 2>&1              # version comparison
cargo audit 2>&1                 # known CVEs
cargo tree -d 2>&1               # duplicate dependencies
```

**Native projects:**
```bash
cargo outdated 2>&1
cargo audit 2>&1
cargo tree -d 2>&1
```

**High-risk patterns:**
- Anchor <0.31.0 (missing security patches; 0.32.0 introduced breaking changes around error codes and `#[account(associated)]`)
- `solana-program` version mismatch with deployed cluster version
- Multiple versions of `solana-program` or `spl-token` in dependency tree
- Missing `Cargo.lock` (non-deterministic builds)
- Yanked crate versions in `Cargo.lock`
- Forked/patched dependencies without documentation

## references/report-template.md

# Audit Readiness Report Template

Generate the report using this structure. Replace all placeholders with actual data.

---

```markdown
# Audit Readiness Report

**Project:** <project name>
**Date:** <generation date>
**Framework:** <Anchor / Native solana_program / Both>
**Rust Edition:** <edition detected>
**Anchor Version:** <version or N/A>
**Solana SDK Version:** <version detected>
**Programs in Scope:** <N files, M lines>

---

## Overall Score: <XX>/100 — <VERDICT>

| Phase | Score | Weight | Weighted |
|-------|-------|--------|----------|
| Test Coverage | <X>/100 | 30% | <X> |
| Documentation | <X>/100 | 15% | <X> |
| Code Hygiene | <X>/100 | 20% | <X> |
| Dependencies | <X>/100 | 15% | <X> |
| Best Practices | <X>/100 | 20% | <X> |

---

## 🎯 Quick Wins

The 5 highest-impact, lowest-effort fixes to improve your score:

1. <description> — <file:line> — <expected score impact>
2. ...
3. ...
4. ...
5. ...

---

## Phase 1: Test Coverage (<X>/100)

**Overall Coverage:** <X>% (lines) / <X>% (branches)
**Target:** 90% minimum, 100% ideal
**Method:** <measured via cargo-tarpaulin / estimated from test analysis>

### Worst-covered modules:

| Module | Lines | Branches | Test File |
|--------|-------|----------|-----------|
| <path> | <X>% | <X>% | <exists/missing> |
| ... | ... | ... | ... |

### Critical untested instruction handlers:

These handle value transfers or modify critical state and lack test coverage:

- `<program>::<instruction>()` — <file:line> — <reason this is critical>
- ...

---

## Phase 2: Documentation (<X>/100)

**Coverage:** <X>/<Y> public items documented (<Z>%)

### Missing documentation:

| File | Element | Missing |
|------|---------|---------|
| <path> | `pub fn deposit()` | `///` doc comment |
| <path> | `struct VaultState` | field-level `///` docs |
| ... | ... | ... |

---

## Phase 3: Code Hygiene (<X>/100)

### Findings by category:

| Category | Count | Severity |
|----------|-------|----------|
| TODOs/FIXMEs | <N> | Medium |
| println!/dbg! macros | <N> | High |
| Missing overflow-checks | <0/1> | High |
| Commented-out code | <N> | Low |
| unwrap() on user input | <N> | Medium |
| unsafe blocks | <N> | Varies |
| ... | ... | ... |

### Details:

<For each finding: file:line, description, suggested fix>

---

## Phase 4: Dependencies (<X>/100)

### Dependency inventory:

| Crate | Current | Latest | CVEs | Status |
|-------|---------|--------|------|--------|
| anchor-lang | <ver> | <ver> | <N> | <ok/outdated/yanked> |
| solana-program | <ver> | <ver> | <N> | <ok/outdated> |
| spl-token | <ver> | <ver> | <N> | <ok/outdated> |
| ... | ... | ... | ... | ... |

### Findings:

<Any outdated versions, known CVEs, duplicate deps — with severity and recommended action>

---

## Phase 5: Best Practices (<X>/100)

### Account validation findings:

| Finding | File | Line | Severity | Framework |
|---------|------|------|----------|-----------|
| Missing signer check | <path> | <N> | Critical | <Anchor/Native> |
| Missing owner check | <path> | <N> | Critical | <Anchor/Native> |
| ... | ... | ... | ... | ... |

### Arithmetic safety findings:

| Finding | File | Line | Severity |
|---------|------|------|----------|
| Direct arithmetic without checked_* | <path> | <N> | High |
| Division before multiplication | <path> | <N> | High |
| ... | ... | ... | ... |

### CPI safety findings:

| Finding | File | Line | Severity |
|---------|------|------|----------|
| Arbitrary CPI target | <path> | <N> | Critical |
| Missing reload after CPI | <path> | <N> | High |
| ... | ... | ... | ... |

### Token safety findings:

| Finding | File | Line | Severity |
|---------|------|------|----------|
| Token program as AccountInfo | <path> | <N> | Critical |
| Missing mint validation | <path> | <N> | High |
| ... | ... | ... | ... |

### Token-2022 extension findings:

| Finding | File | Line | Severity |
|---------|------|------|----------|
| Transfer Hook not validated | <path> | <N> | Critical |
| Permanent Delegate not checked | <path> | <N> | Critical |
| Missing extension enumeration | <path> | <N> | Medium |
| ... | ... | ... | ... |

### Compute optimization opportunities:

| Type | Count | Impact |
|------|-------|--------|
| Missing zero-copy | <N> | Reduced CU usage on large accounts |
| Redundant account loads | <N> | ~100 CU per redundant load |
| Excessive msg! calls | <N> | ~100 CU per msg! |
| ... | ... | ... |

---

## Phase 6: Vulnerability Scan (Optional)

<If a dedicated Solana vulnerability scanner was run (Soteria, Trident, Solazy, etc.),
include its findings here grouped by severity.>

<If no scanner was available, include this recommendation:>

> **Recommended next step:** Run a dedicated vulnerability scanner for deeper analysis.
> Suggested tools:
> - **Trident** (Ackee Blockchain) — fuzz testing framework (`cargo install trident-cli`)
> - **Soteria / sec3** — static analysis for Anchor programs
> - **Solazy** — SAST + reverse engineering CLI
> - **cargo-geiger** — unsafe Rust usage across dependency tree

---

## Appendix: Full Findings List

<Complete list of all findings, sorted by severity (Critical > High > Medium > Low > Info),
with file paths, line numbers, descriptions, and suggested fixes.>
```

---

## Scoring Rules

### Test Coverage Score
Direct mapping: coverage percentage = score.
If coverage tools failed to run (missing dependency, compilation error), score is 0.

### Documentation Score
`(fully_documented_pub_items / total_pub_items) * 100`
An item counts as "fully documented" only if it has a `///` doc comment.

### Code Hygiene Score
Start at 100. Deductions:
- println!/dbg! in production: -15 each
- Missing overflow-checks in release profile: -15
- TODO/FIXME: -3 each (cap at -30)
- Commented-out code blocks: -2 each (cap at -20)
- Dead code: -5 each
- unsafe without justification: -10 each

### Dependencies Score
Start at 100. Deductions:
- Known CVE in dependency: -20 each (critical), -10 (others)
- Outdated by major version: -15 each
- Yanked crate: -15 each
- Missing Cargo.lock: -10
- Outdated by minor version: -5 each
- Duplicate versions of same crate: -5 each

### Best Practices Score
Start at 100. Deductions:
- Missing signer check: -15 each
- Missing owner check: -15 each
- Pubkey-only authority (no signer): -15 each
- Arbitrary CPI target: -15 each
- Account revival after close: -15 each
- Transfer Hook not validated: -15 each
- Permanent Delegate not checked: -15 each
- AccountInfo as CPI program: -15 each
- Missing has_one/seed constraint: -10 each
- Shared PDA across domains: -10 each
- init_if_needed usage: -10 each
- Missing mint/authority validation: -10 each
- Token-2022 extension not enumerated: -10 each (cap at -30)
- Direct arithmetic without overflow protection: -10 each (cap at -30)
- Close without cleanup: -10 each
- PDA seed collision risk: -5 each
- Hardcoded lamports in create_account: -5 each
- as cast between int widths: -5 each (cap at -15)
- Missing event/log on state change: -3 each (cap at -30)
- unwrap() on user input: -3 each (cap at -15)
- Vec operations in loops (no pre-alloc): -2 each (cap at -10)

## Verdicts

- 90-100: ✅ **Audit Ready** — Your codebase meets the standard. Proceed with scheduling your audit.
- 75-89: ⚠️ **Almost Ready** — A few items to address. Most audit firms would accept this but you'd get cleaner results by fixing the flagged items first.
- 50-74: 🔶 **Needs Work** — Significant preparation needed. Address the findings before engaging auditors to avoid wasting their time on preventable issues.
- Below 50: ❌ **Not Ready** — Major gaps in testing, documentation, or code quality. Investing time here first will dramatically improve the value you get from an audit.

## references/shared-rules.md

# Shared Rules

## Output Format

Every assigned phase MUST use this exact structure:

```
PHASE <N> | <Name> | SCORE: <X>/100

FAIL | <check> | <-N> | <file:line or n/a>
desc: <one factual sentence — what is wrong>
fix: <one sentence — specific action to fix it>

PASS | <check>
note: <brief evidence>

END PHASE <N>
```

Rules:
- Every assigned phase MUST appear between PHASE and END markers
- FAIL needs: check name, deduction, file location (or `n/a`)
- `desc:` = factual problem statement
- `fix:` = specific actionable instruction (command to run, file to create, code to change)
- PASS needs: check name, optional `note:` with evidence
- Score = 100 minus deductions (min 0, max 100). Apply deduction caps from your checklist.
- One blank line between each FAIL/PASS block

## DO NOT Report

Never flag: compute/gas optimizations (CU reduction, zero-copy suggestions, clone removal),
functions >60 lines, magic numbers, naming conventions, code style.
These are informational and do not affect audit readiness.

## DO NOT Do

- Do NOT perform security vulnerability analysis or threat modeling
- Do NOT suggest architecture changes or redesigns
- Do NOT produce prose, tables, summaries, or markdown formatting
- Do NOT output anything except the structured PHASE/FAIL/PASS format above
- Do NOT analyze files outside the project directory

## Scope

Only the project's own program source (programs/*/src/ or src/, excluding target/, tests/, test/, node_modules/, .anchor/).
- Inline `//` comments explaining purpose = documented (not a finding)
- `#[msg("...")]` on error variants = documented (not a finding)
- `/// CHECK:` on UncheckedAccount = documented (not a finding)
- `unsafe` with `// SAFETY:` = justified (INFO only, no deduction)
- Pinned older dependency versions in audited code = INFO only (no deduction)

