CPI to SPL Token
Token operations go through the SPL Token program via spl_token::instruction builders. Validate mints, authorities, and decimals before any CPI.
Recipe
let ix = spl_token::instruction::transfer(
token_program.key, source.key, dest.key, authority.key, &[], amount,
)?;
invoke(&ix, accounts)?;When to reach for this:
- Escrow release transfers.
- Minting reward tokens.
- Burning fee tokens.
Working Example
pub fn cpi_transfer(amount: u64, token_program: &AccountInfo, source: &AccountInfo, dest: &AccountInfo, auth: &AccountInfo, bump: u8) -> ProgramResult {
let ix = spl_token::instruction::transfer(token_program.key, source.key, dest.key, auth.key, &[], amount)?;
invoke_signed(&ix, &[source.clone(), dest.clone(), auth.clone(), token_program.clone()], &[&[b"auth", &[bump]]])
}What this demonstrates:
- spl_token helper builds data + metas.
- PDA authority uses invoke_signed.
- Amount is raw token units (decimals).
Deep Dive
Checks
- Source/dest mint match
- Authority owns source
- Token program id correct (Token vs Token-2022)
Token-2022
Separate program id - pass correct program account.
Rust Notes
use spl_token::state::Account as TokenAccount;Gotchas
- Wrong token program id - Token-2022 vs classic.. Fix: Validate program account key.
- Mint mismatch - Drain wrong pool.. Fix: Unpack and compare mint pubkeys.
- Decimals confusion - Off-by 10^n.. Fix: Use raw amounts consistently.
- Missing delegate check - Unauthorized transfer.. Fix: Validate authority field.
- Freeze account - Transfer fails.. Fix: Handle error code.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| anchor_spl | Ergonomic CPI | Native |
| Client-side transfer | User signs | Program escrow |
| Token-2022 extensions | Transfer hooks | Extra accounts |
FAQs
Mint CPI?
Needs mint authority signer.
Burn?
Similar to transfer with burn ix.
Approve delegate?
Separate instruction.
ATA creation?
Associated token program CPI.
Multisig authority?
Extra signer accounts in CPI.
Close token account?
Transfer remaining then close.
Rent on token acct?
Exempt typically.
Unpack token data?
spl_token::state unpack.
Fee on transfer?
Token-2022 extension.
Sim error decode?
Map token error codes.
anchor 0.32?
anchor_spl wrappers.
Checked amount?
Always before CPI.
Related
- SPL Token in Programs - Overview
- PDAs as Authorities - PDA mint
- Vault & Escrow - Escrow
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.