Skip to content
On this page

Burn TIP-3 Tokens

let's burn some tokens 🔥.

In this section we will learn the how to burn TIP-3 tokens from a token wallet.

The TIP-3 standard have to methods to burn tokens:

  • burn: This method will be called on the token wallet and easily burns the tokens.

  • burnByRoot: The burnTokens will be called on the token root contract, accordingly root will call the burnByRoot function on the token wallet and burns the tokens.

TIP

To utilize the burnByRoot function, it is essential to ensure that the burnByRootDisabled parameter is set to false during the deployment of the token root contract. This will enable the functionality required for burning tokens.

Furthermore, it is important to note that only the owner of the root contract has the authority to invoke the burnTokens function.

Step 1: Write Burning Script

Utilize the code sample below to burn TIP- tokens using locklift and the stats of the previously written script in the transfer tip-3 section:

INFO

Before we start to write our scripts we need to make sure that there is a file named 05-burn-tip3.ts in the script folder in the project root.

WARNING

  • Notice that if the Notify parameter be true for the transaction, the change will be sent back to the sender accounts tokenWallet contract !!
    So if you want the change back into your account contract leave the Notify unchecked !!

typescript
// Preparing the burn amounts
const burnAmount: number = 20 * 10 ** decimals;
const burnByRootAmount: number = 10 * 10 ** decimals;

console.log(
  'Alice balance before burn: ',
  Number(
    (
      await aliceTokenWallet.methods
        .balance({
          answerId: 0,
        })
        .call()
    ).value0
  ) /
    10 ** decimals
);

// burning tokens by calling the "burn" method in the alice's token wallet
await aliceTokenWallet.methods
  .burn({
    amount: burnAmount,
    remainingGasTo: aliceAccount.address,
    callbackTo: zeroAddress,
    payload: '',
  })
  .send({
    from: aliceAccount.address,
    amount: locklift.utils.toNano(3),
  });

// checking if tis burned
console.log(
  'Alice balance after burn: ',
  Number(
    (
      await aliceTokenWallet.methods
        .balance({
          answerId: 0,
        })
        .call()
    ).value0
  ) /
    10 ** decimals
);

// burning tokens by calling the "burnTokens" on the token root
await tokenRootContract.methods
  .burnTokens({
    amount: burnByRootAmount,
    walletOwner: aliceAccount.address,
    remainingGasTo: aliceAccount.address,
    callbackTo: zeroAddress,
    payload: '',
  })
  .send({
    from: aliceAccount.address,
    amount: locklift.utils.toNano(3),
  });
console.log(
  'Alice balance after burn by root: ',
  Number(
    (
      await aliceTokenWallet.methods
        .balance({
          answerId: 0,
        })
        .call()
    ).value0
  ) /
    10 ** decimals
);
typescript
import {
  Address,
  Contract,
  Transaction,
} from 'everscale-inpage-provider';
import * as tip3Artifacts from 'tip3-docs-artifacts';
import { provider, providerAddress } from './useProvider';

async function main() {
  try {
    const tokenRootAddress: Address = new Address(
      '<YOUR_TOKEN_WALLET_ADDRESS>'
    );

    // Fetching the required contracts
    const tokenRootContract: Contract<
      tip3Artifacts.FactorySource['TokenRoot']
    > = new provider.Contract(
      tip3Artifacts.factorySource['TokenRoot'],
      tokenRootAddress
    );
    const tokenWalletAddress: Address = (
      await tokenRootContract.methods
        .walletOf({ answerId: 0, walletOwner: providerAddress })
        .call({})
    ).value0;

    const tokenWalletContract: Contract<
      tip3Artifacts.FactorySource['TokenWallet']
    > = new provider.Contract(
      tip3Artifacts.factorySource['TokenWallet'],
      tokenWalletAddress
    );

    // Fetching the decimals
    const [decimals, symbol] = await Promise.all([
      Number(
        (
          await tokenRootContract.methods
            .decimals({ answerId: 0 })
            .call()
        ).value0
      ),
      (await tokenRootContract.methods.symbol({ answerId: 0 }).call())
        .value0,
    ]);

    const burnAmount: number = 100 * 10 ** decimals;

    const oldBal: number =
      Number(
        (
          await tokenWalletContract.methods
            .balance({ answerId: 0 })
            .call()
        ).value0
      ) /
      10 ** decimals;

    // burning tokens from a token wallet by calling the burn method
    const burnRes: Transaction = await tokenWalletContract.methods
      .burn({
        amount: burnAmount,
        payload: '',
        remainingGasTo: providerAddress,
        callbackTo: tip3Artifacts.zeroAddress,
      })
      .send({
        from: providerAddress,
        amount: String(3 * 10 ** 9),
      });

    if (burnRes.aborted) {
      throw new Error(
        `Transaction aborted ! ${
          (burnRes.exitCode, burnRes.resultCode)
        }`
      );
    }
    // Checking if the user already doesn't have the any wallet of that token root
    // Getting the recipient balance

    const newBal: number =
      Number(
        (
          await tokenWalletContract.methods
            .balance({ answerId: 0 })
            .call()
        ).value0
      ) /
      10 ** decimals;

    if (oldBal >= newBal) {
      console.log(
        `${
          burnAmount / 10 ** decimals
        } ${symbol}'s successfully burnt !`
      );

      return `Hash: ${burnRes.id.hash} \n old Balance  ${oldBal} \n New balance: ${newBal}`;
    } else {
      console.error(`Failed \n
      ${(burnRes.exitCode, burnRes.resultCode)}`);
    }

    /*
     Using burnByRoot function

    */
    const burnByRootAmount: number = 50 * 10 ** decimals;

    const oldBalance: number =
      Number(
        (
          await tokenWalletContract.methods
            .balance({ answerId: 0 })
            .call()
        ).value0
      ) /
      10 ** decimals;

    // Deploying a new contract if didn't exist before
    const burnByRotRes: Transaction = await tokenRootContract.methods
      .burnTokens({
        amount: burnByRootAmount,
        walletOwner: providerAddress,
        payload: '',
        remainingGasTo: providerAddress,
        callbackTo: tip3Artifacts.zeroAddress,
      })
      .send({
        from: providerAddress,
        amount: String(3 * 10 ** 9),
      });

    if (burnByRotRes.aborted) {
      throw new Error(
        `Transaction aborted ! ${
          (burnByRotRes.exitCode, burnByRotRes.resultCode)
        }`
      );
    }
    // Checking if the user already doesn't have the any wallet of that token root
    // Getting the recipient balance

    const newBalance: number =
      Number(
        (
          await tokenWalletContract.methods
            .balance({ answerId: 0 })
            .call()
        ).value0
      ) /
      10 ** decimals;

    if (oldBal >= newBal) {
      console.log(
        `${
          burnByRootAmount / 10 ** decimals
        } ${symbol}'s successfully burnt`
      );

      return `Hash: ${burnByRotRes.id.hash} \n old Balance  ${oldBal} \n New balance: ${newBal}`;
    } else {
      throw new Error(`Failed \n
       ${(burnByRotRes.exitCode, burnByRotRes.resultCode)}`);
    }
  } catch (e: any) {
    throw new Error(`Failed: ${e.message}`);
  }
}

Step 2: Burn Tokens

Use this command to burn TIP-3 tokens:

shell
npx locklift run -s ./scripts/05-burn-tip3.ts -n local
burnTip3Output

Congratulations, you have successfully burned TIP-3 tokens from a token wallet 🎉

Burn TIP-3 tokens

Token Root address

Amount

GIF

Burn TIP-3 Tokens By root

TIP

In order to utilize the burnByRoot you must be the root owner !

Token Root address

Target address to burn tokens from

Amount

GIF