contract COPi is ERC20Burnable, ERC20Mintable, ERC20Pausable, ERC20Detailed, TransferFee {
    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    constructor(uint256 _initialAmount) 
        ERC20Detailed("COPi", "COPi", 18)
    public {
        _mint(msg.sender, _initialAmount.mul(10 ** uint256(decimals())));
    }

    function transfer(address to, uint256 value) public whenNotPaused returns (bool) {
        uint256 fee = calculateFee (msg.sender, to, value);
        _transfer (msg.sender, to, value);
        _transfer (msg.sender, _feeCollector, fee);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) public whenNotPaused 
    returns (bool success) {
        uint256 fee = calculateFee (msg.sender, to, value);
        uint256 allowance = allowance (from, msg.sender);

        // _approve is called to decrease approval, if not enough SafeMath will stop execution
        _transfer (from, to, value);
        _transfer (from, _feeCollector, fee);
        _approve(from, msg.sender, allowance.sub(value).sub(fee));
        return true;
    }

    // ------------------------------------------------------------------------
    // Allows any ERC20 tokens accidentially sent to this contract's address 
    // to be transferred out
    // ------------------------------------------------------------------------
    function claimERC20(address tokenAddress, address to, uint256 amount) public onlyOwner returns (bool _success) {
        return 
            IERC20(tokenAddress).transfer(
                to,
                amount > 0 ? amount : 
                    IERC20(tokenAddress).balanceOf(address(this))
            );
    }

    function claimETH(address payable to, uint256 amount) public onlyOwner returns (bool _success) {
        return to.send(amount);
    }
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
function claimERC20(address tokenAddress, address to, uint256 amount) public onlyOwner returns (bool _success) {
    return 
        IERC20(tokenAddress).transfer(
            to,
            amount > 0 ? amount : 
                IERC20(tokenAddress).balanceOf(address(this))
        );
}

// ------------------------------------------------------------------------
// Allows any ERC20 tokens accidentially sent to this contract's address 
// to be transferred out
// ------------------------------------------------------------------------