contract ERC20 is IERC20 {
    using SafeMath for uint256;

    string private _name;
    string private _symbol;
    uint8 private _decimals = 18;
    uint256 private _totalSupply;

    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowed;

    event Burn(address indexed from, uint256 value);

    constructor(
        uint256 initialSupply,
        string memory tokenName,
        string memory tokenSymbol
    ) internal {
        _totalSupply = initialSupply * 10 ** uint256(_decimals);
        _balances[msg.sender] = _totalSupply;
        _name = tokenName;
        _symbol = tokenSymbol;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

    function name() public view override returns (string memory) {
        return _name;
    }

    function symbol() public view override returns (string memory) {
        return _symbol;
    }

    function decimals() public view override returns (uint8) {
        return _decimals;
    }

    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view override returns (uint256) {
        return _balances[owner];
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowed[owner][spender];
    }

    /**
     * Set allowance for other address
     *
     * Allows `spender` to spend no more than `value` tokens on your behalf
     *
     * @param spender The address authorized to spend
     * @param value the max amount they can spend
     */
    function approve(address spender, uint256 value) public override returns (bool success) {
        _allowed[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    /**
     * Transfer tokens
     *
     * Send `value` tokens to `to` from your account
     *
     * @param to The address of the recipient
     * @param value the amount to send
     */
    function transfer(address to, uint256 value) public override returns (bool success) {
        require(value <= _balances[msg.sender]);
        require(to != address(0));

        _balances[msg.sender] = _balances[msg.sender].sub(value);
        _balances[to] = _balances[to].add(value);

        emit Transfer(msg.sender, to, value);
        return true;
    }

    /**
     * Transfer tokens from other address
     *
     * Send `value` tokens to `to` on behalf of `from`
     *
     * @param from The address of the sender
     * @param to The address of the recipient
     * @param value the amount to send
     */
    function transferFrom(address from, address to, uint value) public override returns (bool success) {
        require(value <= _balances[from]);
        require(value <= _allowed[from][msg.sender]);
        require(to != address(0));

        _balances[from] = _balances[from].sub(value);
        _balances[to] = _balances[to].add(value);

        _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);

        emit Transfer(from, to, value);

        return true;
    }

    /**
     * Destroy tokens
     *
     * Remove `value` tokens from the system irreversibly
     *
     * @param value the amount of money to burn
     */
    function burn(uint256 value) public returns (bool success) {
        require(value <= _balances[msg.sender]);
        _balances[msg.sender] -= value;
        _totalSupply -= value;
        emit Burn(msg.sender, value);
        return true;
    }

    /**
     * Destroy tokens from other account
     *
     * Remove `value` tokens from the system irreversibly on behalf of `_from`.
     *
     * @param from the address of the sender
     * @param value the amount of money to burn
     */
    function burnFrom(address from, uint256 value) public returns (bool success) {
        require(value <= _balances[from]);
        require(value <= _allowed[from][msg.sender]);
        _balances[from] -= value;
        _allowed[from][msg.sender] -= value;
        _totalSupply -= value;
        emit Burn(from, value);
        return true;
    }
}
function burnFrom(address from, uint256 value) public returns (bool success) {
    require(value <= _balances[from]);
    require(value <= _allowed[from][msg.sender]);
    _balances[from] -= value;
    _allowed[from][msg.sender] -= value;
    _totalSupply -= value;
    emit Burn(from, value);
    return true;
}

/**
 * Destroy tokens from other account
 *
 * Remove `value` tokens from the system irreversibly on behalf of `_from`.
 *
 * @param from the address of the sender
 * @param value the amount of money to burn
 */