Как перенести SOL в инструкцию смарт-контракта привязки
Я создаю децентрализованное приложение, в котором несколько пользователей могут вносить SOL в учетную запись события, и в зависимости от того, кто выиграет мероприятие, они могут выкупить SOL обратно в свой кошелек.
Как я могу передать SOL (а не любой другой spl-токен) непосредственно в адрес хранилища учетной записи события в инструкции смарт-контракта привязки?
5 ответов
Чтобы отправить собственный SOL с помощью Anchor, вы можете использовать следующий код внутри инструкции:
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(),
],
);
Где сумма — это число (u64), представляющее Лэмпортс (0,000000001 SOL).
Вы можете проверить функцию Transfer в документации по программе Solana и в разделе Solana Cookbook вSending SOL .
К сожалению, все ответы до сих пор относятся к простой Солане, а не к Якорю.
Якорь уже поставляется с дополнительными удобствами, облегчающими переводы. Вы были на правильном пути с кодом в вопросе:
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<>
обертки, просто заменитеclone()
сto_account_info()
.
Вы должны сделать что-то вроде этого
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>,
}
Надеюсь это поможет.
Для собственного SOL вам придется сделать что-то немного другое, вызвав
system_instruction::transfer
с системной программой, а не с программой токена SPL.
В Anchor нет удобной оболочки (которую я могу найти), поэтому вот пример без Anchor: https://github.com/solana-labs/solana-program-library/blob/78cb32435296eb258ec3de76ee4ee2d391f397ee/associated- токен-счет/программа/src/tools/account.rs#L29
Чтобы отправить собственный 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