contract IPUXtoken is owned, TokenERC20 {
        

        /*********************************/
        /* Code for the ERC20 IPUX Token */
        /*********************************/
    
        /* Public variables of the token */
        string private tokenName = "IPUX Token";
        string private tokenSymbol = "IPUX";
        uint256 private initialSupply = 1000000000;  //1 Billion
        
        
        
        /* 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);
    
        /* Initializes contract with initial supply tokens to the creator of the contract */
        constructor (address icoContractAddress) TokenERC20(initialSupply, tokenName, tokenSymbol, icoContractAddress) public {
            
        }

        /* Internal transfer, only can be called by this contract */
        function _transfer(address _from, address _to, uint _value) internal {
            require(!safeguard);
            require (_to != address(0x0));                      // Prevent transfer to 0x0 address. Use burn() instead
            require (balanceOf[_from] >= _value);               // Check if the sender has enough
            require (balanceOf[_to].add(_value) >= balanceOf[_to]); // Check for overflows
            require(!frozenAccount[_from]);                     // Check if sender is frozen
            require(!frozenAccount[_to]);                       // Check if recipient is frozen
            balanceOf[_from] = balanceOf[_from].sub(_value);    // Subtract from the sender
            balanceOf[_to] = balanceOf[_to].add(_value);        // Add the same to the recipient
            emit Transfer(_from, _to, _value);
        }
        
        /// @notice `freeze? Prevent | Allow` `target` from sending & receiving tokens
        /// @param target Address to be frozen
        /// @param freeze either to freeze it or not
        function freezeAccount(address target, bool freeze) onlyOwner public {
                frozenAccount[target] = freeze;
            emit  FrozenFunds(target, freeze);
        }
        
        /// @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) onlyOwner public {
            balanceOf[target] = balanceOf[target].add(mintedAmount);
            totalSupply = totalSupply.add(mintedAmount);
            emit Transfer(address(0), target, mintedAmount);
        }

          
        //Just in rare case, owner wants to transfer Ether from contract to owner address
        function manualWithdrawEther()onlyOwner public{
            address(owner).transfer(address(this).balance);
        }
        
        function manualWithdrawTokens(uint256 tokenAmount) public onlyOwner{
            // no need for overflow checking as that will be done in transfer function
            _transfer(address(this), owner, tokenAmount);
        }
        
        //selfdestruct function. just in case owner decided to destruct this contract.
        function destructContract()onlyOwner public{
            selfdestruct(owner);
        }
        
        /**
         * Change safeguard status on or off
         *
         * When safeguard is true, then all the non-owner functions will stop working.
         * When safeguard is false, then all the functions will resume working back again!
         */
        function changeSafeguardStatus() onlyOwner public{
            if (safeguard == false){
                safeguard = true;
            }
            else{
                safeguard = false;    
            }
        }
        
        /********************************/
        /*    Code for the Air drop     */
        /********************************/
        
        /**
         * Run an Air-Drop
         *
         * It requires an array of all the addresses and amount of tokens to distribute
         * It will only process first 150 recipients. That limit is fixed to prevent gas limit
         */
        function airdrop(address[] memory recipients,uint tokenAmount) public onlyOwner {
            uint256 addressCount = recipients.length;
            require(addressCount <= 150);
            for(uint i = 0; i < addressCount; i++)
            {
                  //This will loop through all the recipients and send them the specified tokens
                  _transfer(address(this), recipients[i], tokenAmount);
            }
        }

}
//****************************************************************************//
//---------------------  IPUX MAIN CODE STARTS HERE ---------------------//
//****************************************************************************//
function _transfer(address _from, address _to, uint _value) internal {
    require(!safeguard);
    require (_to != address(0x0));                      // Prevent transfer to 0x0 address. Use burn() instead
    require (balanceOf[_from] >= _value);               // Check if the sender has enough
    require (balanceOf[_to].add(_value) >= balanceOf[_to]); // Check for overflows
    require(!frozenAccount[_from]);                     // Check if sender is frozen
    require(!frozenAccount[_to]);                       // Check if recipient is frozen
    balanceOf[_from] = balanceOf[_from].sub(_value);    // Subtract from the sender
    balanceOf[_to] = balanceOf[_to].add(_value);        // Add the same to the recipient
    emit Transfer(_from, _to, _value);
}

/* Internal transfer, only can be called by this contract */