Working with Pubkeys & Accounts
Pubkey identifies accounts and programs. AccountInfo is the runtime handle for lamports, data, owner, and signer flags. Correct slicing and validation prevent privilege escalation.
Search across all documentation pages
Pubkey identifies accounts and programs. AccountInfo is the runtime handle for lamports, data, owner, and signer flags. Correct slicing and validation prevent privilege escalation.
use solana_program::{account_info::AccountInfo, pubkey::Pubkey};
fn assert_signer(ai: &AccountInfo) -> ProgramResult {
if !ai.is_signer { return Err(ProgramError::MissingRequiredSignature); }
Ok(())
}When to reach for this:
next_account_info.use solana_program::{
account_info::{next_account_info, AccountInfo},
program_error::ProgramError,
pubkey::Pubkey,
};
pub fn process_transfer(accounts: &[AccountInfo], expected_owner: &Pubkey) -> ProgramResult {
let iter = &mut accounts.iter();
let payer = next_account_info(iter)?;
let vault = next_account_info(iter)?;
if !payer.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
if vault.owner != expected_owner {
return Err(ProgramError::IncorrectProgramId);
}
if !vault.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}What this demonstrates:
next_account_info advances the account iterator in client order.| Field | Meaning |
|---|---|
key | Account address |
lamports | SOL balance ref |
data | Byte payload ref |
owner | Program that may write data |
is_signer | Signed this tx |
is_writable | Mutable in this tx |
== on references.is_on_curve == false off-chain; on-chain treat as normal keys.let (pda, bump) = Pubkey::find_program_address(&[b"vault", owner.as_ref()], program_id);key when you meant owner allows impersonation. Fix: Name variables clearly and lint reviews.**lamports changes.| Alternative | Use When | Don't Use When |
|---|---|---|
Anchor Account<'info, T> | Auto owner/discriminator checks | Manual control |
Pinocchio AccountView | Lower CU account parsing | Ecosystem maturity |
| Account maps off-chain | Client builds account metas | On-chain must still verify |
Tied to the instruction - do not store references across CPI.
Yes - PDAs are pubkeys off the ed25519 curve.
Use ==; no constant-time requirement for pubkeys.
Use **account.lamports or borrow helpers.
Transaction builder - program must assert for safety.
Uninitialized accounts may be zero length until allocated.
New accounts are owned by System Program until assigned.
Only via PDAs with invoke_signed.
Off-chain Pubkey::from_str - on-chain receive as account key.
Use iterator pattern; avoid hard-coded len without checks.
Program accounts are executable; data accounts are not.
Check Rent::get()?.is_exempt when creating accounts.
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 16, 2026