Basic question about burning testnet tokens


I created a testnet token using the templated Openzeppelin erc20 code and the full set of imports

import "@openzeppelin/contracts@4.8.0/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC20/extensions/ERC20Snapshot.sol";
import "@openzeppelin/contracts@4.8.0/access/Ownable.sol";
import "@openzeppelin/contracts@4.8.0/security/Pausable.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC20/extensions/ERC20FlashMint.sol";

I compiled the file several times (testnet token wasn't showing in metamask quickly enough:) so minted way more than intended.

Now I want to burn the excess

On reading how to do this, it seemed quite simple; in the burn function code section, I believed i simply needed to add account address and amount to burn, connect to metamask and recompile, as below (account address changed)

function _burn(address account, uint256 amount)
        override(ERC20, ERC20Votes)
        super._burn(0xb680s76w543sf8912b4eb3a9002fefacc692a2a9, 3000000000000);

also tried

function _burn(address 0xb680s76w543sf8912b4eb3a9002fefacc692a2a9, uint256 3000000000000)
        override(ERC20, ERC20Votes)
        super._burn(account, amount);

however, this gave me the following errors

ParserError: Expected ',' but got 'Number'

Are both of these locations NOT where I need to insert the account and the amount to achieve the burn?

And if not, where am I to specify (and in what format) the account address and burn amount?

Hello @Dennis_McMahon

The _burn function is internal, and cannot be called by anyone. Overriding it is not the right approach.

What you want, is to expose a public (or external) function that provides an entrypoint to this internal function. Be aware that this public (or external) function will probably need to be protected.

I strongly advise that you try out the openzeppelin wizard. If you check the "burnable" toogle, it will import @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol which gives an example of how _burn can be exposed safely.

Hi Amxx

Yes when I created the file, I imported the burnable function, so it's already included in the compiled contract.

My question now is how do actually use the function to burn excess tokens?:slight_smile:

If you imported and inherited ERC20Burnable.sol (as done by the wizard when checking the "burnable" box) then the contract will have 2 public functions:

  • burn(uint256 amount)
  • burnFrom(address account, uint256 amount)

The first one can be used by any user to burn their own tokens. The second one allow a user to burn someone else's token, provided that the owner authorized that user to manipulate his/her tokens.

You can find javascript code that calls these function in the test file for this contract


yes it does

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)

pragma solidity ^0.8.0;

import "../ERC20.sol";
import "../../../utils/Context.sol";

 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
abstract contract ERC20Burnable is Context, ERC20 {
     * @dev Destroys `amount` tokens from the caller.
     * See {ERC20-_burn}.
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);

     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     * See {ERC20-_burn} and {ERC20-allowance}.
     * Requirements:
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
    function burnFrom(address account, uint256 amount) public virtual {
        _spendAllowance(account, _msgSender(), amount);
        _burn(account, amount);

This is from the erc20Burnable.sol file

so we are all clear that I have the function yes?

And the code above calls the function right?

So now we just need 3 steps:

  1. Connect that code to the Token Address (which I assume is automatically done because that contract generated that Token Address, correct?)

  2. Connect the Account address where the token burning is to take place to this contract - it's another account so will be burnFrom so the question is - where does account address get typed in and what does it replace in the code?

do I / can I do the below in the ERC20Burnable.sol file then compile that file?

burnFrom(0x9876shd67457383 account, 10000 amount)

or is it

burnFrom(address 0x9876shd67457383, uint256 10000)

If not this, what and where do i insert my account address and amount to be burnt?

or just burnFrom(0x9876shd67457383, 10000)

this is not a valid address.

In order to burn 1000 units (wei) from an account (lets say account 0x7859821024E633C5dC8a4FcF86fC52e7720Ce525) you have two option:

  • the owner itself can call burn(1000)
  • a third party, which must have received prior approval by the token owner, can call burnFrom(0x7859821024E633C5dC8a4FcF86fC52e7720Ce525, 1000)

Previous answers from @amxx should provide you with the answers.

However I would like to take a step back and ask you something about your original question

I compiled the file several times (testnet token wasn't showing in metamask quickly enough:) so minted way more than intended.

Compiling a solidity smart contract does not deploy a contract so does it wouldn't have minted "more" tokens then you expected.

If you meant you deployed the contract several times, then that would not "increase" the tokens, instead you would have deployed several different tokens (different addresses) with the same name.

Now I want to burn the excess

Assuming instead you meant you called the mint function of the contract multiple times you would indeed then have to burn the tokens.

On reading how to do this, it seemed quite simple; in the burn function code section, I believed i simply needed to add account address and amount to burn, connect to metamask and recompile, as below (account address changed)

Changing the solidity smart contract and recompiling and then deploying it, would create another "new" token with the same name.
Instead you would need to call the burn function of the existing contract.

You didn't mention how you compiled/deployed the code, if you used remix then you can directly call the functions from there. If you used another method you would have to call the burn function from javascript yourself.


Maybe I misunderstood the decimals in seeking to mint the original amount (which was 100,000,000), but yes, I did call the mint function multiple times!

I ended up with 3,934,640,807,529**.** 6537 tokens + the 100,000,000 I wanted to mint which is obviously more than I bargained for:), all under the same contract address 0x8c218927849E65B11B35e037dbe2779Ce3Aeed47

I transferred the excess into account 1 of my metamask wallet, just to get them out of my "Treasury" account so I assume that means that I am the original contract owner and need to use the burn function, rather than the burnfrom function

So yes, I now need to burn the excess supply over 100,000,000

I used remix, so when you say I can directly call the burn function from there, do i retain the full openzeppelin code, make my mint function zero and insert my total required to burn in the burn function?

Or I need to only deploy the burn function section of the code and insert burn(3,934,640,807,529**.** 6537) and compile?

That's where I think I am stuck at the moment, so I have been looking for just the code snippet I need to run to burn the excess.

What that snippet is may seem obvious to you:) but it's bamboozling me!

Thanks for the help