Serialization Basics
10 examples to get you started with Account Serialization - 7 basic and 3 intermediate.
Prerequisites
- Borsh familiarity from Rust for Solana.
Basic Examples
1. Borsh account struct
Serialize structured state into account data.
#[derive(BorshSerialize, BorshDeserialize)]
pub struct Config { pub fee_bps: u16 }- Default choice for small/medium state.
- Easy versioning with extra fields at end.
- Compute cost scales with size.
2. Account size constant
Predeclare space for create_account.
impl Config { pub const LEN: usize = 2; }- Mismatch causes serialize failure.
- Include discriminator bytes in total.
- Anchor
InitSpacecalculates automatically.
3. Discriminator prefix
Tag account type to prevent confusion.
pub const DISCRIMINATOR: [u8; 8] = [0xC0, 0xFF, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x01];- Anchor uses 8-byte hash discriminators.
- Check before deserialize.
- Different types must differ.
4. Deserialize guard
Validate length and discriminator first.
if data.len() < Config::LEN { return Err(ProgramError::InvalidAccountData); }- Never deserialize untrusted accounts.
- Map errors to InvalidAccountData.
- Reject trailing garbage for fixed layouts.
5. Zero-copy when large
Use Pod for big fixed arrays.
#[repr(C)]
#[derive(Pod, Zeroable, Clone, Copy)]
pub struct Book { pub bids: [u64; 256] }- Avoids parse loop CUs.
- Requires repr(C) discipline.
- See zero-copy accounts page.
6. Instruction vs account
Instructions often Borsh; accounts may be hybrid.
// ix: enum Instruction { Update { val: u64 } }- Ix data is ephemeral per tx.
- Account data persists on-chain.
- Keep schemas separate.
7. Rent and size
Larger accounts need more lamports.
let rent = Rent::get()?.minimum_balance(Config::LEN);- Rent-exempt minimum required.
- realloc increases needed rent.
- Users pay at create/realloc.
Intermediate Examples
8. Version byte migration
First byte indicates schema version.
pub enum Version { V1 = 1, V2 = 2 }- Migration ix reads V1 writes V2.
- Never assume all accounts upgraded.
- Support both during rollout.
Related: Data Versioning & Migration
9. realloc grow
Expand account when schema grows.
// CPI realloc + rent transfer then new fields- Needs payer lamports.
- Zero new bytes or explicit init.
- See realloc article.
Related: realloc & Growing Accounts
10. Space calculation
Sum discriminator + fields + padding.
pub const SPACE: usize = 8 + Config::LEN;- Document formula in code.
- Test on host with serialize.
- Anchor init space macro.
Related: Space Calculation
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.