Solana’s account model is the single most important thing to understand before reading Raydium’s code. Unlike Ethereum where state lives alongside contract code, Solana programs are completely stateless: all state lives in separate “accounts” that programs operate on. Every Raydium pool, position, and vault is an account — understanding how those accounts work makes the rest of the documentation make sense.
The fundamental split: programs vs accounts
Programs
A program on Solana is executable code — a compiled binary loaded from a file, deployed to aPubkey, and invokable via transactions. Programs have no associated state; they contain only logic.
Raydium’s programs:
- CPMM:
CPMMoo8L3F4NbTegBCKVNunggL7H1Zpdmwpwh8KMoZ0F - CLMM:
CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK - AMM v4:
675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8
Accounts
An account is a row of data on-chain. Every account has:pubkey— its address.owner— the program that owns it (controls writes).data— the raw bytes.lamports— SOL balance (1 SOL = 1,000,000,000 lamports).rent_epoch— legacy rent-collection field (ignored since rent-exemption became mandatory).
Ownership
Every account is owned by exactly one program. Only that program’s code can modify the account’sdata field. A user can modify lamports (send/receive SOL) on an account they can sign for, but modifying data requires the owner program to do it on their behalf.
Examples:
- Your user wallet: owned by the System Program. Lamports live here; you sign to transfer.
- Your USDC token account: owned by the SPL Token Program. The token program’s
transferinstruction updates the balance. - A Raydium pool state account: owned by the CPMM program. Only CPMM’s instructions can modify the reserves, fees, etc.
- A Raydium position NFT’s
PersonalPositionState: owned by the CLMM program.
Rent and rent-exemption
Creating an account consumes storage space. Solana charges rent for that space, but as of 2020 all new accounts must be rent-exempt — meaning they hold enough lamports that the rent they’d owe over 2 years is pre-paid. In practice:- Rent-exempt account lives forever.
- Closing the account returns the lamports to the closing signer.
Raydium rent costs
| Account | Size | Rent |
|---|---|---|
| CPMM PoolState | ~1,440 B | ~0.011 SOL |
| CLMM PoolState | ~1,500 B | ~0.012 SOL |
| CLMM TickArray | ~9,000 B | ~0.063 SOL |
| CLMM PersonalPositionState | ~280 B | ~0.003 SOL |
| ATA | 165 B | ~0.002 SOL |
| Vault (Token Account) | 165 B | ~0.002 SOL |
Data vs executable accounts
Accounts come in two flavors:Data accounts
Hold state (pool reserves, token balances, user positions).executable = false. This is the vast majority.
Executable accounts
Hold program bytecode.executable = true. These are programs (CPMM, CLMM, etc.). Programs don’t have data beyond their bytecode.
Program-derived accounts (PDAs)
A PDA is a data account whose address is derived deterministically from a program and some seeds — no private key exists for this address. Only the derivation program can sign on behalf of a PDA viainvoke_signed.
Raydium uses PDAs extensively:
- Pool state PDAs: derived from
[poolTypeDiscriminator, mintA, mintB, ammConfig]. - Vault PDAs: derived from
[pool, mint]. - Observation state PDA: derived from
[observationSeed, pool].
solana-fundamentals/pdas-and-cpis.
Transactions and account references
Every Solana transaction carries an explicit list of accounts it will read/write. The runtime enforces:- Listed accounts can be read or written (per their
is_writableflag). - Unlisted accounts cannot be touched.
Account size and data layout
Every Raydium account has a fixed or bounded size. Layout is defined in code (Rust structs with#[repr(C)]) and documented in sdk-api/anchor-idl.
Anchor programs prepend an 8-byte discriminator to every account they create, derived from hash("account:<StructName>")[0..8]. This lets clients identify the type of an account just by reading the first 8 bytes — crucial for getProgramAccounts scans that enumerate all accounts of a type.
Reading a Raydium pool state
Via the SDK:src/raydium/cpmm/layout.ts in the SDK source.
Worked example: reading a token account
Let’s read a user’s USDC balance.Why this matters for Raydium
The account model shapes Raydium’s design:- Pool state is a single account — everything about a pool (mints, reserves, fees, admin) lives in one account owned by the pool program.
- LP tokens are standard SPL token accounts — Raydium delegates tokenization to the SPL Token program.
- Tick arrays are chunked — CLMM can’t have a single growable array of ticks because accounts have fixed allocated size; instead, it uses chunked
TickArrayPDAs. - Position NFTs are Metaplex NFTs — CLMM positions are standard NFTs per Metaplex; position state is a separate PDA.
- “Where are the pool reserves?” → two vault accounts (token accounts) owned by the SPL Token program, with authority delegated to a PDA of the pool program.
- “Where is the tick data for CLMM?” → a series of TickArray PDAs, each covering 60 consecutive ticks.
- “Where is my farm stake?” → a
UserLedgerPDA derived from[user, farmId], owned by the farm program.
Pointers
solana-fundamentals/programs-and-anchor— how programs process accounts.solana-fundamentals/pdas-and-cpis— PDA derivation and CPI.solana-fundamentals/transactions-and-fees— how accounts are referenced in transactions.sdk-api/anchor-idl— account layouts for Raydium’s programs.
- Solana Account docs.
- SPL Token program — where token accounts live.

