contract tokenERC20 is  ownerShip
{
    // Public variables of the token
    using SafeMath for uint256;
    bytes32 public name;
    bytes8 public symbol;
    uint8 public decimals; // places of decimal
    uint256 public totalSupply;
    uint256 public totalMintAfterInitial;
    uint256 public maximumSupply;

    uint public burningRate = 500;    // 500=5%

    // struct to store token and ether value 
    struct userBalance 
    {
        uint256 totalValue;
        uint256 freezeValue;
        uint256 freezeDate;
        uint256 meltValue;    
    }

    // Mapped storage for token  ( If token address is 0 means ether)
    mapping (address => mapping (address => userBalance)) public tokens;


        // This creates an array with all balances
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;
    
    /* Records for the fronzen accounts */
    mapping (address => bool) public frozenAccount;
        
    /* This generates a public event on the blockchain that will notify clients */
    event FrozenFunds(address target, bool frozen);
    
    // This generates a public event on the blockchain that will notify clients
    event Transfer(address indexed from, address indexed to, uint256 value);
  
    
    // This notifies clients about the amount burnt
    event Burn(address indexed from, uint256 value);

     //Calculate percent and return result
    function calculatePercentage(uint256 PercentOf, uint256 percentTo ) internal pure returns (uint256) 
    {
        uint256 factor = 10000;
        require(percentTo <= factor);
        uint256 c = PercentOf.mul(percentTo).div(factor);
        return c;
    }   

    function setBurningRate(uint _burningRate) onlyOwner public returns(bool success)
    {
        burningRate = _burningRate;
        return true;
    }



    //Token type defnition
    struct tokenTypeData
    {
        bytes32 tokenName;
        bytes8 tokenSymbol;
        uint decimalCount;
        uint minFreezingValue;
        uint rateFactor;      // % of token balance amount = "effective balance amount" to calculate interest
        uint perDayFreezeRate;   //1000 = 10% ,10 = 0.1%, 1 = 0.01%
        bool freezingAllowed;   // If false this token type is not allowed or accepted to freeze
    }
    // Mapped storage struct for token type  data
    mapping (address => tokenTypeData) public tokenTypeDatas;


        /**
         * Constrctor function
         *
         * Initializes contract with initial supply tokens to the creator of the contract
         */
    constructor () public {
    	decimals = 18; // 18 decimal places
        totalSupply = 50000000000000000000000000;       // 50 Million with 18 decimal places
        maximumSupply = 100000000000000000000000000;         // 100 Million with 18 decimal places
        balanceOf[msg.sender]=totalSupply;       // tokens will be sent to owner
        tokens[address(this)][owner].totalValue = balanceOf[msg.sender];
        name = "HYPE Token";                           // Set the name for display purposes
        symbol = "HYPE";                       // Set the symbol for display purposes

        //In house token type data update
        tokenTypeData memory temp;

        temp.tokenName=name;
        temp.tokenSymbol=symbol;
        temp.decimalCount=decimals;
        temp.minFreezingValue=100;
        temp.rateFactor=10000;   //10000 = 100% means token amount = effective amount   
        temp.perDayFreezeRate=100;   // 1% daily freezing reward
        temp.freezingAllowed=true;  
        tokenTypeDatas[address(this)] = temp;
        emit Transfer(address(0), msg.sender, totalSupply);
    }
    
         /* Internal transfer, only can be called by this contract */
        function _transfer(address _from, address _to, uint _value) internal {
            require(!safeGuard,"safeGuard Active");
			require (_to != address(0),"to is address 0");                               // Prevent transfer to 0x0 address. Use burn() instead
			require (balanceOf[_from] >= _value, "no balance in from");               // Check if the sender has enough
			require (balanceOf[_to].add(_value) >= balanceOf[_to],"overflow balance"); // Check for overflows
			require(!frozenAccount[_from],"from account frozen");                     // Check if sender is frozen
			require(!frozenAccount[_to],"to account frozen");                       // Check if recipient is frozen
			balanceOf[_from] = balanceOf[_from].sub(_value);    // Subtract from the sender
            tokens[address(this)][_from].totalValue = tokens[address(this)][_from].totalValue.sub(_value); //parallel record for multi token addressing need
			balanceOf[_to] = balanceOf[_to].add(_value);        // Add the same to the recipient
            tokens[address(this)][_to].totalValue = tokens[address(this)][_to].totalValue.add(_value);   //parallel record for multi token addressing need         
            uint burnValue;
            if(!(msg.sender == owner || msg.sender == address(this)))   // burn if sender is not this contract or owner
            {
                burnValue = calculatePercentage(_value,burningRate); //amount to burn
                require(burnInternal(_to, burnValue),"burning failed");   // burnt from receiver
            }
			emit Transfer(_from, _to,_value);
            
        } 

        function burnInternal(address _burnFrom, uint _burnValue) internal returns(bool success)
        {   
            require(!safeGuard,"safeGuard Active");
            require(_burnFrom != address(0));
            require(balanceOf[_burnFrom] >= _burnValue);   // Check if the sender has enough
			require(!frozenAccount[_burnFrom],"to account frozen");                       // Check if recipient is frozen
			balanceOf[_burnFrom] = balanceOf[_burnFrom].sub(_burnValue);    // Subtract from the sender
            tokens[address(this)][_burnFrom].totalValue = tokens[address(this)][_burnFrom].totalValue.sub(_burnValue); //parallel record for multi token addressing need
			balanceOf[address(0)] = balanceOf[address(0)].add(_burnValue);        // Add the same to the recipient
            tokens[address(this)][address(0)].totalValue = tokens[address(this)][address(0)].totalValue.add(_burnValue);   //parallel record for multi token addressing need         
            totalSupply = totalSupply.sub(_burnValue);            
			emit Transfer(_burnFrom, address(0),_burnValue);                         // Update totalSupply
            return true;            
        }

		function mintInternal(uint256 mintedAmount)  internal returns (bool success) {                         
			totalSupply = totalSupply.add(mintedAmount);
            totalMintAfterInitial = totalMintAfterInitial.add(mintedAmount);
		 	//emit Transfer(address(0), address(this), mintedAmount);
            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 returns (bool success) {
         _transfer(msg.sender, _to, _value);
        return true;
    }
    
        /**
         * Transfer tokens from other address
         *
         * Send `_value` tokens to `_to` in 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, uint256 _value) public returns (bool success) {
        require(!safeGuard);
        require(_from != address(0),"transfer from adderss(0) is invalid");
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value);
        _transfer(_from, _to, _value);
        return true;
    }
    
        /**
         * Set allowance for other address
         *
         * Allows `_spender` to spend no more than `_value` tokens in your behalf
         *
         * @param _spender The address authorized to spend
         * @param _value the max amount they can spend
         */
    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        require(!safeGuard);
        allowance[msg.sender][_spender] = _value;
        return true;
    }

        
		/// @notice Create `mintedAmount` tokens and send it to `target`
		/// @param target Address to receive the tokens
		/// @param mintedAmount the amount of tokens it will receive
		function mintToken(address target, uint256 mintedAmount)  public onlyOwner returns (bool success) {
			balanceOf[target] = balanceOf[target].add(mintedAmount);
            tokens[address(this)][target].totalValue = tokens[address(this)][target].totalValue.add(mintedAmount); //parallel record for multi token addressing need                         
			totalSupply = totalSupply.add(mintedAmount);
            totalMintAfterInitial = totalMintAfterInitial.add(mintedAmount);
		 	emit Transfer(address(0), address(this), mintedAmount);
            return true;
		}


        /**
         * Destroy tokens
         *
         * Remove `_value` tokens from the system irreversibly
         *
         * @param _value the amount of money to burn
         */
    function burn(uint256 _value) public onlyOwner returns (bool success) {
        burnInternal(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 onlyOwner returns (bool success) {
        burnInternal(_from, _value);
        return true;
    }
        
}
function approve(address _spender, uint256 _value) public
    returns (bool success) {
    require(!safeGuard);
    allowance[msg.sender][_spender] = _value;
    return true;
}

/**
 * Set allowance for other address
 *
 * Allows `_spender` to spend no more than `_value` tokens in your behalf
 *
 * @param _spender The address authorized to spend
 * @param _value the max amount they can spend
 */