Turn on deflationary functionality after a specific transaction

Moved from: Unable to deploy and verify ERC20 token with burn and stop burn feature

@abcoathup is there anyway for burn to start after a certain amount of TX? I want burn to start after I add to liquidity pool on uniswap

1 Like

Hi @anon,

Welcome to the community :wave:

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

You could add functionality to automatically use deflationary functionality after a specific block number (e.g. check the block number is passed a specific block).

Alternatively you could turn it on manually by calling a function to set a value.

so you had posted this code
what would you do to execute either of those options
im kinda new to smart contracts

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.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, ERC20Detailed {

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

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
    constructor () public ERC20Detailed("MyToken", "MYT", 18) {
        _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;
    }
}
1 Like

did you edit the post, i dont understand what happened.
sorry, im new to this site

1 Like

also one more question
is there a function to set burn to start after a certain amount of time. for example. 1 hour after contract deploys?

Hi @anon,

When creating a token I recommend reading Points to consider when creating a fungible token (ERC20, ERC777)

I would suggest using the latest version of OpenZeppelin Contracts v3.2.

A good way to quickly experiment is to use Remix. We can convert imports of npm packages to imports via GitHub.

The following code has a hardcoded boolean for enabling deflation. Instead of checking this hardcoded boolean you could have a check against block.timestamp, and set _deflationStart in the constructor for example:

_deflationStart < block.timestamp

Alternatively you could have a function that enables deflation (protected with AccessControl).

Repeating the warning for any future community members coming across this code:
:warning: A deflationary token can cause problems such as this issue: https://medium.com/balancer-protocol/incident-with-non-standard-erc20-deflationary-tokens-95a0f6d46dea

SimpleToken.sol

:warning: The following code has not been tested or audited and should not be used in production.

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

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/token/ERC20/ERC20.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.
 *
 * The following code has not been tested or audited and should not be used in production.
 *
 * Deflationary tokens can cause problems.
 */
contract MyToken is ERC20 {

    uint256 private _minimumSupply = 2000 * (10 ** 18);
    bool _deflationEnabled = true;

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

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

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

        return burnAmount;
    }
}

I edited your post to get syntax highlighting for your contract by wrapping it in ```

```
contract MyContract {
}
```

so would i add a burner role to accessControl?

Would i be able to instead exclude the owner from setting off burn function ?

1 Like

Hi @anon,

If you were to add functionality to turn on (or even off) deflationary functionality (rather than have it turn on at a specific block), then you could create a DeflationRole.

As an example, you can look at the PauserRole and pausing and unpausing token transfers in this preset ERC20: