1
#[derive(Accounts)]
#[instruction(idx:u64)]
pub struct Initialize<'info> {
    // Derived PDAs
    #[account(
        init,
        payer= user_sending,
        seeds=[b"state".as_ref(), user_sending.key().as_ref(), mint_of_token_sent.key().as_ref(), idx.to_le_bytes().as_ref()],
        bump,
        space =8 +8 +32+ 32+ 32+ 8 +1
    )]
    state: Account<'info, State>,

    #[account(
        init,
        payer= user_sending,
        seeds=[b"wallet".as_ref(), user_sending.key().as_ref(), mint_of_token_sent.key().as_ref(), bridge_idx.to_le_bytes().as_ref()],
        bump,
        token::mint= mint_of_token_sent,
        token::authority=state,
    )]
    vault: Account<'info, TokenAccount>,

    #[account(mut)]
    user_sending: Signer<'info>,
    mint_of_token_sent: Account<'info, Mint>,

    #[account(mut,
        constraint=user_sending_token_account.owner==user_sending.key(),
        constraint=user_sending_token_account.mint==mint_of_token_sent.key(),
    )]
    user_sending_token_account: Account<'info, TokenAccount>,

    system_program: Program<'info, System>,
    token_program: Program<'info, Token>,
    rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
#[instruction(idx:u64)]
pub struct BurnTx<'info> {
    #[account(
        mut,
        seeds=[b"state".as_ref(), user_sending.key().as_ref(), mint_of_token_sent.key().as_ref(), idx.to_le_bytes().as_ref()],
        bump,
        has_one= user_sending,
        has_one=mint_of_token_sent,
    )]
    state: Account<'info, State>,

    #[account(
        mut,
        seeds=[b"wallet".as_ref(), user_sending.key().as_ref(), mint_of_token_sent.key().as_ref(), idx.to_le_bytes().as_ref()],
        bump,
    )]
    vault: Account<'info, TokenAccount>,

    #[account(mut)]
    user_sending: Signer<'info>,
    mint_of_token_sent: Account<'info, Mint>,

    system_program: Program<'info, System>,
    token_program: Program<'info, Token>,
    associated_token_program: Program<'info, AssociatedToken>,
    rent: Sysvar<'info, Rent>,
}

My endpoint:

pub fn burn_tx(ctx: Context<BurnTx>, idx: u64) -> Result<()> {
        let bump = ctx.bumps.state.to_le_bytes();
        let binding = ctx.accounts.user_sending.key();
        let mint_of_token_sent_pk = ctx.accounts.mint_of_token_sent.key();
        let idx_bytes = idx.to_le_bytes();
        let inner = vec![
            b"state".as_ref(),
            binding.as_ref(),
            mint_of_token_sent_pk.as_ref(),
            idx_bytes.as_ref(),
            bump.as_ref(),
        ];

        let outer = vec![inner.as_slice()];

        let burn_instruction = Burn {
            mint: ctx.accounts.mint_of_token_sent.to_account_info(),
            from: ctx.accounts.vault.to_account_info(),
            authority: ctx.accounts.state.to_account_info(),
        };

        let cpi_ctx = CpiContext::new_with_signer(
            ctx.accounts.token_program.to_account_info(),
            burn_instruction,
            outer.as_slice(),
        );

        anchor_spl::token::burn(cpi_ctx, ctx.accounts.state.amount)?;

        let should_close = {
            ctx.accounts.escrow_wallet.reload()?;
            ctx.accounts.escrow_wallet.amount == 0
        };

        if should_close {
            let ca = CloseAccount {
                account: ctx.accounts.vault.to_account_info(),
                destination: ctx.accounts.user_sending.to_account_info(),
                authority: ctx.accounts.state.to_account_info(),
            };

            let cpi_ctx = CpiContext::new_with_signer(
                ctx.accounts.token_program.to_account_info(),
                ca,
                outer.as_slice(),
            );

            anchor_spl::token::close_account(cpi_ctx)?;
        }

        Ok(())
    }

I got this error:

Cross-program invocation with unauthorized signer or writable account.

I am using anchor framework verison 0.29.0.

2 Answers 2

2

same issue can't find anything on this.

update: really simple issue the mint account needs to be marked as mutable

#[account(mut)] <--
mint_of_token: Account<'info, Mint>
1
  • 1
    Same is true for minting. Commented Apr 7 at 11:39
0

I don't know why you had to make PDA to be the authority of the program Token Account...

Regarding Solana Anchor Rust How to burn program-owned ATA token account, you can do it this way:

solana-cli 1.18.18, anchor 0.30.1

  pub fn burn_token(ctx: Context<BurnToken>, amount: u64) -> Result<()> {
    let cpi_accounts = Burn {
      mint: ctx.accounts.mint.to_account_info(),
      from: ctx.accounts.from.to_account_info(),
      authority: ctx.accounts.auth.to_account_info(),
    };
    let cpi_program = ctx.accounts.token_program.to_account_info();

    let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
    msg!("about to burn");
    token::burn(cpi_ctx, amount)?;
    Ok(())
  }
...
#[derive(Accounts)]
pub struct BurnToken<'info> {
  #[account(mut, token::mint = mint, token::token_program = token_program)]
  pub from: Account<'info, TokenAccount>,
  #[account(mut)]
  pub mint: Account<'info, Mint>,
  pub token_program: Program<'info, Token>,
  #[account(mut)]
  pub auth: Signer<'info>,
}

In Anchor JavaScript test file:

        await program.methods
            .burnToken(amount)
            .accounts({
                mint: your_mint,
                from: your_program_token_account,
                //auth: auth123,// omitted because it is the signer
                //tokenProgram: TOKEN_PROGRAM_ID,
            })
            .rpc();

The auth123 has to match how you generated your Program Token account:

  #[account(init, payer = auth123, seeds = [b"your_program_123"], 
bump,token::mint = mint, token::authority = auth123 )]
  pub program_token_account: Account<'info, TokenAccount>,
  pub mint: Account<'info, Mint>,
  #[account(mut)]
  pub auth123: Signer<'info>,

Source: https://betterprogramming.pub/how-to-burn-tokens-using-the-anchor-framework-on-solana-6f3c8c50f857

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.