Skip to main content

Custom Orders

Custom orders leverage the IConditionalOrder or IConditionalOrderGenerator interface to enable sophisticated trading strategies based on on-chain conditions. The framework recommends extending BaseConditionalOrder for most implementations, as it handles signature verification automatically.

Key Interfaces

  • IConditionalOrder provides the foundational verification method
  • IConditionalOrderGenerator extends this by adding order generation capabilities on-chain
The verify function checks discrete order validity, while getTradeableOrder produces executable orders for the CoW Protocol API.

BaseConditionalOrder Advantages

This abstract contract streamlines development by automating:
  • Order hash verification
  • ERC165 interface support
Developers focus solely on implementing the order generation logic through the getTradeableOrder function, which must return a valid GPv2Order.Data struct.

Implementation Examples

TradeAboveThreshold

Executes when an owner’s token balance exceeds a specified threshold, selling the entire balance.

PerpetualStableSwap

Automatically rebalances between two tokens based on relative holdings, applying a configurable spread.

Error Communication

Specialized revert errors guide watchtowers on retry behavior:
ErrorBehavior
PollTryNextBlockTemporary condition, retry soon
PollTryAtBlock / PollTryAtEpochOrder valid at specific time
PollNeverPermanent invalidity, stop monitoring
OrderNotValidGeneric failure condition

Advanced Features

  • Context-based cabinet storage for persistent values
  • offchainInput parameters for dynamic watchtower-provided data
  • Validity bucketing prevents hash collisions across sequential queries

Best Practices

  • Maintain gas efficiency in getTradeableOrder
  • Ensure deterministic logic within validity buckets
  • Employ clear error messaging
  • Implement proper ERC165 interface support
All revert paths must use recognized custom errors.If getTradeableOrder (or getTradeableOrderWithSignature) reverts with bytes that the Watch Tower cannot decode to a known error (OrderNotValid, PollTryNextBlock, PollTryAtBlock, PollTryAtEpoch), the Watch Tower permanently stops polling your order with no notification to the order creator.This means arithmetic overflows, failed external calls, and bare revert() statements will silently kill your order’s polling. Wrap your handler logic in a try/catch and always revert with OrderNotValid(reason) as a fallback for any unexpected failure. See Troubleshooting — Order stopped being polled for debugging steps.

Security Considerations

  • Validate external calls
  • Manage arithmetic carefully — unhandled overflows will cause the Watch Tower to permanently drop your order
  • Address reentrancy risks

Watch Tower Integration

Custom handlers are automatically discovered and executed by the Watch Tower. When a programmatic order is created via ComposableCoW, the Watch Tower:
  1. Detects the ConditionalOrderCreated event on-chain
  2. Polls your handler’s getTradeableOrder() on every block (or per your error hints)
  3. Submits the resulting discrete order to the CoW Protocol OrderBook when conditions are met
You do not need to register your handler in the SDK registry — the Watch Tower falls back to direct contract calls for any handler not in the built-in registry. Your handler just needs to be deployed and have an order created via ComposableCoW.create() or ComposableCoW.createWithContext().
Test your handler on Sepolia first. The Watch Tower supports Sepolia and will poll your handler the same way it does on mainnet. See Watch Tower Configuration for Sepolia setup.
Last modified on March 12, 2026