no_std & the Program Environment
Solana programs compile to SBF and run in a sandbox without std. You get solana_program syscalls, optional alloc, and a strict CU budget.
Search across all documentation pages
Solana programs compile to SBF and run in a sandbox without std. You get solana_program syscalls, optional alloc, and a strict CU budget.
#![no_std]
extern crate alloc;
use solana_program::{
account_info::AccountInfo, entrypoint, program_error::ProgramError,
pubkey::Pubkey,
};When to reach for this:
cargo build-sbf.alloc collections and fixed-size account layouts.#![no_std]
extern crate alloc;
use alloc::vec::Vec;
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
program_error::ProgramError, pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
if instruction_data.is_empty() {
return Err(ProgramError::InvalidInstructionData);
}
let _owner = accounts.get(0).ok_or(ProgramError::NotEnoughAccountKeys)?;
let buf: Vec<u8> = instruction_data.to_vec();
solana_program::msg!("bytes: {}", buf.len());
Ok(())
}What this demonstrates:
#![no_std] plus extern crate alloc is the default native program layout.AccountInfo references supplied by the runtime..so and invokes the symbol registered by entrypoint!.| Layer | Examples | Notes |
|---|---|---|
| Core | solana_program | Accounts, CPI, sysvars, errors |
| Serialize | borsh, bytemuck | Instruction and account layouts |
| Math | num-traits, checked ops | Avoid std math |
| Avoid | std, tokio, reqwest | Will not compile for SBF |
// Prefer &[u8] over Vec unless you must own bytes.
// solana_program re-exports Pubkey, ProgramError, and sysvars.std breaks cargo build-sbf. Fix: Pin deps with cargo tree and prefer no_std-compatible crates.Vec::push in hot paths allocates and costs CUs. Fix: Use fixed account sizes or stack arrays with known bounds.unwrap on bad client data aborts the whole transaction. Fix: Return ProgramError::InvalidAccountData instead.Vec without extern crate alloc fails to link. Fix: Add extern crate alloc at crate root.println! is unavailable on-chain. Fix: Use msg! or custom errors sparingly.
| Alternative | Use When | Don't Use When |
|---|---|---|
| Anchor 0.32.1 | Faster iteration with account macros | Maximum CU/binary efficiency |
| Pinocchio | Zero-dependency entrypoints | Need Anchor ergonomics |
| bytemuck only | Large fixed layouts | Variable-length strings |
No std. Use alloc (Vec, String) or store data in accounts.
The instruction fails and no state changes commit.
Use msg! - it costs CUs and appears in transaction logs.
No. Single-threaded execution per instruction.
No I/O beyond account data and syscalls.
Enables heap allocation through the program allocator.
Solana Bytecode Format - the on-chain target (successor to BPF).
Use #[cfg(test)] on host with solana-program-test or LiteSVM 0.6.x.
No async runtime on-chain.
Clock, Rent, Instructions - read via sysvar modules.
Keep stack usage small; large state belongs in accounts.
It allocates heavily - avoid in production paths.
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.
Reviewed by Chris St. John·Last updated Jul 19, 2026