Burn tokens
Outline
If you wish to burn
tokens, then use burn
instruction from token
program.
In this chapter we will look at most used functionality of token
program.
By the end of this chapter, you should know be able burn
tokens from token account. The final outcome of this chapter is found here
Prerequisite
For the demonstration purpose, we will retain only create_mint
, transfer_mint
instructions.
So the remove the following
freeze_token_account
instructionunfreeze_token_account
instructiontransfer_token_to_another
instructionTransferTokenToAnother
contextUnfreezeTokenAccount
contextFreezeTokenAccount
context
And remove test cases related to them.
Or you can clone the Chapter-5 repo for getting started immediately.
How to burn
tokens ?
We use burn
instruction from token_program
to destroy minted tokens. Again, only spl_token_mint` authority can perform this action.
Let us follow the 2-step process to burn
a token.
- Create a
BurnToken
context - Write a
burn_token
instruction to performburn
action.
Step-1 : Create a BurnToken
context ?
Create a BurnToken
context using the struct
in lib.rs
file.
In this code, we burn a token from payer_mint_ata
account.
// Burn token
#[derive(Accounts)]
pub struct BurnToken<'info> {
#[account(
mut,
seeds = [
b"spl-token-mint".as_ref(),
],
bump = vault.spl_token_mint_bump,
)]
pub spl_token_mint: Account<'info, Mint>, // ---> 1
#[account(
seeds = [
b"vault"
],
bump = vault.bump, // --> 2
)]
pub vault : Account<'info, Vault>,
#[account(mut)]
pub payer : Signer<'info>, // ---> 3
#[account(
mut,
associated_token::mint = spl_token_mint,
associated_token::authority = payer
)]
pub payer_mint_ata: Box<Account<'info, TokenAccount>>, // --> 4
pub system_program: Program<'info, System>, // ---> 5
pub token_program: Program<'info, Token>, // ---> 6
pub rent: Sysvar<'info, Rent>, // ---> 7
pub associated_token_program : Program<'info, AssociatedToken>, // ---> 8
}
- We pass the
spl_token_mint
account without anymut
orinit
decoration. - We pass the
vault
. Again, this can be used for security purpose. - We pass
payer
as thesigner
this time. - We pass
payer_mint_ata
where we want tofreeze
the account. system_program
account for executing the instruction.token_program
account used for performingfreeze
operationrent
might have to passed as we are usingassociated_token_program
associated_token_program
account is passed for creating ATA.
With this context, we can invoke a burn
instruction.
Step-2 : Create a burn_token
instruction ?
We use the burn
instruction from token_program
to burn tokens. A CPI
call is made to token_program
to achieve this.
Let us first update the import in lib.rs
file
use anchor_spl::{token::{self, Mint, Token, TokenAccount, FreezeAccount, ThawAccount, Burn}, associated_token::AssociatedToken};
Add burn_token
instruction.
pub fn burn_token(ctx : Context<BurnToken>) -> Result<()> {
let cpi_context = CpiContext::new(
ctx.accounts.token_program.to_account_info(),
Burn {
from : ctx.accounts.payer_mint_ata.to_account_info(),
mint : ctx.accounts.spl_token_mint.to_account_info(),
authority : ctx.accounts.payer.to_account_info()
},
);
token::burn(cpi_context, 1)?; // we burn 1 token
Ok(())
}
We burn 1 token from payer_mint_ata
account.
To test this, let's us write a test case in spl-token.ts
file.
Add the following test case in describe
block
it("should burn a token of payer wallet ", async () => {
try {
const [splTokenMint, _1] = await findSplTokenMintAddress();
const [vaultMint, _2] = await findVaultAddress();
const [payerMintAta, _3] = await findAssociatedTokenAccount(
payer.publicKey,
splTokenMint
);
const tx = await program.methods
.burnToken()
.accounts({
splTokenMint: splTokenMint,
vault: vaultMint,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
tokenProgram: TOKEN_PROGRAM_ID,
systemProgram: SystemProgram.programId,
payerMintAta: payerMintAta,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
payer: payer.publicKey,
})
.signers([payer])
.rpc();
console.log("Your transaction signature", tx);
} catch (err) {
console.log(err);
}
});
Run the test command
anchor test
With that, we should see the below output with a successfully executed transaction.