CPI (“cross-program invocation”) is the mechanism by which one Solana program calls another. Raydium’s Anchor programs ship CPI wrapper crates that make the call site look like a typed function call — account structs with validated field names and
cpi::<ix>() helpers. This page documents the general pattern; for product-specific snippets see the code-demos page of each product chapter.Cargo dependencies
cpi feature flag makes the crates compile to just the CPI surface (account structs + invokers) rather than the full program, so your binary stays small.
For working CPI examples that wire up the account structs end-to-end, see raydium-io/raydium-cpi-example (covers AMM v4, CPMM, and CLMM).
Account list construction
Every Raydium CPI requires anAccounts struct in the calling program. Fields match the program’s instruction account order 1-for-1, with field-level validators:
UncheckedAccount because the callee (Raydium) owns the validation. Your calling program only strictly validates accounts you own — user ATAs, your own PDAs. The /// CHECK: doc-comment suppresses Anchor’s warning about missing checks.
Building the CPI call
Anchor generates one helper per instruction:cpi::swap_base_input is generated from the IDL; its argument list mirrors the Anchor instruction’s argument list.
Signer seeds (PDA-signed CPI)
When your program signs the CPI on behalf of a PDA (common for vaults, escrows, etc.), useCpiContext::new_with_signer:
authority (or similar signer role), the Solana runtime checks that the PDA signs via these seeds.
Remaining accounts
Some Raydium instructions take remaining accounts — a variable-length list appended after the fixed accounts. The canonical examples:- CLMM
SwapV2: appends 1–8TickArrayStateaccounts corresponding to the tick arrays the swap might traverse. - Farm v6
Deposit: appends(reward_vault, user_reward_ata)pairs for each live reward stream.
.with_remaining_accounts(...):
Error propagation
Raydium’s programs return their own error enums. Anchor wraps them; your calling program sees them asErr(ProgramError::Custom(code)). To handle specific errors:
sdk-api/anchor-idl). You can test against specific codes by comparing against the numeric value.
Compute budget in composed CPIs
Each CPI frame has overhead (~1,500 CU for the call itself), and the callee’s own CU consumption stacks on top of yours. A transaction that calls CPMM swap from inside your program spends:ComputeBudgetProgram::set_compute_unit_limit(...) instruction in the transaction — the default 200k CU limit will silently exhaust.
AMM v4 — manual Instruction construction
AMM v4 has no Anchor crate. Build theInstruction by hand:
products/amm-v4/code-demos for the full account list.
Farm v6 — reward-pair remaining accounts
Farm v6’sDeposit / Withdraw / Harvest use the (reward_vault_i, user_reward_ata_i) pair pattern in remaining accounts. Exact sequence:
farm_state.reward_infos[i].reward_state.
Testing a CPI flow
Local dev requires the Raydium programs to be available in your test validator. Options:-
anchor testwith program clone — inAnchor.toml:This pulls the deployed bytecode from mainnet into your local validator. -
Devnet — Raydium deploys all programs to devnet with the same program IDs as mainnet. Run
anchor test --provider.cluster devnetto hit live code. -
Local deploy — clone the Raydium repos and
anchor deployto a local validator. Adds test cycle overhead but lets you modify the callee for debugging.
Pointers
products/cpmm/code-demos,products/clmm/code-demos,products/amm-v4/code-demos,products/farm-staking/code-demos— product-specific CPI examples.sdk-api/anchor-idl— IDL retrieval and client regeneration.integration-guides/cpi-integration— higher-level patterns: escrows, vaults, aggregator composition.

