'How to transfer SOL in anchor smart contract instruction
I am creating a dapp where multiple users can deposit SOL into an event account, and depending on whoever wins the event, they can redeem SOL back to their wallet.
How can I transfer native SOL (not any other spl-token) directly into the event account's vault address in an anchor smart contract instruction?
Would the following anchor instruction work?
If yes, what should be the PROGRAM_ACCOUNT in the following? Presumably, it should be the account that handles native SOL, but I couldn't find it in the documentation.
token::transfer(
CpiContext::new(
PROGRAM_ACCOUNT,
anchor_spl::token::Transfer {
from: source_user_info,
to: destination_user_info,
authority: source_user_info,
},
),
1,
)?;
Thanks in advance!
Solution 1:[1]
To send native SOL using Anchor, you can use the following code inside an instruction:
let ix = anchor_lang::solana_program::system_instruction::transfer(
&ctx.accounts.from.key(),
&ctx.accounts.to.key(),
amount,
);
anchor_lang::solana_program::program::invoke(
&ix,
&[
ctx.accounts.from.to_account_info(),
ctx.accounts.to.to_account_info(),
],
);
Where amount is a number (u64) representing the Lamports (0.000000001 SOL).
You can check the Transfer function in the Solana Program documentation and the Solana Cookbook section of Sending SOL.
Solution 2:[2]
You have to do something like this
let lamports: u64 = 1000000;
let sol_transfer = anchor_lang::solana_program::system_instruction::transfer(
&ctx.accounts.from.key,
&ctx.accounts.to.key,
lamports,
);
invoke(
&sol_transfer,
&[
ctx.accounts.from.clone(),
ctx.accounts.to.clone(),
ctx.accounts.system_program.clone(),
],
)?;
Also, make sure to pass system_program to your program. For example
#[derive(Accounts)]
pub struct SolSend<'info> {
#[account(mut, signer)]
/// CHECK: This is not dangerous because we don't read or write from this account
pub from: AccountInfo<'info>,
/// CHECK: This is not dangerous because we don't read or write from this account
#[account(mut)]
pub to: AccountInfo<'info>,
/// CHECK: This is not dangerous because we don't read or write from this account
pub system_program: AccountInfo<'info>,
}
Hope this helps.
Solution 3:[3]
For native SOL, you'll have to do something a bit different, calling system_instruction::transfer with the system program, and not the SPL token program.
There isn't a handy wrapper in Anchor (that I can find), so here's an example of doing it without Anchor: https://github.com/solana-labs/solana-program-library/blob/78cb32435296eb258ec3de76ee4ee2d391f397ee/associated-token-account/program/src/tools/account.rs#L29
Solution 4:[4]
To send native SOL with Anchor
#[program]
pub mod learn_solana_anchor {
use super::*;
pub fn transfer_native_sol(ctx: Context<Transfer>) -> Result<()> {
let amount_of_lamports = 42; // could be an argument ;-)
let from = ctx.accounts.from.to_account_info();
let to = ctx.accounts.to.to_account_info();
// Debit from_account and credit to_account
**from.try_borrow_mut_lamports()? -= amount_of_lamports;
**to.try_borrow_mut_lamports()? += amount_of_lamports;
Ok(())
}
}
#[derive(Accounts)]
pub struct Transfer<'info> {
#[account(mut)]
/// CHECK: This is not dangerous because its just a stackoverflow sample o.O
pub from: AccountInfo<'info>,
#[account(mut)]
/// CHECK: This is not dangerous because we just pay to this account
pub to: AccountInfo<'info>,
#[account()]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
Ref
https://solanacookbook.com/references/programs.html#how-to-transfer-sol-in-a-program
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | patriciobcs |
| Solution 2 | scripter |
| Solution 3 | Jon C |
| Solution 4 | Sr. Oshiro |
