Languages .mdc

Rust

Rust best practices for Solana smart contract development using Anchor framework and Solana SDK

How to use
  1. Copy the rule content.
  2. In your project root, create .cursorrules or .cursor/rules/rust.mdc
  3. Paste the content and save.

Rust + Solana (Anchor) Best Practices

Program Structure

  • Structure Solana programs using Anchor framework standards
  • Place program entrypoint logic in lib.rs, not main.rs
  • Organize handlers into modules (e.g., initialize, update, close)
  • Separate state definitions, errors, instructions, and utils
  • Group reusable logic under a utils module (e.g., account validation)
  • Use declare_id!() to define program ID

Anchor Framework

  • Use #[derive(Accounts)] for all instruction contexts
  • Validate accounts strictly using constraint macros (e.g., #[account(mut)], seeds, bump])
  • Define all state structs with #[account] and #[derive(AnchorSerialize, AnchorDeserialize)]
  • Prefer Init, Close, Realloc, Mut, and constraint macros to avoid manual deserialization
  • Use ctx.accounts to access validated context accounts
  • Handle CPI (Cross-Program Invocation) calls via Anchor’s CPI helpers

Serialization

  • Use Borsh or Anchor’s custom serializer (not Serde) for on-chain data
  • Always include #[account(zero_copy)] or #[repr(C)] for packed structures
  • Avoid floating point types — use u64, u128, or fixed-point math
  • Zero out or close unused accounts to reduce rent costs

Testing

  • Write tests in TypeScript using Anchor’s Mocha + Chai setup (tests/*.ts)
  • Use anchor.workspace.MyProgram to load deployed contracts
  • Use provider.simulate() to inspect failed txs
  • Spin up a local validator (anchor test) and reset between tests
  • Airdrop SOL to wallets with provider.connection.requestAirdrop(...)
  • Validate program logs using tx.confirmation.logMessages

Solana SDK (Manual)

  • Use solana_program crate when not using Anchor (bare-metal programs)
  • Carefully deserialize accounts using AccountInfo, try_from_slice_unchecked
  • Use solana_program::msg! for lightweight debugging logs
  • Verify accounts via is_signer, is_writable, key == expected
  • Never panic! Use ProgramError::Custom(u32) or ErrorCode enums

Security Patterns

  • Always validate msg.sender/signer with account_info.is_signer
  • Prevent replay attacks via seeds, bump, and unique PDAs
  • Use strict size checks before reallocating or deserializing
  • Avoid unsafe unchecked casting; prefer Anchor deserialization
  • For CPIs, validate target_program against expected program ID
  • When using randomness, never rely on timestamps — use oracles or off-chain VRFs

Performance

  • Prefer zero-copy deserialization when accounts are large
  • Minimize compute usage; avoid loops and recursion
  • Avoid memory reallocations mid-instruction
  • Use #[account(zero_copy)] and #[repr(packed)] for tight layout
  • Profile compute units with solana logs and anchor run

Dev Workflow

  • Use anchor init to scaffold projects
  • Add Anchor IDL support for front-end usage (JSON ABI)
  • Use anchor build, anchor deploy, anchor test consistently
  • Use separate Anchor.toml environments for devnet/mainnet/localnet
  • Format all Rust code with cargo fmt, lint with cargo clippy
  • Keep Cargo.lock checked into programs/ but not root

Documentation

  • Use /// Rust doc comments for all instructions and accounts
  • Include doc examples for each instruction
  • Document PDA derivation logic and bump seed expectations
  • Maintain up-to-date README.md with test commands and deployment steps

Wallet & Network Handling

  • Use anchorProvider.wallet.publicKey for signer verification in tests
  • Do not hardcode keypairs — use env-based loading (process.env.ANCHOR_WALLET)
  • Deploy with clear cluster targets (localnet, devnet, mainnet)
  • Use anchor keys sync to propagate program ID changes
  • Commit target/idl/ and target/types/ to share with front end

CI/CD & Deploy

  • Use GitHub Actions with solana-cli, anchor-cli, and node installed
  • Run anchor test in CI for every PR
  • Use solana program deploy with explicit --program-id on production deploys
  • Upload IDLs to a central registry (e.g., GitHub, IPFS, or anchor.cloud)

Similar rules

More in Languages →