// Contract: EthPro
// Target function: function name() override public view returns (string memory)
/**
*
*  ███████╗████████╗██╗  ██╗    ██████╗ ██████╗  ██████╗ 
*  ██╔════╝╚══██╔══╝██║  ██║    ██╔══██╗██╔══██╗██╔═══██╗
*  █████╗     ██║   ███████║    ██████╔╝██████╔╝██║   ██║
*  ██╔══╝     ██║   ██╔══██║    ██╔═══╝ ██╔══██╗██║   ██║
*  ███████╗   ██║   ██║  ██║    ██║     ██║  ██║╚██████╔╝
*  ╚══════╝   ╚═╝   ╚═╝  ╚═╝    ╚═╝     ╚═╝  ╚═╝ ╚═════╝ 
*
* 
* ETH PRO
* https://eth-pro.github.io/
* or
* https://eth-pro.netlify.app/
* 
**/


pragma solidity ^0.6.7;

/**
    Utilities & Common Modifiers
*/

contract GreaterThanZero {
    // verifies that an amount is greater than zero
    modifier greaterThanZero(uint256 _amount) {
        require(_amount > 0);
        _;
    }
}

contract ValidAddress {
    // validates an address - currently only checks that it isn't null
    modifier validAddress(address _address) {
        require(_address != address(0));
        _;
    }
}

contract OnlyPayloadSize {
	//Mitigate short address attack and compatible padding problem while using “call“ 
	modifier onlyPayloadSize(uint256 numCount){
		assert((msg.data.length == numCount*32 + 4) || (msg.data.length == (numCount + 1)*32));
		_;
	}
}

contract NotThis {
    // verifies that the address is different than this contract address
    modifier notThis(address _address) {
        require(_address != address(this));
        _;
    }
}

contract SafeMath {
    // Overflow protected math functions

    /**
        @dev returns the sum of _x and _y, asserts if the calculation overflows

        @param _x   value 1
        @param _y   value 2

        @return sum
    */
    function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) {
        uint256 z = _x + _y;
        require(z >= _x);        //assert(z >= _x);
        return z;
    }

    /**
        @dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number

        @param _x   minuend
        @param _y   subtrahend

        @return difference
    */
    function safeSub(uint256 _x, uint256 _y) internal pure returns (uint256) {
        require(_x >= _y);        //assert(_x >= _y);
        return _x - _y;
    }

    /**
        @dev returns the product of multiplying _x by _y, asserts if the calculation overflows

        @param _x   factor 1
        @param _y   factor 2

        @return product
    */
    function safeMul(uint256 _x, uint256 _y) internal pure returns (uint256) {
        uint256 z = _x * _y;
        require(_x == 0 || z / _x == _y);        //assert(_x == 0 || z / _x == _y);
        return z;
    }
	
	function safeDiv(uint256 _x, uint256 _y)internal pure returns (uint256){
	    // assert(b > 0); // Solidity automatically throws when dividing by 0
        // uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return _x / _y;
	}
	
	function ceilDiv(uint256 _x, uint256 _y)internal pure returns (uint256){
		return (_x + _y - 1) / _y;
	}
}


contract Sqrt {
	function sqrt(uint x)public pure returns(uint y) {
        uint z = (x + 1) / 2;
        y = x;
        while (z < y) {
            y = z;
            z = (x / z + z) / 2;
        }
    }
}


contract Floor {
	/**
        @dev Returns the largest integer smaller than or equal to _x.
        @param _x   number _x
        @return     value
    */
	function floor(uint _x)public pure returns(uint){
		return (_x / 1 ether) * 1 ether;
	}
}

contract Ceil {
	/**
        @dev Returns the smallest integer larger than or equal to _x.
        @param _x   number _x
        @return ret    value ret
    */
	function ceil(uint _x)public pure returns(uint ret){
		ret = (_x / 1 ether) * 1 ether;
		if((_x % 1 ether) == 0){
			return ret;
		}else{
			return ret + 1 ether;
		}
	}
}
	
contract IsContract {
	//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
    function isContract(address _addr) internal view returns (bool is_contract) {
        uint length;
        assembly {
              //retrieve the size of the code on target address, this needs assembly
              length := extcodesize(_addr)
        }
        return (length>0);
    }
}
    
contract LogEvent {
    // todo: for debug
    event logEvent(string name, uint256 value);
}


/**
    ERC20 Standard Token interface
*/
interface IERC20Token {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address _holder) external view returns (uint256);
    function allowance(address _holder, address _spender) external view returns (uint256);

    function transfer(address _to, uint256 _amount) external returns (bool success);
    function transferFrom(address _from, address _to, uint256 _amount) external returns (bool success);
    function approve(address _spender, uint256 _amount) external returns (bool success);
    
    event Transfer(address indexed _from, address indexed _to, uint256 _amount);
    event Approval(address indexed _holder, address indexed _spender, uint256 _amount);
}


/**
    ERC20 Standard Token implementation
*/
contract ERC20Token is IERC20Token, SafeMath, ValidAddress {
    string  internal/*public*/ m_name = '';
    string  internal/*public*/ m_symbol = '';
    uint8   internal/*public*/ m_decimals = 0;
    uint256 internal/*public*/ m_totalSupply = 0;
    mapping (address => uint256) internal/*public*/ m_balanceOf;
    mapping (address => mapping (address => uint256)) internal/*public*/ m_allowance;

    event Transfer(address indexed _from, address indexed _to, uint256 _amount);
    event Approval(address indexed _holder, address indexed _spender, uint256 _amount);