Solana Smart Contract Best Practices (Audits)
Common Security Issues
- Signer enforcement
- Typed accounts
- Ownership validation
- PDA patterns
- Checked arithmetic
- Input validation
- Error handling
- Account space
- CPI account reloading
- Compute units
- Upgradeability
- Testing
- Token-2022 extension security
Index
Reference Files
- DEVELOPMENT_PATTERNS.md -- 14 practices with full vulnerable/secure code examples
- COMMON_MISTAKES.md -- 31 vulnerability patterns + 4 case studies
- TOKEN_2022_SECURITY.md -- Token-2022 extension security (9 patterns)
- SECURITY_TESTING.md -- TDD-style exploit tests for each vulnerability class
14 Practice Areas
31 Vulnerability Patterns
| # |
Vulnerability |
Severity |
| 1-4 |
Arithmetic (overflow, precision, saturating, division by zero) |
High |
| 5 |
Unhandled errors |
High |
| 6-12 |
Account validation (permission, signer, writable, owner, init, PDA, system) |
High-Critical |
| 13-15 |
State management (lamports, oracle, ownership reset) |
Low-High |
| 16 |
Account reloading after CPI |
High |
| 17 |
Casting vulnerabilities (as casts) |
High |
| 18 |
Authority transfer pitfalls |
High |
| 19 |
Account data reallocation |
Medium |
| 20 |
CPI signer pitfalls |
Critical |
| 21 |
Security dependency chain |
High |
| 22 |
Frontrunning / slippage |
High |
| 23 |
Remaining accounts validation |
Medium |
| 24 |
Unsafe Rust |
High |
| 25 |
Vector length bug |
Medium |
| 26 |
Seed collisions |
High |
| 27 |
Dangling pointers |
High |
| 28 |
Account reassignment bug |
Medium |
| 29 |
Heap exhaustion (32KB limit) |
Medium |
| 30 |
Account constraint fragility |
Medium |
| 31 |
Ed25519 introspection |
High |
Token-2022 Security (9 patterns)
| Pattern |
Severity |
| Token-agnostic interface |
High |
| Pre-created ATAs |
Medium |
| SPL token validation |
High |
| CPIGuard extension |
High |
| Default account state |
Medium |
| Mint close authority |
High |
| Permanent delegate |
Critical |
| Transfer hook |
High |
| Transfer fees |
High |
Case Studies
| Exploit |
Impact |
Root Cause |
| Wormhole Bridge |
$320M+ |
Missing sysvar validation |
| Jet Protocol |
-- |
PDA without caller validation |
| Mango Markets |
$115M |
Oracle price manipulation |
| Cashio |
$48M |
Missing account validation |
When to Use
- Writing new Solana/Anchor programs from scratch
- Reviewing pull requests that add or modify program logic
- Refactoring existing programs for security and maintainability
- Preparing a program for mainnet deployment
- Integrating Token-2022 tokens or extensions
- Onboarding developers to Solana best practices
- Post-audit remediation work
When NOT to Use
- For vulnerability scanning of deployed programs (use
solana-security-audit instead)
- For non-Solana blockchain code
- For off-chain client/frontend code only
- When the codebase is a Solana SDK library, not a program
Rationalizations to Reject
- "Rust prevents overflow by default" -- Only in debug mode. Release builds wrap silently. Always use
checked_*() arithmetic or set overflow-checks = true in Cargo.toml.
- "Anchor handles everything" -- Only when you use the correct types.
AccountInfo<'info> bypasses all checks. unwrap() panics your program.
- "We'll add validation later" -- Validation is not a feature; it's structural. Missing it at write-time means missing it at audit-time.
- "The space calculation is close enough" -- Off-by-one in account space causes silent data truncation or allocation failure. Calculate exactly.
- "We don't need tests for constraints" -- Constraints are your security boundary. Every
has_one, constraint, and seeds must have a negative test.
- "The account data is fresh, we just wrote it" -- After CPI, Anchor's deserialized account structs are stale. Always call
.reload().
- "Token-2022 is just like SPL Token" -- Token-2022 extensions (transfer fees, permanent delegates, CPI guards) change fundamental assumptions. Check every extension.
- "We only accept known tokens" -- Governance changes or new pools can introduce Token-2022 tokens. Code defensively.
How This Skill Works
When invoked, follow a two-phase approach: Discover, then Fix.
Phase 1: Discover (TDD Red)
- Scan for Solana programs in the codebase
- Check each practice area against the 14 development patterns
- Scan for vulnerability patterns across all 31 common mistakes
- Check Token-2022 compatibility if token operations are present
- Report findings grouped by severity (Block Deployment / Fix Before Mainnet / Improve)
- For each finding, write an exploit test that proves the vulnerability exists
- Use the test patterns from SECURITY_TESTING.md
- The exploit test should PASS when the vulnerability is present (red = vulnerable)
- This provides evidence and a regression test
Phase 2: Fix (TDD Green)
- Apply the fix using the secure code patterns from the reference files
- Run the exploit test again -- it should now FAIL (green = fixed)
- Write a verification test that confirms the correct behavior
- Run the full test suite to ensure no regressions
This TDD approach ensures:
- Every vulnerability has proof (the exploit test)
- Every fix has verification (the exploit test now fails)
- No regressions in existing functionality
Quick Reference: 14 Practice Areas
| # |
Practice |
Category |
Key Check |
| 1 |
Signer Checks |
Security |
Signer<'info> + has_one on all authority ops |
| 2 |
Typed Accounts |
Security |
Account<'info,T>, Program<'info,T> not AccountInfo |
| 3 |
Ownership & Constraints |
Security |
has_one, constraint, input length validation |
| 4 |
PDA Usage |
Security |
seeds + bump, stored bump, unique seeds per entity |
| 5 |
Input Validation |
Security |
checked_*() arithmetic, range checks, bounds checks |
| 6 |
Error Handling |
Reliability |
#[error_code], require!, no unwrap()/panic! |
| 7 |
Account Space |
Correctness |
Exact calculation: 8 + (4+len) + fields |
| 8 |
Account Reloading |
Correctness |
.reload() after CPI before reading account data |
| 9 |
Code Reusability |
Maintainability |
CPIs, shared crates, modular instruction handlers |
| 10 |
Documentation |
Maintainability |
/// doc comments, /// CHECK: on unchecked accounts |
| 11 |
Testing |
Quality |
Unit + integration + negative tests, solana-bankrun |
| 12 |
Security Audits |
Quality |
cargo-audit, clippy, professional audit before mainnet |
| 13 |
Upgradeability |
Operations |
PDA storage, account versioning, multisig authority |
| 14 |
Compute Units |
Performance |
Profile CU, ComputeBudgetInstruction, split heavy txs |
Review Workflow
Step 1: Identify Programs
rg "#\[program\]" programs/
rg "anchor-lang" Cargo.toml
Step 2: Security Checks (Practices 1-5)
# Raw AccountInfo (Practice 2)
rg "AccountInfo<'info>" programs/
# Missing signer types (Practice 1)
rg "authority.*AccountInfo|admin.*AccountInfo|owner.*AccountInfo" programs/
# Missing constraints (Practice 3)
rg "#\[derive\(Accounts\)\]" programs/ -A 20
# PDA patterns (Practice 4)
rg "seeds\s*=" programs/
rg "bump\s*=" programs/
# Unsafe arithmetic (Practice 5)
rg "\+\s*amount|\-\s*amount|\*\s*amount|/\s*amount" programs/
rg "checked_add|checked_sub|checked_mul|checked_div" programs/
# Unsafe casts (Vulnerability 17)
rg "\bas\s+(u8|u16|u32|u64|i8|i16|i32|i64)" programs/
rg "try_from" programs/
Step 3: Reliability Checks (Practice 6)
# unwrap/panic in production code
rg "\.unwrap\(\)|panic!\(" programs/
# Custom error types
rg "#\[error_code\]" programs/
rg "require!\(" programs/
# Unsafe blocks (Vulnerability 24)
rg "unsafe\s*\{" programs/
Step 4: Correctness Checks (Practices 7-8)
# Account space calculations
rg "space\s*=" programs/
# CPI followed by account reads (needs reload)
rg "invoke\(|invoke_signed\(|mint_to\(|transfer\(" programs/ -A 5
rg "\.reload\(\)" programs/
# Remaining accounts (Vulnerability 23)
rg "remaining_accounts" programs/
Step 5: Token-2022 Checks
# Check if using token operations
rg "token::|token_interface::|TokenInterface|TokenAccount" programs/
# Check for transfer_checked vs transfer
rg "token::transfer\b" programs/ # Should be transfer_checked
# Check for Interface vs Program types
rg "Program<'info,\s*Token>" programs/ # Should be Interface<TokenInterface>
# Token-2022 extension checks
rg "get_extension|StateWithExtensions" programs/
Step 6: Advanced Security Checks
# Authority transfer patterns (Vulnerability 18)
rg "authority|admin|owner" programs/ -A 3
# Slippage protection (Vulnerability 22)
rg "swap|trade|exchange" programs/
rg "minimum_amount|slippage|deadline" programs/
# Seed collision risk (Vulnerability 26)
rg "seeds\s*=" programs/ | sort
# Heap usage (Vulnerability 29)
rg "Vec::with_capacity|Vec::new|vec!\[" programs/
# Overflow checks in Cargo.toml
rg "overflow-checks" Cargo.toml
Step 7: Quality Checks (Practices 9-14)
# Documentation
rg "/// CHECK:" programs/
rg "///\s" programs/
# Test coverage
ls tests/
rg "#\[test\]|#\[should_panic\]|it\(" tests/
Reporting Format
## [CATEGORY] Practice #N: Practice Name
**Location**: `programs/my-program/src/lib.rs:45`
**Issue**: Description of what's wrong.
**Current Code**:
(vulnerable code block)
**Recommended Fix**:
(secure code block)
**Why**: Explanation of the risk and how the fix prevents it.
Priority Guidelines
Block Deployment (Critical)
- Missing signer checks on authority operations (#1)
- Raw
AccountInfo where typed accounts are needed (#2)
- No ownership validation on mutable operations (#3)
- Unchecked arithmetic in financial calculations (#5)
unwrap() or panic! in production code (#6)
- CPI signer forwarding to untrusted programs (V20)
- Permanent delegate tokens accepted without checks (Token-2022)
- No slippage protection on swaps (V22)
Fix Before Mainnet (High)
- Incorrect account space calculations (#7)
- Missing
.reload() after CPI (#8)
- No PDA seeds or non-deterministic accounts (#4)
- No tests for security constraints (#11)
- No professional audit (#12)
- Unsafe
as casts on user input (V17)
- Single-step authority transfer (V18)
- Unvalidated remaining accounts (V23)
- Seed collisions between features (V26)
- Transfer fees not accounted for (Token-2022)
- Missing
overflow-checks = true in Cargo.toml
Improve for Maintainability (Medium)
- Missing documentation and
/// CHECK: comments (#10)
- Non-modular instruction handlers (#9)
- No upgrade strategy (#13)
- Unoptimized compute usage (#14)
- No Token-2022 compatibility
Additional Resources
1---2name: solana-best-practices3description: Reviews Solana/Anchor programs for development best practices. Use when writing, reviewing, improving or auditing Solana smart contracts. 31 vulnerability patterns with 4 real-world case studies.4---56# Solana Smart Contract Best Practices (Audits)78## Common Security Issues9 - Signer enforcement10 - Typed accounts11 - Ownership validation12 - PDA patterns13 - Checked arithmetic14 - Input validation15 - Error handling16 - Account space17 - CPI account reloading18 - Compute units19 - Upgradeability20 - Testing21 - Token-2022 extension security2223## Index2425### Reference Files26- [DEVELOPMENT_PATTERNS.md](references/DEVELOPMENT_PATTERNS.md) -- 14 practices with full vulnerable/secure code examples27- [COMMON_MISTAKES.md](references/COMMON_MISTAKES.md) -- 31 vulnerability patterns + 4 case studies28- [TOKEN_2022_SECURITY.md](references/TOKEN_2022_SECURITY.md) -- Token-2022 extension security (9 patterns)29- [SECURITY_TESTING.md](references/SECURITY_TESTING.md) -- TDD-style exploit tests for each vulnerability class3031### 14 Practice Areas32| # | Practice | Category |33|---|----------|----------|34| 1 | [Signer Checks](#quick-reference-14-practice-areas) | Security |35| 2 | [Typed Accounts](#quick-reference-14-practice-areas) | Security |36| 3 | [Ownership & Constraints](#quick-reference-14-practice-areas) | Security |37| 4 | [PDA Usage](#quick-reference-14-practice-areas) | Security |38| 5 | [Input Validation](#quick-reference-14-practice-areas) | Security |39| 6 | [Error Handling](#quick-reference-14-practice-areas) | Reliability |40| 7 | [Account Space](#quick-reference-14-practice-areas) | Correctness |41| 8 | [Account Reloading](#quick-reference-14-practice-areas) | Correctness |42| 9 | [Code Reusability](#quick-reference-14-practice-areas) | Maintainability |43| 10 | [Documentation](#quick-reference-14-practice-areas) | Maintainability |44| 11 | [Testing](#quick-reference-14-practice-areas) | Quality |45| 12 | [Security Audits](#quick-reference-14-practice-areas) | Quality |46| 13 | [Upgradeability](#quick-reference-14-practice-areas) | Operations |47| 14 | [Compute Units](#quick-reference-14-practice-areas) | Performance |4849### 31 Vulnerability Patterns50| # | Vulnerability | Severity |51|---|--------------|----------|52| 1-4 | Arithmetic (overflow, precision, saturating, division by zero) | High |53| 5 | Unhandled errors | High |54| 6-12 | Account validation (permission, signer, writable, owner, init, PDA, system) | High-Critical |55| 13-15 | State management (lamports, oracle, ownership reset) | Low-High |56| 16 | Account reloading after CPI | High |57| 17 | Casting vulnerabilities (`as` casts) | High |58| 18 | Authority transfer pitfalls | High |59| 19 | Account data reallocation | Medium |60| 20 | CPI signer pitfalls | Critical |61| 21 | Security dependency chain | High |62| 22 | Frontrunning / slippage | High |63| 23 | Remaining accounts validation | Medium |64| 24 | Unsafe Rust | High |65| 25 | Vector length bug | Medium |66| 26 | Seed collisions | High |67| 27 | Dangling pointers | High |68| 28 | Account reassignment bug | Medium |69| 29 | Heap exhaustion (32KB limit) | Medium |70| 30 | Account constraint fragility | Medium |71| 31 | Ed25519 introspection | High |7273### Token-2022 Security (9 patterns)74| Pattern | Severity |75|---------|----------|76| Token-agnostic interface | High |77| Pre-created ATAs | Medium |78| SPL token validation | High |79| CPIGuard extension | High |80| Default account state | Medium |81| Mint close authority | High |82| Permanent delegate | Critical |83| Transfer hook | High |84| Transfer fees | High |8586### Case Studies87| Exploit | Impact | Root Cause |88|---------|--------|------------|89| Wormhole Bridge | $320M+ | Missing sysvar validation |90| Jet Protocol | -- | PDA without caller validation |91| Mango Markets | $115M | Oracle price manipulation |92| Cashio | $48M | Missing account validation |9394---9596## When to Use9798- Writing new Solana/Anchor programs from scratch99- Reviewing pull requests that add or modify program logic100- Refactoring existing programs for security and maintainability101- Preparing a program for mainnet deployment102- Integrating Token-2022 tokens or extensions103- Onboarding developers to Solana best practices104- Post-audit remediation work105106## When NOT to Use107108- For vulnerability scanning of deployed programs (use `solana-security-audit` instead)109- For non-Solana blockchain code110- For off-chain client/frontend code only111- When the codebase is a Solana SDK library, not a program112113## Rationalizations to Reject114115- "Rust prevents overflow by default" -- Only in debug mode. Release builds wrap silently. Always use `checked_*()` arithmetic or set `overflow-checks = true` in Cargo.toml.116- "Anchor handles everything" -- Only when you use the correct types. `AccountInfo<'info>` bypasses all checks. `unwrap()` panics your program.117- "We'll add validation later" -- Validation is not a feature; it's structural. Missing it at write-time means missing it at audit-time.118- "The space calculation is close enough" -- Off-by-one in account space causes silent data truncation or allocation failure. Calculate exactly.119- "We don't need tests for constraints" -- Constraints are your security boundary. Every `has_one`, `constraint`, and `seeds` must have a negative test.120- "The account data is fresh, we just wrote it" -- After CPI, Anchor's deserialized account structs are stale. Always call `.reload()`.121- "Token-2022 is just like SPL Token" -- Token-2022 extensions (transfer fees, permanent delegates, CPI guards) change fundamental assumptions. Check every extension.122- "We only accept known tokens" -- Governance changes or new pools can introduce Token-2022 tokens. Code defensively.123124## How This Skill Works125126When invoked, follow a two-phase approach: **Discover**, then **Fix**.127128### Phase 1: Discover (TDD Red)1291301. **Scan for Solana programs** in the codebase1312. **Check each practice area** against the 14 development patterns1323. **Scan for vulnerability patterns** across all 31 common mistakes1334. **Check Token-2022 compatibility** if token operations are present1345. **Report findings** grouped by severity (Block Deployment / Fix Before Mainnet / Improve)1356. **For each finding, write an exploit test** that proves the vulnerability exists136 - Use the test patterns from [SECURITY_TESTING.md](references/SECURITY_TESTING.md)137 - The exploit test should PASS when the vulnerability is present (red = vulnerable)138 - This provides evidence and a regression test139140### Phase 2: Fix (TDD Green)1411427. **Apply the fix** using the secure code patterns from the reference files1438. **Run the exploit test again** -- it should now FAIL (green = fixed)1449. **Write a verification test** that confirms the correct behavior14510. **Run the full test suite** to ensure no regressions146147This TDD approach ensures:148- Every vulnerability has **proof** (the exploit test)149- Every fix has **verification** (the exploit test now fails)150- **No regressions** in existing functionality151152## Quick Reference: 14 Practice Areas153154| # | Practice | Category | Key Check |155|---|----------|----------|-----------|156| 1 | Signer Checks | Security | `Signer<'info>` + `has_one` on all authority ops |157| 2 | Typed Accounts | Security | `Account<'info,T>`, `Program<'info,T>` not `AccountInfo` |158| 3 | Ownership & Constraints | Security | `has_one`, `constraint`, input length validation |159| 4 | PDA Usage | Security | `seeds` + `bump`, stored bump, unique seeds per entity |160| 5 | Input Validation | Security | `checked_*()` arithmetic, range checks, bounds checks |161| 6 | Error Handling | Reliability | `#[error_code]`, `require!`, no `unwrap()`/`panic!` |162| 7 | Account Space | Correctness | Exact calculation: `8 + (4+len) + fields` |163| 8 | Account Reloading | Correctness | `.reload()` after CPI before reading account data |164| 9 | Code Reusability | Maintainability | CPIs, shared crates, modular instruction handlers |165| 10 | Documentation | Maintainability | `///` doc comments, `/// CHECK:` on unchecked accounts |166| 11 | Testing | Quality | Unit + integration + negative tests, `solana-bankrun` |167| 12 | Security Audits | Quality | `cargo-audit`, `clippy`, professional audit before mainnet |168| 13 | Upgradeability | Operations | PDA storage, account versioning, multisig authority |169| 14 | Compute Units | Performance | Profile CU, `ComputeBudgetInstruction`, split heavy txs |170171## Review Workflow172173### Step 1: Identify Programs174175```bash176rg "#\[program\]" programs/177rg "anchor-lang" Cargo.toml178```179180### Step 2: Security Checks (Practices 1-5)181182```bash183# Raw AccountInfo (Practice 2)184rg "AccountInfo<'info>" programs/185186# Missing signer types (Practice 1)187rg "authority.*AccountInfo|admin.*AccountInfo|owner.*AccountInfo" programs/188189# Missing constraints (Practice 3)190rg "#\[derive\(Accounts\)\]" programs/ -A 20191192# PDA patterns (Practice 4)193rg "seeds\s*=" programs/194rg "bump\s*=" programs/195196# Unsafe arithmetic (Practice 5)197rg "\+\s*amount|\-\s*amount|\*\s*amount|/\s*amount" programs/198rg "checked_add|checked_sub|checked_mul|checked_div" programs/199200# Unsafe casts (Vulnerability 17)201rg "\bas\s+(u8|u16|u32|u64|i8|i16|i32|i64)" programs/202rg "try_from" programs/203```204205### Step 3: Reliability Checks (Practice 6)206207```bash208# unwrap/panic in production code209rg "\.unwrap\(\)|panic!\(" programs/210211# Custom error types212rg "#\[error_code\]" programs/213rg "require!\(" programs/214215# Unsafe blocks (Vulnerability 24)216rg "unsafe\s*\{" programs/217```218219### Step 4: Correctness Checks (Practices 7-8)220221```bash222# Account space calculations223rg "space\s*=" programs/224225# CPI followed by account reads (needs reload)226rg "invoke\(|invoke_signed\(|mint_to\(|transfer\(" programs/ -A 5227rg "\.reload\(\)" programs/228229# Remaining accounts (Vulnerability 23)230rg "remaining_accounts" programs/231```232233### Step 5: Token-2022 Checks234235```bash236# Check if using token operations237rg "token::|token_interface::|TokenInterface|TokenAccount" programs/238239# Check for transfer_checked vs transfer240rg "token::transfer\b" programs/ # Should be transfer_checked241242# Check for Interface vs Program types243rg "Program<'info,\s*Token>" programs/ # Should be Interface<TokenInterface>244245# Token-2022 extension checks246rg "get_extension|StateWithExtensions" programs/247```248249### Step 6: Advanced Security Checks250251```bash252# Authority transfer patterns (Vulnerability 18)253rg "authority|admin|owner" programs/ -A 3254255# Slippage protection (Vulnerability 22)256rg "swap|trade|exchange" programs/257rg "minimum_amount|slippage|deadline" programs/258259# Seed collision risk (Vulnerability 26)260rg "seeds\s*=" programs/ | sort261262# Heap usage (Vulnerability 29)263rg "Vec::with_capacity|Vec::new|vec!\[" programs/264265# Overflow checks in Cargo.toml266rg "overflow-checks" Cargo.toml267```268269### Step 7: Quality Checks (Practices 9-14)270271```bash272# Documentation273rg "/// CHECK:" programs/274rg "///\s" programs/275276# Test coverage277ls tests/278rg "#\[test\]|#\[should_panic\]|it\(" tests/279```280281## Reporting Format282283```markdown284## [CATEGORY] Practice #N: Practice Name285286**Location**: `programs/my-program/src/lib.rs:45`287288**Issue**: Description of what's wrong.289290**Current Code**:291(vulnerable code block)292293**Recommended Fix**:294(secure code block)295296**Why**: Explanation of the risk and how the fix prevents it.297```298299## Priority Guidelines300301### Block Deployment (Critical)302- Missing signer checks on authority operations (#1)303- Raw `AccountInfo` where typed accounts are needed (#2)304- No ownership validation on mutable operations (#3)305- Unchecked arithmetic in financial calculations (#5)306- `unwrap()` or `panic!` in production code (#6)307- CPI signer forwarding to untrusted programs (V20)308- Permanent delegate tokens accepted without checks (Token-2022)309- No slippage protection on swaps (V22)310311### Fix Before Mainnet (High)312- Incorrect account space calculations (#7)313- Missing `.reload()` after CPI (#8)314- No PDA seeds or non-deterministic accounts (#4)315- No tests for security constraints (#11)316- No professional audit (#12)317- Unsafe `as` casts on user input (V17)318- Single-step authority transfer (V18)319- Unvalidated remaining accounts (V23)320- Seed collisions between features (V26)321- Transfer fees not accounted for (Token-2022)322- Missing `overflow-checks = true` in Cargo.toml323324### Improve for Maintainability (Medium)325- Missing documentation and `/// CHECK:` comments (#10)326- Non-modular instruction handlers (#9)327- No upgrade strategy (#13)328- Unoptimized compute usage (#14)329- No Token-2022 compatibility330331## Additional Resources332333- [SlowMist Solana Security Best Practices](https://github.com/slowmist/solana-smart-contract-security-best-practices) (original source)334- [Solana Program Security Best Practices](https://github.com/bigjoefilms/Solana-program-development-security-best-practices)335- [Zealynx Solana Security Checklist](https://www.zealynx.io/blogs/solana-security-checklist)336- [Helius Security Guide](https://www.helius.dev/blog/a-hitchhikers-guide-to-solana-program-security)337- [Anchor Documentation](https://www.anchor-lang.com/docs)338- [Solana Toolkit Best Practices](https://solana.com/docs/toolkit/best-practices)339- [Anchor Account Constraints](https://www.anchor-lang.com/docs/references/account-constraints)