contract ERC20 is IERC20 {
    using MathOverflowGuard for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * Requirements:
     *
     * - 'recipient' cannot be the zero address.
     * - the caller must have a balance of at least 'amount'.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

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

    /**
     * Requirements:
     *
     * - 'spender' cannot be the zero address.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * 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 'value'.
     * - the caller must have allowance for 'sender''s tokens of at least 'amount'.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * This is an alternative to 'approve' that can be used as a mitigation for
     * problems described in 'IERC20.approve'.
     *
     * Emits an 'Approval' event indicating the updated allowance.
     *
     * Requirements:
     *
     * - 'spender' cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * Atomically decreases the allowance granted to 'spender' by the caller.
     *
     * This is an alternative to 'approve' that can be used as a mitigation for
     * problems described in 'IERC20.approve'.
     *
     * Emits an 'Approval' event indicating the updated allowance.
     *
     * Requirements:
     *
     * - 'spender' cannot be the zero address.
     * - 'spender' must have allowance for the caller of at least
     * 'subtractedValue'.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * Moves tokens 'amount' from 'sender' to 'recipient'.
     *
     * This is internal function is equivalent to 'transfer', and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a 'Transfer' event.
     *
     * Requirements:
     *
     * - 'sender' cannot be the zero address.
     * - 'recipient' cannot be the zero address.
     * - 'sender' must have a balance of at least 'amount'.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /**
     * Creates 'amount' tokens and assigns them to 'account', increasing
     * the total supply.
     *
     * Emits a 'Transfer' event with 'from' set to the zero address.
     *
     * Requirements
     *
     * - 'to' cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * Destoys 'amount' tokens from 'account', reducing the
     * total supply.
     *
     * Emits a 'Transfer' event with 'to' set to the zero address.
     *
     * Requirements
     *
     * - 'account' cannot be the zero address.
     * - 'account' must have at least 'amount' tokens.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * Sets 'amount' as the allowance of 'spender' over the 'owner's tokens.
     *
     * This is internal function is equivalent to 'approve', and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an 'Approval' event.
     *
     * Requirements:
     *
     * - 'owner' cannot be the zero address.
     * - 'spender' cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * Destoys 'amount' tokens from 'account'.'amount' is then deducted
     * from the caller's allowance.
     *
     * See '_burn' and '_approve'.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}
/**
 * Implementation of the 'IERC20' interface.
 *
 * Base code from (https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
 *
 */
function transfer(address recipient, uint256 amount) public returns (bool) {
    _transfer(msg.sender, recipient, amount);
    return true;
}

/**
 * Requirements:
 *
 * - 'recipient' cannot be the zero address.
 * - the caller must have a balance of at least 'amount'.
 */