function trade(uint amount, uint[3] order, bytes32 r, bytes32 s, uint8 v) external {
        Order memory o = parseOrder(order);

        if (!validateOrderParams(o)) {
            LogTradeError(msg.sender, o.addr, o.matchId, o.orderHash, uint16(Status.ORDER_MALFORMED));
            return;
        }

        if (!validateOrderSig(o, r, s, v)) {
            LogTradeError(msg.sender, o.addr, o.matchId, o.orderHash, uint16(Status.ORDER_BAD_SIG));
            return;
        }

        Trade memory t = tradeCore(amount, o);

        if (t.status != Status.OK) {
            LogTradeError(msg.sender, o.addr, o.matchId, o.orderHash, uint16(t.status));
            return;
        }

        

        var m = matches[o.matchId];

        if (m.firstTradeTimestamp == 0) {
            assert(block.timestamp > 0);
            m.firstTradeTimestamp = uint64(block.timestamp);
        }

        m.positions[t.longAddr] = t.newLongPosition;
        m.positions[t.shortAddr] = t.newShortPosition;

        adjustBalance(t.longAddr, t.longBalanceDelta);
        adjustBalance(t.shortAddr, t.shortBalanceDelta);

        filledAmounts[o.orderHash] += (o.direction == 0 ? t.shortAmount : t.longAmount);

        LogTrade(msg.sender, o.addr, o.matchId, o.orderHash, o.direction, o.price, t.longAmount, t.newLongPosition, t.shortAmount, t.newShortPosition);
    }