rust 如何在锚智能合约指令中传递SOL

8ehkhllq  于 2023-01-21  发布在  其他
关注(0)|答案(5)|浏览(195)

我正在创建一个dapp,多个用户可以将SOL存入一个活动帐户,并根据谁赢得了活动,他们可以赎回SOL回到他们的钱包。
如何在锚智能合约指令中将原生SOL(而不是任何其他spl-token)直接传输到事件账户的金库地址?
下面的锚指令是否有效?如果有效,下面的PROGRAM_ACCOUNT应该是什么?应该是处理本机SOL的帐户,但在文档中找不到。

token::transfer(
    CpiContext::new(
        PROGRAM_ACCOUNT,
        anchor_spl::token::Transfer {
            from: source_user_info,
            to: destination_user_info,
            authority: source_user_info,
        },
    ),
    1,
)?;

先谢了!

xam8gpfp

xam8gpfp1#

要使用锚发送本机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(),
        ],
    );

其中,数量是表示Lamports(0.00000001 SOL)的数字(u64)。
您可以查看Solana程序文档中的Transfer函数和发送SOL的Solana Cookbook部分。

qcbq4gxm

qcbq4gxm2#

不幸的是,到目前为止,所有的答案都是普通的索拉纳,而不是锚。
锚已经提供了额外的便利,使转账更容易。您在问题中的代码是正确的:

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)?;

这是假设此帐户结构:

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

当然,如果您使用的是Account<> Package 器,只需将clone()替换为to_account_info()即可。

dba5bblo

dba5bblo3#

对于本机SOL,您必须做一些不同的事情,用系统程序调用system_instruction::transfer,而不是SPL令牌程序。
锚中没有方便的 Package 器(我能找到),所以这里有一个不使用Anchor的例子:https://github.com/solana-labs/solana-program-library/blob/78cb32435296eb258ec3de76ee4ee2d391f397ee/associated-token-account/program/src/tools/account.rs#L29

oewdyzsn

oewdyzsn4#

你必须做这样的事

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(),
    ],
)?;

此外,确保将system_program传递给您的程序。

#[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>,
}

希望这个有用。

wj8zmpe1

wj8zmpe15#

发送带锚的本地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>,
}

参考

https://solanacookbook.com/references/programs.html#how-to-transfer-sol-in-a-program

相关问题