function fillOrder(
          address[3] orderAddresses,
          uint[4] orderValues,
          uint8 v,
          bytes32 r,
          bytes32 s)
          public
          payable
    {

        Order memory order = Order({
            maker: orderAddresses[0],
            taker: orderAddresses[1],
            contractAddr: orderAddresses[2],
            nftTokenId: orderValues[0],
            tokenAmount : orderValues[1],
            expirationTimestampInSec: orderValues[2],
            orderHash: getOrderHash(orderAddresses, orderValues)
        });


        if (msg.value < order.tokenAmount) {
            LogError(uint8(Errors.INSUFFICIENT_BALANCE_OR_ALLOWANCE), order.orderHash);
            return ;
        }


        require(msg.value >= order.tokenAmount);
        require(order.taker == address(0) || order.taker == msg.sender);


        require(order.tokenAmount > 0 );
        require(isValidSignature(
            order.maker,
            order.orderHash,
            v,
            r,
            s
        ));

        if (block.timestamp >= order.expirationTimestampInSec) {
            LogError(uint8(Errors.ORDER_EXPIRED), order.orderHash);
            return ;
        }


        require( transferViaProxy ( order.contractAddr , order.maker,msg.sender , order.nftTokenId )  );

        uint256 transCut = _computeCut(order.tokenAmount);
        order.maker.transfer(order.tokenAmount - transCut);
        uint256 bidExcess = msg.value - order.tokenAmount;
        
        msg.sender.transfer(bidExcess);
        LogFill(order.maker,msg.sender,order.contractAddr,order.nftTokenId,order.tokenAmount, keccak256(order.contractAddr),order.orderHash );
    }