30 Common Mistakes Solana Developers Make (And How to Avoid Them)
Solana's account model and Rust-based development create unique pitfalls that catch even experienced developers. Here are the most common mistakes and how to avoid them.
Account Validation Failures
Missing account ownership check
criticalNot verifying that accounts are owned by expected programs allows attackers to pass fake accounts.
Fix: Always check account.owner matches expected program ID. Anchor does this automatically with #[account()].
Not validating account discriminators
highWithout discriminator checks, wrong account types can be passed to instructions.
Fix: Use Anchor's automatic discriminator validation. In native, implement manual type checks.
Missing signer validation
criticalNot checking that required accounts have actually signed the transaction.
Fix: Always verify is_signer for accounts that should authorize the action.
Trusting account data without validation
highAssuming account data is correctly formatted without deserializing and validating.
Fix: Always deserialize and validate account data. Handle deserialization errors.
Not checking account mutability
mediumAttempting to write to accounts not marked as writable.
Fix: Mark accounts as writable with #[account(mut)] or is_writable checks.
PDA Problems
Inconsistent PDA seeds
highUsing different seeds for derivation and validation causes lookup failures.
Fix: Centralize seed generation. Use constants for seed strings.
Not storing bump in account
mediumRecalculating bump wastes compute units and can fail.
Fix: Store bump seed in the account data. Pass stored bump for signing.
Using find_program_address in instruction handlers
mediumfind_program_address is expensive. Calling it repeatedly wastes compute.
Fix: Derive PDA client-side and pass as account. Verify with create_program_address.
Wrong program ID in PDA derivation
highUsing wrong program ID creates PDAs that can't sign for your program.
Fix: Always use your program's ID for PDA derivation.
Seeds too long
mediumPDA seeds have a maximum total length of 32 bytes.
Fix: Hash long seeds or restructure to stay under limit.
Token Handling Errors
Not checking token mint
criticalToken accounts can hold any SPL token. Not validating mint allows wrong tokens.
Fix: Always validate token_account.mint matches expected mint.
Ignoring token decimals
highCalculating amounts without considering decimals leads to wrong values.
Fix: Always account for token decimals in calculations.
Not closing empty accounts
lowEmpty token accounts still cost rent. Not closing them leaks SOL.
Fix: Close token accounts when emptied to recover rent.
Wrong token program ID
mediumToken-2022 uses different program ID than SPL Token.
Fix: Check token_program matches account.owner.
Not handling frozen accounts
mediumTransfers to/from frozen accounts fail silently or with confusing errors.
Fix: Check account freeze state before transfers.
Arithmetic Issues
Integer overflow/underflow
highRust's release mode doesn't check for overflow by default.
Fix: Use checked_add, checked_sub, checked_mul for all arithmetic.
Precision loss in division
highInteger division truncates. Order of operations matters for precision.
Fix: Multiply before dividing. Use fixed-point math for precision.
Rounding in wrong direction
mediumRounding errors can be exploited over many transactions.
Fix: Round in favor of the protocol, not the user.
Using u64 for timestamps
lowSolana Clock uses i64 for timestamps. Type mismatch causes issues.
Fix: Use i64 for timestamp handling. Cast carefully.
CPI Vulnerabilities
CPI to arbitrary programs
criticalNot validating target program allows attackers to redirect CPIs.
Fix: Hardcode expected program IDs or validate against known addresses.
Missing signer seeds in CPI
highPDA-signed CPIs without seeds fail authorization.
Fix: Pass correct signer_seeds when PDA needs to sign CPI.
Reentrancy through CPI
highCPIs can call back into your program with unexpected state.
Fix: Follow checks-effects-interactions. Update state before CPI.
Not checking CPI return values
mediumIgnoring CPI results can mask failures.
Fix: Always check invoke/invoke_signed results.
Common Development Mistakes
Not handling compute budget
mediumComplex operations can exceed compute limit.
Fix: Test compute usage. Request additional compute units if needed.
Forgetting to update IDL
mediumChanged program without updating IDL breaks clients.
Fix: Regenerate IDL after program changes. Version your IDLs.
Testing only on localnet
mediumLocalnet doesn't have same constraints as mainnet.
Fix: Test on devnet with realistic conditions.
Not initializing accounts properly
highUninitialized accounts contain garbage data.
Fix: Always initialize account data. Use Anchor's init constraint.
Ignoring rent requirements
highAccounts below rent-exempt threshold get garbage collected.
Fix: Ensure accounts have sufficient lamports for rent exemption.
Clockwork misuse
mediumUsing Solana's clock sysvar for critical timing without considering validator manipulation.
Fix: Use slot numbers or understand clock manipulation bounds.
Hardcoded cluster-specific addresses
mediumUsing mainnet program IDs in devnet code or vice versa.
Fix: Use environment configuration for cluster-specific addresses.
Ignoring transaction size limits
highSolana transactions have a 1232 byte limit, causing unexpected failures.
Fix: Monitor transaction sizes. Split large operations across multiple transactions.