Advanced· Lesson 5 of 8· 3 min
Cross-program invocation
Programs call other programs. That one mechanism is how a swap moves tokens, how a locker signs for its vault, and why one bad step anywhere rolls back everything.
A cross-program invocation (CPI) is a program calling an instruction on another program during its own execution, passing along some of the accounts it was given. The Token program never needs to know about exchanges; an exchange calls it. The call stack can go four levels deep below the top-level instruction, and every level sees the same atomic transaction.
What gets passed down
A program can only hand a callee accounts it received itself, with at most the privileges they arrived with: an account that was not writable for the caller cannot become writable for the callee, and a signature cannot be invented. There is one exception, and it is the important one: a program may add signer status for its own program derived addresses by calling invoke_signed with the seeds. That is how a program “owns” a vault without a private key.
// Anchor: the locker releases tokens from a vault it controls
let seeds = &[b"lock", lock.key().as_ref(), &[lock.bump]];
token::transfer(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
Transfer { from: vault, to: recipient_ata, authority: lock_pda },
&[seeds], // the runtime re-derives lock_pda and treats it as a signer
),
amount,
)?;Reading a call chain

- The top-level instruction: Jupiter's route.
- Jupiter invokes a pool program (Meteora's DLMM) — depth 2. Indentation is depth.
- The pool invokes the Token program to move tokens — depth 3.
- The pool calling itself: self-recursion is the only reentrancy the runtime allows.
- Each level reports units consumed of the budget it had left. Nested calls share the one budget.
- The second hop: a different pool program, the same pattern.
- “Program data”: an event the pool emitted, base64. Explorers decode it with the program's IDL.
Explorers show the same structure as “inner instructions” under each top-level instruction, decoded where they know the program. The associated-token-account creation earlier in the same transaction is a good small example: one instruction, four inner calls.

- The Associated Token program's single instruction expands to these.
- A CPI to the Token program that returns data: the account size to allocate.
- The extension the ATA program always requests: immutable owner.
- A CPI to the System program to create the account — signed by the wallet, whose signature the ATA program passed down.
- Assigned to the Token program, so the next CPI can initialise it.
What the callee can and cannot trust
The runtime guarantees signer and writable flags and account ownership. It guarantees nothing else: the caller chooses which accounts to pass and in what order, and can pass the wrong mint, a look-alike vault or its own account as the “pool”. A well-written program therefore checks everything it relies on — owner, expected address, PDA derivation, discriminator — before acting. Most exploits of Solana programs have been a missing check of exactly this kind, and it is what Anchor's account constraints exist to enforce (Reading an Anchor program).
Failure and return data
- Any level returning an error fails the whole transaction. There is no partial success; the fee is still paid.
- The log names the failing program and its error code. The line above it, from the same program, usually says why.
- A callee can hand back up to 1,024 bytes of return data; the caller reads it after the call. The Token program's “get account data size” above works this way.
- Each CPI costs a fixed overhead of about a thousand units plus whatever the callee uses, all from one shared budget.
Where you meet it
Every Solstack transaction is a chain of CPIs: creating a token calls System, Token and Metadata; the Token Locker's release calls the Token program with invoke_signed for its vault; the Launchpad's settlement calls Raydium to create a pool and then the Token program to burn the LP. Transaction Inspector shows the full tree for any signature, which is the fastest way to learn what a program you are about to use really does.
What to remember
- A CPI is a program calling another program's instruction, up to four levels deep, within one atomic transaction.
- Privileges only flow down, except that a program can sign for its own PDAs with invoke_signed.
- Explorers show CPIs as nested logs and inner instructions. Indentation is depth.
- The runtime guarantees signatures, writability and ownership. Everything else the callee must check.
- Any level failing fails everything, fee paid. Return data lets a callee answer its caller.