Update deflationary ERC20 from OpenZeppelin Contracts 2.x to 3.x

Hi,
I tested implementing this contract, with the openzeppelin-solidity 2.5 includes and it worked very well
Later, testing other things, I updated the includes openzeppelin-solidity 3X and my previous code did not work

I'm trying to adjust the code so that, taking advantage of the openzeppelin-solidity 3.x libraries, it works, but I'm not moving from here:

contract MyToken is ERC20 {

    uint256 private _minimumSupply = 2000 * (10 ** 18);

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
constructor () public ERC20( "MyToken", "MTN") {
    _mint(msg.sender, 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.div(100);
        uint256 availableBurn = totalSupply().sub(_minimumSupply);
        if (burnAmount > availableBurn) {
            burnAmount = availableBurn;
        }
    }

    return burnAmount;
}   
}

I am testing in remix, and I try to include the files corresponding to version 2.5 again, they do not work,
I understand that they were overwritten and only the includes from version 3.x are kept

Can you explain to me what the difference is and how to correct it

Thank you very much

1 Like

Hi @Refresko,

:warning: If you create a fee on transfer or deflationary token (burn a percentage on transfer) this can cause issues when used with other contracts such as: https://medium.com/balancer-protocol/incident-with-non-standard-erc20-deflationary-tokens-95a0f6d46dea
From: Points to consider when creating a fungible token (ERC20, ERC777)


You were missing the keyword override that was introduced in Solidity 0.6, see: https://docs.soliditylang.org/en/v0.7.5/060-breaking-changes.html?highlight=override#how-to-update-your-code

:warning: The following code has not been tested nor audited. Deflationary tokens can cause issues. (see above)

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.2;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {

    uint256 private _minimumSupply = 2000 * (10 ** 18);

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
    constructor () public ERC20( "MyToken", "MTN") {
        _mint(msg.sender, 10000 * (10 ** uint256(decimals())));
    }

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

    function transferFrom(address from, address to, uint256 amount) public override 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.div(100);
            uint256 availableBurn = totalSupply().sub(_minimumSupply);
            if (burnAmount > availableBurn) {
                burnAmount = availableBurn;
            }
        }

        return burnAmount;
    }   
}

Friend, thanks for the reply.
And thanks for the warning of the “risk” deflationary tokens and for correcting and demonstrate the absence of the word override

Regards!!!

1 Like

Sorry that such simple things make me ask you, but I do not understand the error

I am trying to test in VS code studio
I already have the WLS 2 and am using Truffle

So, in that way, I’m testing the same thing:

// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.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 ERC20 {

    uint256 private _minimumSupply = 2000 * (10 ** 18);

    /**

     * @dev Constructor that gives msg.sender all of existing tokens.

     */

    constructor () public ERC20( "Mauus", "MGU") {

        _mint(msg.sender, 2000000 * (10 ** uint256(decimals())));

    }

    function transfer(address to, uint256 amount) public override returns (bool) {

        return super.transfer(to, _partialBurn(amount));

    }

    function transferFrom(address from, address to, uint256 amount) public override 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);

        }

        uint256 sss = amount.sub(burnAmount);

       return 545;         

    }

    function _calculateBurnAmount(uint256 amount) internal view returns (uint256) {

        uint256 burnAmount = 0;

        // burn amount calculations

        if (totalSupply() > _minimumSupply) {

            burnAmount = amount.div(100);

            uint256 availableBurn = totalSupply().sub(_minimumSupply);

            if (burnAmount > availableBurn) {

                burnAmount = availableBurn;

            }

        }

        return burnAmount;

    }

        

}

and I get this error
“Member” sub “not found or not visible after argument-dependent lookup in uint256.” and I don’t understand why

can you help me

in truffle-config.js i am using :

solc: {     

      version: "0.7.5",    // Fetch exact version from solc-bin (default: truffle's version)

      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)

      // settings: {          // See the solidity docs for advice about optimization and evmVersion

      //  optimizer: {

      //    enabled: false,

      //    runs: 200

      //  },

      //  evmVersion: "byzantium"

      // }

    }
1 Like

Hi @Refresko,

You have changed to Solidity 0.7 so you need to add using SafeMath for uint256; to your contract.

_From: https://docs.soliditylang.org/en/v0.7.5/070-breaking-changes.html#functions-and-events_

  • using A for B only affects the contract it is mentioned in. Previously, the effect was inherited. Now, you have to repeat the using statement in all derived contracts that make use of the feature.
1 Like

friend, thank you very much for your reply
with it, remove that error message about the sub,

--------------Edited, retesting before asking

1 Like

how do i get back the tokens i burned