Anchor turns account validation into declarations, which removes whole classes of bugs. But Anchor only checks what you tell it to check. Run these 16 checks on any Anchor program before sending it to an auditor. This list is preparation for an audit, not a replacement for one.
Accounts and signers
- [ ] Use
Signerfor every account that must authorize the instruction. A plain account orUncheckedAccountis not checked for a signature. - [ ] Tie stored authorities to the signer with
has_oneor an explicit constraint, for example#[account(mut, has_one = authority)]. - [ ] Justify every
UncheckedAccountandAccountInfo: validate owner, key or data yourself. - [ ] Prevent the same account being passed twice into two mutable slots, for example
from.key() != to.key().
PDAs and initialization
- [ ] Validate PDAs with
seedsandbumpin the account constraint, and store the canonical bump. - [ ] Design seeds so users cannot collide: include the user or the parent account.
- [ ] Avoid
init_if_neededunless you have a reason, and check it cannot reset balances or owners. - [ ] Close accounts with the
closeconstraint instead of draining lamports by hand.
Tokens and CPIs
- [ ] Constrain token accounts by mint and authority (
token::mint,token::authorityor associated token constraints). - [ ] Use
Program<>orInterface<>types for programs you call, so the program ID is checked. - [ ] Decide on Token-2022 support explicitly and review extensions such as transfer fees and transfer hooks.
- [ ] Scope PDA signer seeds tightly: separate PDAs for vaults, authorities and configuration.
Math, upgrades and testing
- [ ] Use checked arithmetic and keep
overflow-checks = truein the release profile. Round in the protocol's favour. - [ ] Validate
remaining_accountsby hand: Anchor does no validation on them. - [ ] Plan account layout changes before upgrades: version accounts or reserve space, use
realloccarefully. - [ ] Test the failure paths (wrong signer, wrong mint, duplicated accounts, zero and maximum amounts) and fuzz the rest, for example with Trident.
What to do with the results
Fix what you find, write down the invariants your program must always keep, and send both to your auditor with a frozen commit. Before mainnet, also go through the pre-launch checklist in the GitHub repository below.
Full article with FAQ: https://orivions.com/blog/anchor-security-checklist
All three checklists on GitHub: https://github.com/JakeMalarczyk/solana-security-checklists
Top comments (0)