Skip to main content
11 of 11
idk bugged browser

Hey there if you are using anchor, you can do cpis in a "anchor way". Also the account that is sending sol either the account is owned by the program(cpi with signer seeds) or needs to be the Signer/Owner.(simple cpi) ( ill show you the both options )

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

#[program]
mod hello_anchor {
use super::*;
pub fn initialize(ctx: Context<Initialize>, data: u64) -> 
Result<()> {
    ctx.accounts.init(&ctx.bumps, data)?;
    msg!("Changed data to: {}!", data);
    Ok(())
}

pub fn send_sol(ctx: Context<SendSol>, amount: u64) -> Result<()> 
{
    ctx.accounts.send_sol(amount)
}
pub fn send_sol_pda(ctx: Context<SendSolPda>, amount: u64) -> 
Result<()> {
    ctx.accounts.send_sol_pda(amount)
}
}
//Owner Signer way
#[derive(Accounts)]
pub struct SendSol<'info> {
#[account(mut)]
pub sender: Signer<'info>,
pub receiver: AccountInfo<'info>,
pub system_program: Program<'info, System>,
}

impl<'info> SendSol<'info> {    
pub fn send_sol(
    &mut self,
    amount:u64,
) -> Result<()> {       
    let accounts = Transfer {
        from: self.sender.to_account_info(),
        to: self.receiver.to_account_info()
    };

    let ctx = CpiContext::new(
        self.system_program.to_account_info(),
        accounts
    );

    transfer(ctx, amount)
}
}
//PDa way
#[derive(Accounts)]
pub struct SendSolPda<'info> {
#[account(
    seeds=[b"sender"],
    bump = sender.bump
)]
pub sender: Account<'info, SigningAccount>,
pub receiver: AccountInfo<'info>,
pub system_program: Program<'info, System>,
}

impl<'info> SendSolPda<'info> {    
pub fn send_sol_pda(
    &mut self,
    amount:u64,
) -> Result<()> {       
    let accounts = Transfer {
        from: self.sender.to_account_info(),
        to: self.receiver.to_account_info()
    };
    let seeds = &[
        &b"sender"[..],
        &[self.sender.bump],
    ];

    let signer_seeds = &[&seeds[..]];

    let ctx = CpiContext::new_with_signer(
        self.system_program.to_account_info(),
        accounts,
        signer_seeds
    );

    transfer(ctx, amount)
}
}

#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
      init,
      payer = signer,          
      seeds = [b"sender"], 
      bump,
      space = SigningAccount::LEN
)]
pub new_account: Account<'info, SigningAccount>,
#[account(mut)]
pub signer: Signer<'info>,
pub system_program: Program<'info, System>,
}

impl<'info> Initialize<'info> {
pub fn init(
    &mut self, 
    bumps: &InitializeBumps,
    data: u64,
) -> Result<()> {
    
    self.new_account.set_inner(SigningAccount{ 
        data, 
        bump: bumps.new_account
});
    Ok(())

}

}

#[account]
pub struct SigningAccount {
data: u64,
bump: u8,
}

impl SigningAccount {
pub const LEN: usize = 8 + 8 + 1;

}

Notes:

  1. Changed your send_sol function;
  2. Added send_sol_pda function;
  3. Fixed and added the normal cpi way;
  4. Added Pda Cpi;
  5. Also added a set_inner when initing the type SigningAccount accounts.