- TransferChecked validates that the decimals parameter matches the mint’s decimals.
- Use
TransferCheckedCpifor Light-to-Light transfers in on-chain programs when you need decimal verification without interface routing. - For transfers involving SPL or Token 2022 accounts, use Transfer Interface instead. It uses
transferCheckedunder the hood.
Agent skill
Agent skill
Install the agent skill:See the AI tools guide for dedicated skills.
Report incorrect code
Copy
Ask AI
npx skills add https://zkcompression.com
- TypeScript Client
- Rust Client
- Program
transferChecked is called automatically under the hood by transferInterface and createTransferInterfaceInstructions. You do not need to call it directly.TransferChecked is called automatically under the hood by TransferInterface. You do not need to call it directly.- Guide
- AI Prompt
Transfer Checked with CPI
- invoke (External signer)
- invoke_signed (PDA signer)
Report incorrect code
Copy
Ask AI
use light_token::instruction::TransferCheckedCpi;
TransferCheckedCpi {
source: source.clone(),
mint: mint.clone(),
destination: destination.clone(),
amount,
decimals,
authority: authority.clone(),
system_program: system_program.clone(),
max_top_up: None,
fee_payer: None,
}
.invoke()?;
Report incorrect code
Copy
Ask AI
use light_token::instruction::TransferCheckedCpi;
let signer_seeds = authority_seeds!(bump);
TransferCheckedCpi {
source: source.clone(),
mint: mint.clone(),
destination: destination.clone(),
amount,
decimals,
authority: authority.clone(),
system_program: system_program.clone(),
max_top_up: None,
fee_payer: None,
}
.invoke_signed(&[signer_seeds])?;
Full Code Example
View the source code and full example with shared test utilities.
Report incorrect code
Copy
Ask AI
#![allow(unexpected_cfgs, deprecated)]
use anchor_lang::prelude::*;
use light_token::instruction::TransferCheckedCpi;
declare_id!("HXmfewpozFdxhM8BayL9v5541gwoGMXTrUoip5KySs2f");
#[program]
pub mod light_token_anchor_transfer_checked {
use super::*;
pub fn transfer_checked(
ctx: Context<TransferCheckedAccounts>,
amount: u64,
decimals: u8,
) -> Result<()> {
TransferCheckedCpi {
source: ctx.accounts.source.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
destination: ctx.accounts.destination.to_account_info(),
amount,
decimals,
authority: ctx.accounts.authority.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
fee_payer: ctx.accounts.fee_payer.to_account_info(),
}
.invoke()?;
Ok(())
}
}
#[derive(Accounts)]
pub struct TransferCheckedAccounts<'info> {
/// CHECK: Light token program for CPI
pub light_token_program: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
#[account(mut)]
pub source: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub mint: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
#[account(mut)]
pub destination: AccountInfo<'info>,
pub authority: Signer<'info>,
#[account(mut)]
pub fee_payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
Add transfer-checked CPI to an Anchor program
Report incorrect code
Copy
Ask AI
---
description: Add transfer-checked CPI to an Anchor program
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, WebFetch, AskUserQuestion, Task, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskOutput, mcp__deepwiki, mcp__zkcompression
---
## Add transfer-checked CPI to an Anchor program
Context:
- Guide: https://zkcompression.com/light-token/cookbook/transfer-checked
- Skills and resources index: https://zkcompression.com/skill.md
- SPL to Light reference: https://zkcompression.com/api-reference/solana-to-light-comparison
- Crate: light-token (TransferCheckedCpi)
- Example: https://github.com/Lightprotocol/examples-light-token/tree/main/programs/anchor/basic-instructions/transfer-checked
Key CPI struct: `light_token::instruction::TransferCheckedCpi`
Note: TransferInterface uses TransferChecked under the hood for Light-to-Light transfers.
Use TransferChecked/TransferCheckedCpi directly only when you need Light-to-Light without interface routing.
### 1. Index project
- Grep `declare_id|#\[program\]|anchor_lang|Account<|Pubkey|invoke|transfer|decimals|amount` across src/
- Glob `**/*.rs` and `**/Cargo.toml` for project structure
- Identify: program ID, existing instructions, account structs, token accounts
- Read Cargo.toml — note existing dependencies and framework version
- Task subagent (Grep/Read/WebFetch) if project has multiple crates to scan in parallel
### 2. Read references
- WebFetch the guide above — review the Program tab CPI code samples
- WebFetch skill.md — check for a dedicated skill and resources matching this task
- TaskCreate one todo per phase below to track progress
### 3. Clarify intention
- AskUserQuestion: what is the goal? (add transfer-checked to existing program, new program from scratch, migrate from SPL transfer_checked)
- AskUserQuestion: should the authority be an external signer or a PDA? (determines invoke vs invoke_signed)
- Summarize findings and wait for user confirmation before implementing
### 4. Create plan
- Based on steps 1–3, draft an implementation plan: which files to modify, what code to add, dependency changes
- Follow the guide's step order: Build TransferCheckedCpi struct → call .invoke() or .invoke_signed()
- If anything is unclear or ambiguous, loop back to step 3 (AskUserQuestion)
- Present the plan to the user for approval before proceeding
### 5. Implement
- Add deps if missing: Bash `cargo add light-token anchor-lang@0.31`
- Follow the guide and the approved plan
- Write/Edit to create or modify files
- TaskUpdate to mark each step done
### 6. Verify
- Bash `anchor build`
- Bash `anchor test` if tests exist
- TaskUpdate to mark complete
### Tools
- mcp__zkcompression__SearchLightProtocol("<query>") for API details
- mcp__deepwiki__ask_question("Lightprotocol/light-protocol", "<q>") for architecture
- Task subagent with Grep/Read/WebFetch for parallel lookups
- TaskList to check remaining work