Skip to main content

Conditional Orders

Conditional orders are programmable orders that execute automatically when predefined conditions are met. They are a key component of the CoW Protocol’s programmatic order framework, enabling sophisticated trading strategies without manual intervention.

What are Conditional Orders?

Conditional orders allow traders to define complex order logic that executes based on specific blockchain conditions such as price thresholds, time intervals, or custom smart contract logic. Unlike traditional orders that are immediately placed, conditional orders are monitored by the Watch Tower and only posted to the OrderBook when their conditions are satisfied.
Conditional orders are created through the ComposableCoW contract, which emits events that the Watch Tower monitors.

Order Structure

Each conditional order contains the following components:
type ConditionalOrder = {
  /**
   * Id of the conditional order (which also happens to be the key used for `ctx` in the ComposableCoW contract).
   *
   * This is a `keccak256` hash of the serialized conditional order.
   */
  id: string;

  /**
   * The transaction hash that created the conditional order (useful for debugging purposes)
   */
  tx: string;

  /**
   * The parameters of the conditional order
   */
  params: ConditionalOrderParams;

  /**
   * The merkle proof if the conditional order is belonging to a merkle root
   * otherwise, if the conditional order is a single order, this is null
   */
  proof: Proof | null;

  /**
   * Map of discrete order hashes to their status
   */
  orders: Map<OrderUid, OrderStatus>;

  /**
   * the address to poll for orders (may, or **may not** be `ComposableCoW`)
   */
  composableCow: string;

  /**
   * The result of the last poll
   */
  pollResult?: {
    lastExecutionTimestamp: number;
    blockNumber: number;
    result: PollResult;
  };
};

Order Parameters

The ConditionalOrderParams contain the core logic:
  • handler: The smart contract address that implements the conditional order logic
  • salt: A unique identifier to distinguish orders with identical parameters
  • staticInput: Immutable data passed to the handler for order evaluation

Merkle Proofs

Conditional orders can be created individually or as part of a merkle tree:
type Proof = {
  merkleRoot: BytesLike;
  path: BytesLike[];
};
Merkle trees allow efficient batch creation of multiple conditional orders in a single transaction, reducing gas costs.

Order Lifecycle

Conditional orders follow a specific lifecycle from creation to completion:
  1. Creation: An order is created via the ComposableCoW contract, which emits either a ConditionalOrderCreated event (single order) or MerkleRootSet event (batch orders)
  2. Registration: The Watch Tower detects the event and adds the order to its registry, tracking it by owner
  3. Polling: On each block, the Watch Tower polls the conditional order to check if conditions are met
  4. Execution: When conditions are satisfied, the Watch Tower posts the discrete order to the CoW Protocol OrderBook API
  5. Tracking: The order is tracked with status updates (SUBMITTED or FILLED)
  6. Cleanup: Expired or cancelled orders are removed from the registry

Order Status

Each discrete order generated from a conditional order has a status:
enum OrderStatus {
  SUBMITTED = 1,
  FILLED = 2,
}

How They Work in ComposableCoW

The ComposableCoW contract provides the framework for creating and managing conditional orders:
  • Handler registration: Custom order types register handler contracts that implement specific order logic
  • Event emission: The contract emits events when orders are created or modified
  • Order validation: Handlers validate whether order conditions are met when polled
  • Signature generation: Valid orders return order details and signatures for submission
The Watch Tower calls the getTradeableOrderWithSignature function on the ComposableCoW contract to check if an order should be placed.

Order Identification

Each conditional order has a unique ID generated by hashing its parameters:
const conditionalOrderId = ConditionalOrder.leafToId(params);
This ID is used throughout the system to track the order’s state and poll results.
Last modified on March 4, 2026