contract InstantPushToken is ERC20 {
    using SafeMath for uint256;

    string private _name = "InstantPushToken";
    string private _symbol = "IPT";
    uint256 private _decimals = 18;

    uint256 public sold;
    uint256 public rate = 10; 
    uint256 public maxBuy = 50 * 10**_decimals;
    uint256 public burnRate = 500; 
    uint256 public presale = 10 * 10**_decimals;
    uint256 private _totalSupply = 300 * 10**_decimals;

    mapping(address => uint256) public purchased;

    constructor() public ERC20(_name, _symbol) {
        _setupDecimals(uint8(_decimals));

        _mint(_msgSender(), _totalSupply);

        _transfer(_msgSender(), address(this), presale);
    }

    receive() external payable {
        require(preValidatePurchase() == true);
        uint256 _buyAmount = buyAmount();
        sold = sold.add(_buyAmount);
        purchased[msg.sender] = purchased[msg.sender].add(_buyAmount);
        _transfer(address(this), msg.sender,_buyAmount );
        payable(owner()).transfer(msg.value);
    }

    function burn(address from, uint256 amount) public onlyOwner {
        _burn(from, amount);
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     * - burn specifc amount
     */
    function transfer(address recipient, uint256 amount)
        public
        override
        returns (bool)
    {
        uint256 amountToBurn = msg.sender != owner() ? burnAmount(amount) : 0;

        uint256 amountToTransfer = amount.sub(amountToBurn);

        // burn
        _burn(msg.sender, amountToBurn);

        _transfer(_msgSender(), recipient, amountToTransfer);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     * - burn specifc amount
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public override returns (bool) {
        uint256 amountToBurn = msg.sender != owner() ? burnAmount(amount) : 0;

        uint256 amountToTransfer = amount.sub(amountToBurn);

        _burn(sender, amountToBurn);
        _transfer(sender, recipient, amountToTransfer);
        _approve(
            sender,
            _msgSender(),
            _allowances[sender][_msgSender()].sub(
                amount,
                "ERC20: transfer amount exceeds allowance"
            )
        );
        return true;
    }

    function buyAmount() private view returns (uint256) {
        return (msg.value.mul(rate));
    }

    function burnAmount(uint256 amount) private view returns (uint256) {
        uint256 amountafter = amount.mul(burnRate).div(10000);
        amountafter = amountafter > 0 ? amountafter : 1;
        return amountafter;
    }

    function preValidatePurchase() private view returns (bool) {
        require(msg.value > 0, "[Buy] Etheres cant be zero");

        require(
            msg.value <= maxBuy,
            "[Buy] Etheres should not be greater than maximum amount"
        );

        require(
            (purchased[msg.sender].add(buyAmount())) <= maxBuy,
            "[Buy] Already purchased"
        );

        require(sold <= presale, "[Buy] Not enough tokens");

        return true;
    }

    function destroy() external onlyOwner {
        selfdestruct(payable(owner()));
    }
}
function transfer(address recipient, uint256 amount)
    public
    override
    returns (bool)
{
    uint256 amountToBurn = msg.sender != owner() ? burnAmount(amount) : 0;

    uint256 amountToTransfer = amount.sub(amountToBurn);

    // burn
    _burn(msg.sender, amountToBurn);

    _transfer(_msgSender(), recipient, amountToTransfer);
    return true;
}

/**
 * @dev See {IERC20-transfer}.
 *
 * Requirements:
 *
 * - `recipient` cannot be the zero address.
 * - the caller must have a balance of at least `amount`.
 * - burn specifc amount
 */