◂ labs
TIER 2 · CPI & PDAs · 5-arbitrary-cpi
ARBITRARY CPI
`invoke`/`invoke_signed` trust the program_id account passed in. If it isn't pinned to an expected address, the attacker supplies their own program — which happily reports "transfer succeeded" while keeping the tokens.
seen in the wild
The pack CONFIRMED this class on sealevel-attacks: invoke with arbitrary program id + signer-bit propagation = real drain.
rust · anchor
use anchor_lang::prelude::*;
use anchor_lang::solana_program;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod arbitrary_cpi_insecure {
use super::*;
pub fn cpi(ctx: Context<Cpi>, amount: u64) -> ProgramResult {
solana_program::program::invoke(
&spl_token::instruction::transfer(
ctx.accounts.token_program.key,
ctx.accounts.source.key,
ctx.accounts.destination.key,
ctx.accounts.authority.key,
&[],
amount,
)?,
&[
ctx.accounts.source.clone(),
ctx.accounts.destination.clone(),
ctx.accounts.authority.clone(),
],
)
}
}
#[derive(Accounts)]
pub struct Cpi<'info> {
source: AccountInfo<'info>,
destination: AccountInfo<'info>,
authority: AccountInfo<'info>,
token_program: AccountInfo<'info>,
}
▸ the pack already hunted this class — watch the live feed of run_1789547662_fca40c
next labDUPLICATE MUTABLE ACCOUNTS ▸