function availableVolume(address tokenBuy, uint amountBuy, address tokenSell, uint amountSell, uint expires, uint nonce, address user, uint8 v, bytes32 r, bytes32 s) public view returns(uint) {
        bytes32 hash = keccak256(abi.encodePacked(this, tokenBuy, amountBuy, tokenSell, amountSell, expires, nonce, user));
        if (!(
            (orders[user][hash] || ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)),v,r,s) == user) &&
            block.timestamp <= expires
        )) return 0;
        uint available1 = safeSub(amountBuy, orderFills[user][hash]);
        uint available2 = safeMul(tokens[tokenSell][user], amountBuy) / amountSell;
        if (available1<available2) return available1;
        return available2;
    }