TIP-1003: Client Order IDs
Status: Draft
Authors: Dan Robinson
Authors: Dan Robinson
Abstract
This TIP adds support for optional client order IDs (clientOrderId) to the Stablecoin DEX. Users can specify a uint128 identifier when placing orders, which serves as an idempotency key and a predictable handle for the order. The system-generated orderId is not predictable before transaction execution, making client order IDs useful for order management.
Motivation
Traditional exchanges allow users to specify a client order ID (calledClOrdID in FIX protocol, cloid in Hyperliquid) for several reasons:
- Idempotency: If a transaction is submitted twice (e.g., due to network issues), the duplicate can be detected and rejected
- Predictable reference: Users know the order identifier before the transaction confirms, enabling them to prepare cancel requests or track orders without waiting for confirmation
- Integration: External systems can use their own ID schemes to correlate orders
Specification
New Storage
A new mapping tracks active client order IDs per user:Modified Functions
All order placement functions gain an optionalclientOrderId parameter:
New Functions
Behavior
Placing Orders with clientOrderId
WhenclientOrderId is non-zero:
- Check if
clientOrderIds[msg.sender][clientOrderId]maps to an active order - If it does, revert with
DUPLICATE_CLIENT_ORDER_ID - Otherwise, proceed with order placement and set
clientOrderIds[msg.sender][clientOrderId] = orderId
clientOrderId is zero, no client order ID tracking occurs.
Uniqueness and Reuse
AclientOrderId must be unique among a user’s active orders. Once an order is filled or cancelled, its clientOrderId can be reused. This matches the standard FIX protocol behavior where ClOrdID uniqueness is required only for working orders.
When an order reaches a terminal state (filled or cancelled), the clientOrderIds mapping entry is cleared.
Flip Orders
When a flip order is filled and creates a new order on the opposite side:- The new (flipped) order inherits the original order’s
clientOrderId - The
clientOrderIdsmapping is updated to point to the new order ID - This allows users to track their position across flips using a single
clientOrderId
clientOrderId (was zero), the flipped order also has no clientOrderId.
Cancellation
cancelByClientOrderId(clientOrderId) looks up clientOrderIds[msg.sender][clientOrderId] and cancels that order. It reverts if no active order exists for that clientOrderId.
New Event
OrderPlacedV2 is identical to OrderPlaced but adds the clientOrderId field. When an order is placed, only OrderPlacedV2 is emitted (not both events).
New Errors
Invariants
- A non-zero
clientOrderIdmaps to at most one active order per user clientOrderIds[user][clientOrderId]is cleared when the order is filled or cancelled- Flip orders inherit
clientOrderIdand update the mapping atomically clientOrderId = 0is reserved to mean “no client order ID”