The #[program] Module
The #[program] attribute macro generates Solana's entrypoint, instruction dispatch, and discriminator checks. Your public functions become on-chain instructions.
Recipe
#[program]
pub mod my_program {
use super::*;
pub fn initialize(ctx: Context<Initialize>, amount: u64) -> Result<()> {
ctx.accounts.config.amount = amount;
Ok(())
}
}When to reach for this: You add or rename an instruction exposed to clients.
Working Example
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod escrow {
use super::*;
pub fn initialize(ctx: Context<Initialize>, amount: u64) -> Result<()> {
let escrow = &mut ctx.accounts.escrow;
escrow.amount = amount;
escrow.authority = ctx.accounts.authority.key();
Ok(())
}
pub fn release(ctx: Context<Release>) -> Result<()> {
require!(ctx.accounts.authority.key() == ctx.accounts.escrow.authority, EscrowError::Unauthorized);
// transfer logic ...
Ok(())
}
}
#[account]
pub struct Escrow {
pub amount: u64,
pub authority: Pubkey,
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = authority, space = 8 + Escrow::INIT_SPACE)]
pub escrow: Account<'info, Escrow>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Release<'info> {
#[account(mut, has_one = authority)]
pub escrow: Account<'info, Escrow>,
pub authority: Signer<'info>,
}What this demonstrates:
- Module name becomes the program module namespace in clients
- Each
pub fnis one instruction with a unique discriminator - Account structs are separate
#[derive(Accounts)]types - Return
Result<()>for fallible instructions
Deep Dive
How It Works
- Anchor hashes the instruction name to an 8-byte discriminator prepended to instruction data.
- The generated dispatcher deserializes accounts into your Context<T> struct.
- Private functions inside the module are not exposed as instructions.
- use super::*; brings account structs and types into scope.
Handler Signatures
| Part | Role |
|---|---|
Context<T> | Validated accounts for this instruction |
| Extra args | Borsh-deserialized instruction data |
Result<()> | Success or custom program error |
Gotchas
- Handler named
init- Conflicts with reserved patterns in some tooling.. Fix: Useinitializeinstead. - Account struct inside #[program] - Macro cannot find types reliably.. Fix: Define
#[derive(Accounts)]at module root. - Missing
use super::*- Types not in scope inside module.. Fix: Add the import at top of program module. - Pub fn with wrong Context type - Dispatch passes wrong account layout.. Fix: Match struct name to
Context<StructName>. - Returning non-Result - Only Result and return-data patterns compile for handlers.. Fix: Use
Result<()>unless returning data explicitly.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Native entrypoint! + match | Minimal binary size | You want declarative account validation |
| Pinocchio dispatch | Lowest CU overhead | You need Anchor IDL and macros |
| Multiple #[program] modules | Not supported in one crate | Split into separate program crates |
FAQs
What Anchor version does this site use?
0.32.1 for anchor-lang, Anchor CLI, and examples in this section.
Do I need Solana CLI alongside Anchor?
Yes. Solana CLI 3.0.10 handles keypairs, airdrops, and solana program inspection.
Where does the IDL live after build?
target/idl/<program>.json in your workspace.
Can I mix UncheckedAccount with Signer?
Yes, but every unchecked field needs explicit constraints or handler checks.
How do I test without devnet?
Use anchor test with Surfpool 0.12.0 or LiteSVM 0.6.x in CI.
What is the 8-byte prefix on account data?
Anchor account discriminator; do not strip it when sizing space.
Should I commit generated IDL?
Yes, or publish on-chain IDL so clients have a canonical source.
How do I debug constraint failures?
Run with logs; Anchor prints constraint name and account index.
Does Anchor work on Agave 4.1.1?
Yes. This stack targets Agave validators with Solana CLI 3.0.10.
What should I read next in this section?
See sibling articles linked in Related for deeper program module topics.
Related
- Instruction Handlers - Context and signatures
- The Accounts Struct - validation structs
- Building & Deploying - build output
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.