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.
Recipe
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:
- Debugging permission errors (wrong owner or missing signer)
- Determining if an address is a program vs data account
- Calculating rent from
data.length - Verifying account existence before building transactions
Working Example
solana 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:
- All five fields are readable by any program that receives the account
executabledistinguishes program accounts from data accountsdata_len()returns byte buffer size excluding the metadata fields
Deep Dive
Field Reference
| 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 |
How It Works
- Metadata fields (
lamports,owner,executable,rent_epoch) are runtime-managed - Only
ownercan resize or writedata(plus System Program for allocation) - Program accounts have
owner = BPF Loaderandexecutable = true
Gotchas
- Confusing lamports with token balance - SPL balances live in token account
data, notlamports. Fix: read token account layout for balances. - Assuming
datais UTF-8 text - it is raw bytes (Borsh, bincode, or custom). Fix: deserialize with the correct schema. - Ignoring
executableflag - passing a program account where data is expected fails. Fix: check flag before deserialization. rent_epochsemantics changed - modern accounts are rent-exempt; epoch field is legacy. Fix: usegetMinimumBalanceForRentExemptionfor funding.- Owner vs authority - owner is the program; authority is often a pubkey inside
data. Fix: validate both in your constraints.
Alternatives
| 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) |
FAQs
What are the five account fields?
Lamports, data, owner, executable, rent_epoch. Every account has all five.
Who can change the owner field?
Only the current owner program (via assign) or System Program during creation. Not arbitrary programs.
What is the maximum account data size?
10 MB per account in Agave 4.1.1. Practical limits are lower due to rent and CU costs.
Can lamports and data change in the same instruction?
Yes. Programs often deduct lamports while updating data in one atomic instruction.
What does executable=true mean?
The account contains deployed BPF bytecode loaded by a BPF loader program.
Is owner the same as upgrade authority?
No. Upgrade authority is metadata on the program data account, separate from the owner field on individual accounts.
How do I check if an account exists?
getAccountInfo returns null if the account has never been funded/created.
What lives in a wallet account's data?
Typically empty (0 bytes). Wallet SOL is in lamports only.
Can two programs co-own an account?
No. Exactly one owner program per account.
What encoding should RPC use for binary data?
base64 or base58 for getAccountInfo. jsonParsed for known program layouts like SPL Token.
Does rent_epoch affect transaction validity?
No for modern rent-exempt accounts. It is informational/legacy.
How is account data laid out in Anchor?
8-byte discriminator + Borsh-serialized struct fields.
Related
- Account Model Basics - overview examples
- Rent & Rent-Exemption - lamports requirements
- Data Accounts & Layout - byte buffer design
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.