Instructions Best Practices
Small, validated, single-purpose handlers scale better than god-instructions.
How to Use This List
- Review each handler for single responsibility.
- Ensure errors are typed and documented in IDL.
- Profile CU on hot paths before mainnet.
A - Handler design
- One clear action per instruction avoid multi-mode opcodes.
- Validate args with require! early before CPIs or transfers.
- Delegate complex logic to modules keep #[program] thin.
- Emit events for state changes clients should not parse logs by hand.
B - Accounts and CPIs
- Validate CPI programs in accounts struct not inside unchecked metas.
- Use ctx.bumps for PDA CPI signers do not re-derive bumps.
- Document remaining_accounts order in IDL docs or constants.
- Prefer explicit accounts over args for pubkeys that must sign.
FAQs
What Anchor version is assumed?
0.32.1 throughout this section.
Can a PDA be a Signer in accounts struct?
No. Use seeds constraints and CPI signing.
Where is bump stored?
In your account struct field, set at initialization.
How do clients derive PDAs?
Use @solana/kit 7.0.0 with matching seed bytes.
What program id is used for PDAs?
Your Anchor program's declare_id address.
Do seeds include bump?
Not in seeds array; bump is separate parameter to find_program_address.
How to debug PDA failures?
Compare logged keys; verify seeds and program id client-side.
Are PDAs rent-exempt?
Yes when holding data; fund with payer on init.
Can one PDA sign multiple CPIs in one ix?
Yes with same signer seeds for each CPI.
What to read next?
See Related links for deeper instructions bp topics.
Related
- Instruction Handlers - Context
- CPIs in Anchor Best Practices - CPI rules
- Errors & Events Best Practices - observability
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.