Upgradeable ERC20 token with partial burn on transfer

How can you make this contract upgradeable. Please could you provide the upgradeable version of the MyToken.sol

1 Like

Hi @costech,

I assume you want an upgradeable ERC20 token with mint, burn and pause?
The equivalent of StandaloneERC20.sol + burn.

1 Like

Exactly. Say 3% burn for every Token holder transfer.

1 Like

Hi @costech,


First of all, I suggest looking at Points to consider when creating a fungible token (ERC20, ERC777)

Tokens should be appropriately tested and audited, along with ensuring regulatory compliance.

:warning: A deflationary token can cause issues such as this recent issue: https://medium.com/balancer-protocol/incident-with-non-standard-erc20-deflationary-tokens-95a0f6d46dea

I have done a simple example of an upgradeable version of a contract that burns 3% of tokens on transfer that is also mintable and pausable, though please note I have not done any of the required automated testing.

I recommend that any such contract be fully tested and audited.
For testing, I suggest using the following guide: Test smart contracts like a rockstar


pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Mintable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Pausable.sol";
 * @title MyToken
 * @dev ERC20 Token example, where all tokens are pre-assigned to the creator.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` functions.
contract MyToken is Initializable, ERC20, ERC20Detailed, ERC20Mintable, ERC20Pausable {

    uint256 private _minimumSupply;

     * @dev Gives holder all of existing tokens.
    function initialize(address holder, address minter, address pauser) public initializer {
        ERC20Detailed.initialize("MyToken", "MYT", 18);

        _minimumSupply = 2000 * (10 ** 18);

        _mint(holder, 10000 * (10 ** uint256(decimals())));

    function transfer(address to, uint256 amount) public returns (bool) {
        return super.transfer(to, _partialBurn(amount));

    function transferFrom(address from, address to, uint256 amount) public returns (bool) {
        return super.transferFrom(from, to, _partialBurn(amount));

    function _partialBurn(uint256 amount) internal returns (uint256) {
        uint256 burnAmount = _calculateBurnAmount(amount);

        if (burnAmount > 0) {
            _burn(msg.sender, burnAmount);

        return amount.sub(burnAmount);

    function _calculateBurnAmount(uint256 amount) internal view returns (uint256) {
        uint256 burnAmount = 0;

        // burn amount calculations
        if (totalSupply() > _minimumSupply) {
            burnAmount = amount.mul(3).div(100);
            uint256 availableBurn = totalSupply().sub(_minimumSupply);
            if (burnAmount > availableBurn) {
                burnAmount = availableBurn;

        return burnAmount;


$ oz create
✓ Compiled contracts with solc 0.5.11 (commit.c082d0b4)
? Pick a contract to instantiate MyToken
? Pick a network development
✓ Deploying @openzeppelin/contracts-ethereum-package dependency to network dev-1569294282448
✓ Contract MyToken deployed
All contracts have been deployed
? Do you want to call a function on the instance after creating it? Yes
? Select which function * initialize(holder: address, minter: address, pauser: address)
? holder (address): 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
? minter (address): 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
? pauser (address): 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
✓ Setting everything up to create contract instances
✓ Instance created at 0xA57B8a5584442B467b4689F1144D269d096A3daF


$ oz send-tx
? Pick a network development
? Pick an instance MyToken at 0xA57B8a5584442B467b4689F1144D269d096A3daF
? Select which function transfer(to: address, amount: uint256)
? to (address): 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
? amount (uint256): 100
✓ Transaction successful. Transaction hash: 0x59452556d29f2452ab9452dc939edc4a59337b399510c29424602c6bc15a5ae8
$ oz call
? Pick a network development
? Pick an instance MyToken at 0xA57B8a5584442B467b4689F1144D269d096A3daF
? Select which function balanceOf(owner: address)
? owner (address): 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✓ Method 'balanceOf(address)' returned: 97
1 Like

You’re awesome. This is what I need. Thank you

1 Like

Hi @costech,

Keep asking (and answering) all the questions that you need.

Thanks for being part of the community. :pray:


A post was split to a new topic: Upgrade Token to include burn

A post was split to a new topic: Is there a way to add burn function to deployed ERC20 token?