简体   繁体   English

如何在锚定智能合约指令中转账SOL

[英]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.我正在创建一个 dapp,多个用户可以在其中将 SOL 存入一个活动帐户,并且取决于谁赢得了活动,他们可以将 SOL 兑换回他们的钱包。

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?如何在锚定智能合约指令中将原生 SOL(而非任何其他 spl 代币)直接转移到活动账户的金库地址?

Would the following anchor instruction work?以下锚指令是否有效? If yes, what should be the PROGRAM_ACCOUNT in the following?如果是,下面的PROGRAM_ACCOUNT应该是什么? Presumably, it should be the account that handles native SOL, but I couldn't find it in the documentation.推测应该是处理原生SOL的账号,但是我在文档中没有找到。

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!提前致谢!

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.另外,请确保将 system_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.希望这可以帮助。

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.对于本机 SOL,您必须做一些不同的事情,使用系统程序而不是 SPL 令牌程序调用system_instruction::transfer

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 Anchor 中没有方便的包装器(我可以找到),所以这里有一个没有 Anchor 的示例: https://github.com/solana-labs/solana-program-library/blob/78cb32435296eb258ec3de76ee4ee2d391f397ee/associated-令牌帐户/程序/src/tools/account.rs#L29

To send native SOL using Anchor, you can use the following code inside an instruction:要使用 Anchor 发送本机 SOL,您可以在指令中使用以下代码:

    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).其中,amount 是代表Lampports (0.000000001 SOL) 的数字 (u64)。

You can check the Transfer function in the Solana Program documentation and the Solana Cookbook section of Sending SOL .您可以查看 Solana 程序文档和发送 SOLSolana Cookbook部分中的Transfer function。

To send native SOL with Anchor使用 Anchor 发送本机 SOL

#[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 https://solanacookbook.com/references/programs.html#how-to-transfer-sol-in-a-program

Unfortunately, all of the answers thus far are for plain Solana, not Anchor.不幸的是,到目前为止,所有答案都是针对普通的 Solana,而不是 Anchor。

Anchor already comes with additional conveniences to make transfers easier. Anchor 已经提供了额外的便利,使转移更容易。 You were on the right track with the code in the question:您使用问题中的代码走在正确的轨道上:

use anchor_lang::system_program;

let cpi_context = CpiContext::new(
    ctx.accounts.system_program.to_account_info(), 
    system_program::Transfer {
        from: ctx.accounts.account_a.clone(),
        to: ctx.accounts.account_b.clone(),
    });
system_program::transfer(cpi_context, bid_amount)?;

This is assuming this accounts struct:这是假设这个帐户结构:

#[derive(Accounts)]
pub struct MyInstruction<'info> {
    account_a: AccountInfo<'info>,
    account_b: AccountInfo<'info>,
}

Of course, if you are using Account<> wrappers, just replace clone() with to_account_info() .当然,如果您使用Account<>包装器,只需将clone()替换为to_account_info()

one thing I am confused about, where to specify public key like to whom I am sending我很困惑的一件事是,在哪里指定公钥,比如我要发送给谁

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM