1

我在做我认为简单的代币转移时遇到了问题。

首先是一些代码:

#[derive(Accounts)]
#[instruction(amount: u64)]
pub struct TransferTokens<'info> {
    #[account(mut)]
    pub sender: Signer<'info>,
    #[account(mut)]
    pub sender_tokens: Account<'info, TokenAccount>,
    pub recipient_tokens: Account<'info, TokenAccount>,
    pub mint: Account<'info, Mint>,
    #[account(address = SYSTEM_PROGRAM_ID)]
    pub system_program: Program<'info, System>,
    #[account(address = TOKEN_PROGRAM_ID)]
    pub token_program: Program<'info, Token>,
}

pub fn transfer_tokens(ctx: Context<TransferTokens>, amount: u64) -> ProgramResult {
    let sender = &ctx.accounts.sender;
    let sender_tokens = &ctx.accounts.sender_tokens;
    let recipient_tokens = &ctx.accounts.recipient_tokens;
    let token_program = &ctx.accounts.token_program;

    transfer(
        CpiContext::new(
            token_program.to_account_info(),
            Transfer {
                from: sender_tokens.to_account_info(),
                to: recipient_tokens.to_account_info(),
                authority: sender.to_account_info(),
            },
        ),
        amount,
    )?;

    return Ok(());
}
const mint = new PublicKey("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"); // USDC devnet
const sender = program.provider.wallet.publicKey;
const recipient = new PublicKey(otherPublicKey);
const senderATA = await getOrCreateAssociatedTokenAccount(...);
const recipientATA = await getOrCreateAssociatedTokenAccount(...);
let instructions: TransactionInstruction[];
if (senderATA.instruction) instructions.push(senderATA.instruction);
if (recipientATA.instruction) instructions.push(recipientATA.instruction);
if (instructions.length === 0) instructions = undefined;
const price = 1000;

await program.rpc.transferTokens(new BN(price), {
  accounts: {
    sender: sender,
    senderTokens: senderATA.address,
    recipientTokens: recipientATA.address,
    mint,
    systemProgram: SystemProgram.programId,
    tokenProgram: TOKEN_PROGRAM_ID
  },
  instructions
});

当我运行它时,我得到:

Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account 
    Program XXX invoke [1]
    recipientATA.address's writable privilege escalated
    Program XXX consumed 9908 of 200000 compute units
    Program XXX failed: Cross-program invocation with unauthorized signer or writable account

显然发件人必须签署交易,但我想我真的不明白为什么我需要许可才能将令牌发送给其他人。

JS 代码略有缩写,但我正在做的是添加指令以创建令牌帐户,除非它们存在。奇怪的是,当我包含创建令牌帐户的说明时,这第一次起作用,但之后发生“可写权限升级”错误。

谁能看到我做错了什么?

4

1 回答 1

0

当您将代币从一个用户转移到另一个用户时,两个TokenAccounts 都必须标记为可变的,因为在幕后您是从一个用户的金额中减去并添加到另一个用户的金额!

换句话说,您需要同时添加#[account(mut)]接收令牌帐户和与之关联的铸币厂。

#[account(mut)]
pub recipient_tokens: Account<'info, TokenAccount>,

// ...

#[account(mut)]
pub mint: Account<'info, Mint>,
于 2022-02-14T17:54:19.907 回答