Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Token Burning Explained

Hello! Welcome back to our journey in building your own cryptocurrency token.

In the last lesson, we gave our token a dynamic supply by implementing a mint function. We secured it using OpenZeppelin's Ownable contract, ensuring that only you, the contract owner, have the power to create new tokens.

Today, we'll explore the other side of supply management: destroying tokens. This process, known as burning, is a fundamental mechanism for creating deflationary pressure and managing the token's economic model. Your learning outcome for this lesson is to implement a burning function to permanently destroy tokens.


1. What is Token Burning?

Token burning is the process of permanently removing tokens from circulation. This is achieved by sending them to an address from which they can never be retrieved, effectively destroying them.

Why would you want to do this?

  • Create Scarcity: By reducing the total supply, burning can make the remaining tokens more scarce, which can potentially increase their value (a deflationary model).
  • Utility Consumption: In applications like games, a token might represent a consumable item (e.g., a magic potion). Once used, the token should be burned.
  • Economic Stability: Some projects burn a portion of transaction fees to constantly reduce the supply and reward holders.

There are two common ways to "burn" a token. Watch the beginning of this video to understand them and see why one is clearly better.

ERC721 ERC20 Burnable (OpenZeppelin Solidity implementation): The proper way to burn tokens

This video from BlockchainBob clearly explains what burning means and compares the two main methods: sending to a 'dead address' versus using a proper burn function. Although it uses NFTs (ERC-721) as an example, the core principle is identical for our ERC-20 token.

Watch from 00:03 to 01:47. Focus on the distinction between simply sending a token to the zero address and using a function that properly updates the contract's internal state, like totalSupply.

As the video explains, simply transferring tokens to the zero address (0x00...) makes them inaccessible, but it doesn't decrease the contract's reported totalSupply. This is misleading. With your backend experience, you can think of this as a "soft delete"—the data is still there, just marked as inactive.

A proper burn function performs a "hard delete." It not only removes the tokens from the user's balance but also decreases the totalSupply, which is a more accurate and transparent approach.


2. Standard Implementation: The ERC20Burnable Extension

Just as we used Ownable for access control, we can use a pre-built, audited extension from OpenZeppelin to add burn functionality securely. This module is called ERC20Burnable.

ERC-20 Token Configuration and Solidity Code Snippet
This interface from the OpenZeppelin Contracts Wizard shows how 'Burnable' is a standard, selectable feature when creating a token, just like the 'Mintable' feature we added in the previous lesson.

By inheriting from ERC20Burnable, our contract automatically gains two new public functions:

  1. burn(uint256 amount): Allows any token holder to destroy a specified amount of their own tokens.
  2. burnFrom(address account, uint256 amount): Allows an address that has been given an "allowance" to burn tokens on behalf of another account. This uses the approve and transferFrom pattern, which we will cover in more detail soon.

Let's integrate this into our contract. The process is very similar to how we added Ownable.

ERC-20 Token with Mint, Burn, and Pause - Grasp

The following resource provides a clear example of how to add burn functionality to an ERC-20 token using OpenZeppelin's ERC20Burnable contract.

Read the section titled '3. Adding Mint and Burn Functionality'. Pay close attention to the MyToken.sol code example and the 'Key changes' list, which explain how ERC20Burnable is imported and used.

Here is the updated code for MyToken.sol. Notice how little we need to add to get this powerful functionality.

// contracts/MyToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
// 1. Import the ERC20Burnable extension
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";

/**
 * @title MyToken
 * @dev An ERC20 token that is mintable by its owner and burnable by its holders.
 */
// 2. Add ERC20Burnable to the inheritance list
contract MyToken is ERC20, Ownable, ERC20Burnable {
    constructor() ERC20("My Awesome Token", "MAT") Ownable(msg.sender) {}

    /**
     * @dev Creates `amount` new tokens and assigns them to `to`.
     * Can only be called by the owner.
     */
    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    // The public `burn(uint256 amount)` and `burnFrom(address, uint256)`
    // functions are automatically available by inheriting from ERC20Burnable.
    // No need to write them ourselves!
}

By adding just two lines—the import statement and the contract in the inheritance list—our token is now burnable. Any user can call myToken.burn(100) to destroy 100 of their own tokens, and the totalSupply will be correctly updated. This demonstrates the power of building with modular, reusable components.

Test your understanding!

Imagine you deploy MyToken and mint 1,000 tokens to your address. The totalSupply is 1,000. You then call the burn(400) function from your address.

  1. What will your new token balance be?
  2. What will the new totalSupply of the token be?
  3. Who can call the burn function on your tokens?
Show answer
  1. Your new balance will be 600 tokens (1000 - 400).
  2. The new totalSupply will also be 600 tokens. The ERC20Burnable extension handles decreasing both the user's balance and the total supply.
  3. Only you can call burn on your own tokens. Another user cannot burn your tokens unless you have specifically approved them to do so using the approve function.

3. Advanced Burning: Deflationary Tokens

The ERC20Burnable extension provides a manual way for users to burn tokens. However, some projects, like SafeMoon, implement an automatic burn mechanism where a small fee from every single transaction is automatically burned. This creates a "deflationary" or "reflective" token.

How can we achieve this? We can override the internal _transfer function. Since both the public transfer and transferFrom functions rely on _transfer, modifying it acts like a middleware that intercepts all token movements.

The logic would be:

  1. When a _transfer is initiated, calculate a fee amount (e.g., 1% of the transfer amount).
  2. Burn the fee amount directly from the sender's balance and reduce the total supply.
  3. Transfer the original amount minus the fee to the recipient.

This is a more complex pattern, but it's a powerful way to build unique tokenomics. The following video walks through how to build such a contract from scratch. You don't need to code along, but focus on understanding the logic inside the _transfer function.

Build a Deflationary ERC20 Token from Scratch with Solidity | Like SafeMoon | Transfers Burn Tokens

This video from Blockman Codes demonstrates how to create a deflationary token that burns a percentage of every transfer. This is a great example of a more advanced, custom implementation.

Watch from 09:56 to 13:58. This is the core of the implementation. Pay close attention to how the private _transfer function is modified to calculate a fee, burn a portion of the tokens, and then transfer the remaining amount.

This custom approach shows that while OpenZeppelin provides excellent building blocks, you still have the full power to tailor the logic to fit your project's specific needs by overriding internal functions.


Conclusion

Great work! You've now implemented both sides of supply management: minting and burning. You learned how to use standard, secure OpenZeppelin extensions for common functionality and got a glimpse of how to implement custom logic for more advanced tokenomics.

Key Takeaways:

  • Burning permanently destroys tokens and reduces the totalSupply.
  • A proper burn function is superior to simply sending tokens to a zero address because it keeps the contract's state accurate.
  • ERC20Burnable is the standard OpenZeppelin extension that provides a public burn function, allowing users to destroy their own tokens.
  • For advanced, automatic burning mechanisms (like a transaction tax), you can override internal functions like _transfer to inject custom logic.

Preview of the Next Lesson:
Our token contract is now feature-complete with minting and burning capabilities! But code that only exists on our local machine isn't very useful. In the next lesson, we will write a Hardhat script to deploy your ERC-20 token to a testnet, taking the first step towards making it live and interactive.

Can't find a good explanation? Sign up and we'll make it for you

Sign up