Unfreeze token account
Outline
thaw instruction from token program is used to unfreeze a frozen token account.
Therefore, the prerequisite to thaw instruction is that the token account is frozen.
The final outcome of this chapter can be found here
Prerequisite
For the demonstration purpose, we will be using the previous chapter's repo. You can clone the repo for getting started.
How to Thaw (unfreeze) an account ?
A thaw operation is done on a token account to unfreeze a frozen account. Only spl_token_mint authority can perform this action. Hence only payer can perform this action.
This also involves the below process.
- Create a
UnfreezeTokenAccountcontext - Then write an instruction for freezing the token.
Step-1 : Let's create a UnfreezeTokenAccount context using the struct
// Unfreeze token account
#[derive(Accounts)]
pub struct UnfreezeTokenAccount<'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_mintaccount without anymutorinitdecoration. - We pass the vault. Again, this can be used for security purpose.
- We pass
payeras thesignerthis time. - We pass
payer_mint_atawhere we want tofreezethe account. system_programaccount for executing the instruction.token_programaccount used for performingfreezeoperationrentmight have to passed as we are usingassociated_token_programassociated_token_programaccount is passed for creating ATA.
We will now create an instruction unfreeze_token_account to unfreeze the token account.
Step-2 : Update the imports.
First, let us update the import lib.rs
use anchor_spl::{token::{self, Mint, Token, TokenAccount, FreezeAccount, ThawAccount}, associated_token::AssociatedToken};
Add the unfreeze_token_account instruction.
pub fn unfreeze_token_account(ctx : Context<UnfreezeTokenAccount>) -> Result<()> {
let cpi_context = CpiContext::new(
ctx.accounts.token_program.to_account_info(),
ThawAccount {
account : 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::thaw_account(cpi_context)?;
Ok(())
}
Add a test case in spl-token.ts to test unfreeze instruction.
it("should unfreeze token account 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
.unfreezeTokenAccount()
.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 command
anchor test
You should see a successful test run.

In the chapter, we will focus on burning tokens.