CPI Best Practices
CPIs extend your program's blast radius. These rules keep invocations minimal, verifiable, and compatible with Agave 4.1.1 limits.
How to Use This List
- Map CPI graph on whiteboard before coding.
- Allowlist external program ids in config account.
- Simulate CU and depth for worst-case paths.
A - Safety
- Allowlist callee program IDs; reject user-supplied program accounts. Blocks malicious reentrancy and drainer CPIs.
- Apply checks-effects-interactions: persist state before external CPI. Mitigates reentrancy-style double spends.
- Never escalate signer or writable privileges beyond the outer transaction. Prevents privilege escalation bugs.
- Validate SPL token mints and authorities immediately before token CPI. Stops cross-mint drain bugs.
- Propagate CPI errors with
?unless explicitly handling. Avoids silent partial failure assumptions.
B - Efficiency
- Minimize CPI count per instruction; batch when semantics allow. Saves depth and CU.
- Avoid logging inside CPI-heavy loops. CU multiplication.
- Prefer flat call graphs over depth-4 chains. Reliability under limits.
- Profile with simulation in CI for top instructions. Regression detection.
- Use spl/anchor helpers for instruction encoding. Fewer layout bugs.
C - Operations
- Document account meta order for each CPI in program spec. Client and audit alignment.
- Pin partner program versions and monitor upgrades. Breaking CPI layout changes.
- Test malicious callee stubs in LiteSVM. Reentrancy coverage.
- Separate admin config updates from user CPI paths. Governance clarity.
- Record CPI allowlist changes in changelog. Incident response.
FAQs
Anchor CPI safe?
Only if you still validate accounts and ordering.
How many CPIs per ix?
As few as possible - profile.
invoke_signed audit?
Highest priority.
Token-2022?
Separate program id in allowlist.
Closed program CPI?
No arbitrary user programs.
Open router?
High risk - expert review.
Depth test?
Nest until failure in sim.
CPI events?
Log off-chain from meta.
Failed CPI rollback?
Whole tx atomic.
Surfpool?
Default local CPI testing.
Agave upgrade?
Re-run CPI suite.
Immutable program?
Allowlist frozen - plan carefully.
Related
- CPI Basics - Intro
- PDA Best Practices - Signing
- Native Programs Best Practices - Validation
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.