Account Anatomy
Every Solana account shares the same structural fields. Understanding each field tells you who can write, whether code or data lives there, and how much SOL is locked for rent.
Search across all documentation pages
Every Solana account shares the same structural fields. Understanding each field tells you who can write, whether code or data lives there, and how much SOL is locked for rent.
import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const { value: acct } = await rpc
.getAccountInfo(address("PUBKEY"), { encoding: "base64" })
.send();When to reach for this:
data.lengthsolana account 11111111111111111111111111111111use anchor_lang::prelude::*;
pub fn inspect(ctx: Context<Inspect>) -> Result<()> {
let acct = &ctx.accounts.target;
msg!("lamports: {}", acct.lamports());
msg!("owner: {}", acct.owner);
msg!("data len: {}", acct.data_len());
msg!("executable: {}", acct.executable);
Ok(())
}
#[derive(Accounts)]
pub struct Inspect<'info> {
/// CHECK: raw inspection
pub target: UncheckedAccount<'info>,
}What this demonstrates:
executable distinguishes program accounts from data accountsdata_len() returns byte buffer size excluding the metadata fields| Field | Type | Meaning |
|---|---|---|
lamports | u64 | SOL balance in lamports |
data | &[u8] | Raw byte payload |
owner | Pubkey | Program authorized to write data |
executable | bool | true if account holds BPF program |
rent_epoch | u64 | Legacy tracking; rent-exempt accounts use u64::MAX |
lamports, owner, executable, rent_epoch) are runtime-managedowner can resize or write data (plus System Program for allocation)owner = BPF Loader and executable = truedata, not lamports. Fix: read token account layout for balances.data is UTF-8 text - it is raw bytes (Borsh, bincode, or custom). Fix: deserialize with the correct schema.executable flag - passing a program account where data is expected fails. Fix: check flag before deserialization.rent_epoch semantics changed - modern accounts are rent-exempt; epoch field is legacy. Fix: use getMinimumBalanceForRentExemption for funding.data. Fix: validate both in your constraints.| Alternative | Use When | Don't Use When |
|---|---|---|
getAccountInfo RPC | Off-chain inspection | Hot path in programs (pass accounts in) |
Anchor Account<T> | Typed deserialization | Unknown or variable layouts |
UncheckedAccount | Reading raw bytes with manual checks | Default choice (prefer typed) |
Lamports, data, owner, executable, rent_epoch. Every account has all five.
Only the current owner program (via assign) or System Program during creation. Not arbitrary programs.
10 MB per account in Agave 4.1.1. Practical limits are lower due to rent and CU costs.
Yes. Programs often deduct lamports while updating data in one atomic instruction.
The account contains deployed BPF bytecode loaded by a BPF loader program.
No. Upgrade authority is metadata on the program data account, separate from the owner field on individual accounts.
getAccountInfo returns null if the account has never been funded/created.
Typically empty (0 bytes). Wallet SOL is in lamports only.
No. Exactly one owner program per account.
base64 or base58 for getAccountInfo. jsonParsed for known program layouts like SPL Token.
No for modern rent-exempt accounts. It is informational/legacy.
8-byte discriminator + Borsh-serialized struct fields.
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