Every Instruction receives Accounts as arguments, most accounts are passed in with `Account<'info, Type>` or `Program<'info, ProgramType>` in the anchor framework. This is because anchor expects you to do some checks on every account you pass in, if these checks are not properly done, you are at risk of a security flaw. `Account<'info, Type>` checks that the Account passed in is a program-owned account of the type `Type`. `Type` can be your custom type in your custom program or it can be a type of another program like `Mint` or `TokenAccount`. `Program<'info, ProgramType>` checks that the Account passed in is a program account(executable is set to true). `ProgramType` is usually used for `System` or `Token` or when performing cpi calls. `UncheckedAccount` just means that you are not performing any implicit checks on that account by anchor. It is the same as `AccountInfo` but it was named `UncheckedAccount` to explicitly signify that you are aware you are blindly trusting this account. It should be avoided whenever possible as it can lead to security flaws easily. However, you can use it for a simple SOL transfer. pub SendSol<'info> { #[account(mut)] pub from: Signer<'info>, // UncheckedAccount can be used here but Signer checks that `from` signs the transaction #[account(mut)] pub to: UncheckedAccount<'info>, // AccountInfo can also be used instead but UncheckedAccount is preferred because of semantics pub system_program: Program<'info, System>, // UncheckedAccount can also be used here but Program checks that this Account is executable and owned by System } pub fn send_sol(ctx: Context<SendSol>, amount: u64) -> Result<()> { let sol_transfer_ix = anchor_lang::solana_program::system_instruction::transfer( ctx.accounts.from.key, ctx.accounts.to.key, amount ); invoke( &sol_transfer_ix, &[ ctx.accounts.from.to_account_info(), ctx.accounts.to.to_account_info(), ctx.accounts.system_program.to_account_info(), ] )?; }