# Cross Program Invocation

A **cross program invocation** is when a program invokes the instructions of another program.

This can only go to a max depth of 4 programs.

Accounts and permissions cascade across the invocations, meaning that the accounts and permissions given to program A, will cascade to the subsequent programs it calls.

Programs use the `invoke` and `invoke_signed` functions to trigger other programs behavior.

## Invoke

You use `invoke` when making any CPI that does not require any PDAs to act as signers. Your program will pass on the original signatures to the program being called.

This is how you sign for a regular account owned by the System Program.

The `invoke` method actually just calls `invoke_signed` with an empty `signers_seed` array:

```rust
pub fn invoke(instruction: &Instruction, account_infos: &[AccountInfo]) -> ProgramResult {
    invoke_signed(instruction, account_infos, &[])
}
```

## Invoke signed

When you need to sign with a PDA you have to use `invoke_signed` and provide the seeds required to derive the PDA of the calling program.

PDAs don't have private keys. The Solana runtime will call `create_program_address` using the `seeds` and `program_id` of the calling program. It then compares the resulting PDA to the addresses supplied in the instruction. If it matches it is considered a valid signer.

This is how you sign for transactions on accounts owned by a program instead of the system (like a normal user account which just requires a regular private key signer)

## A simple transfer

Here's an example of a `program` written in Rust using Anchor that handles transfers:

```rust
use anchor_lang::prelude::*;
use anchor_lang::system_program::{transfer, Transfer};

declare_id!("9AvUNHjxscdkiKQ8tUn12QCMXtcnbR9BVGq3ULNzFMRi");

#[program]
pub mod cpi {
    use super::*;

pub fn sol_transfer(ctx: Context<SolTransfer>, amount: u64) -> Result<()> {
        let from_pubkey = ctx.accounts.sender.to_account_info();
        let to_pubkey = ctx.accounts.recipient.to_account_info();
        let program_id = ctx.accounts.system_program.to_account_info();

let cpi_context = CpiContext::new(
            program_id,
            Transfer {
                from: from_pubkey,
                to: to_pubkey,
            },
        );

transfer(cpi_context, amount)?;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct SolTransfer<'info> {
    #[account(mut)]
    sender: Signer<'info>,
    #[account(mut)]
    recipient: SystemAccount<'info>,
    system_program: Program<'info, System>,
}
```

This program takes a `SolTransfer` instruction with an amount and ferries it to the next program, using the provided `program_id` from the `system_program` found on the `SolTransfer` struct.

## Token transfers

Token transfers are done through the `anchor_spl` crate.

```rust
let transfer = anchor_spl::token::Transfer {
    to: ctx.accounts.buyer_token_account.to_account_info(),
    from: ctx.accounts.token_vault.to_account_info(),
    authority: ctx.accounts.pool.to_account_info(),
};

// Transfer tokens to seller from pool
anchor_spl::token::transfer(
    CpiContext::new_with_signer(
        ctx.accounts.token_program.to_account_info(),
        transfer,
        signer_seeds,
    ),
    usdc_amount,
)?;
```

## PDA Transfers

When making transfers through a Program where the Accounts are program-owned, and found at PDAs, we use `invoke_signed` and hand in the `signers_seeds` alongside the `instruction` and `account_infos` array.
