contract BasicERC223 is BlackList,ERC223Interface {
    
    using safeMath for uint;
    uint8 public basisPointsRate;
    uint public minimumFee;
    uint public maximumFee;
    address[] holders;
    
    mapping(address => uint) internal balances;
    
    event Transfer(address from, address to, uint256 value, bytes data, uint256 fee);
    
    /**
    * @dev Function that is called when a user or another contract wants to transfer funds.
    * @param _address address of contract.
    * @return true is _address was contract address.
    */
    function isContract(address _address) internal view returns (bool is_contract) {
        uint length;
        require(_address != address(0));
        assembly {
            length := extcodesize(_address)
        }
        return (length > 0);
    }
    
    /**
    * @dev function that is called by transfer method to calculate Fee.
    * @param _amount Amount of tokens.
    * @return fee calculate from _amount.
    */
    function calculateFee(uint _amount) internal view returns(uint fee){
        fee = (_amount.mul(basisPointsRate)).div(1000);
        if (fee > maximumFee) fee = maximumFee;
        if (fee < minimumFee) fee = minimumFee;
    }
    
    /**
    * @dev function that is called when transaction target is a contract.
    * @return true if transferToContract execute successfully.
    */
    function transferToContract(address _to, uint _value, bytes memory _data) internal returns (bool success) {
        require(_value > 0 && balances[msg.sender]>=_value);
        require(_to != msg.sender && _to != address(0));
        uint fee = calculateFee(_value);
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value.sub(fee));
        if (fee > 0) {
            balances[owner] = balances[owner].add(fee);
        }
        ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
        receiver.tokenFallback(msg.sender, _value, _data);
        emit Transfer(msg.sender, _to, _value);
        emit Transfer(msg.sender, _to, _value,  _data, fee);
        holderIsExist(_to);
        return true;
    }
    
    /**
    * @dev function that is called when transaction target is a external Address.
    * @return true if transferToAddress execute successfully.
    */
    function transferToAddress(address _to, uint _value, bytes memory _data) internal returns (bool success) {
        require(_value > 0 && balances[msg.sender]>=_value);
        require(_to != msg.sender && _to != address(0));
        uint fee = calculateFee(_value);
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value.sub(fee));
        if (fee > 0) {
            balances[owner] = balances[owner].add(fee);
        }
        emit Transfer(msg.sender, _to, _value);
        emit Transfer(msg.sender, _to, _value,  _data, fee);
        holderIsExist(_to);
        return true;
    }
    
    /**
    * @dev Check for existing holder address if not then add it .
    * @param _holder The address to check it already exist or not.
    * @return true if holderIsExist execute successfully.
    */
    function holderIsExist(address _holder) internal returns (bool success){
        for(uint i=0;i<holders.length;i++)
            if(_holder==holders[i])
                success=true;
        if(!success) holders.push(_holder);
    }
    
    /**
    * @dev Get all holders of Contract.
    * @return array of holder address.
    */
    function holder() public onlyOwner view returns(address[] memory){
        return holders;
    }
}
/**
 * @title BasicERC223
 * @dev standard ERC223 contract
 */
function transferToAddress(address _to, uint _value, bytes memory _data) internal returns (bool success) {
    require(_value > 0 && balances[msg.sender]>=_value);
    require(_to != msg.sender && _to != address(0));
    uint fee = calculateFee(_value);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value.sub(fee));
    if (fee > 0) {
        balances[owner] = balances[owner].add(fee);
    }
    emit Transfer(msg.sender, _to, _value);
    emit Transfer(msg.sender, _to, _value,  _data, fee);
    holderIsExist(_to);
    return true;
}

/**
 * @dev function that is called when transaction target is a external Address.
 * @return true if transferToAddress execute successfully.
 */