How It Works
A TWAP order divides your total trade inton equal parts, each executing at a frequency of t seconds. Each part has a validity window defined by the span parameter.
Data Structure
The TWAP order is defined by the following struct:Parameters
The token to sell in the TWAP order
The token to receive in exchange
The address that will receive the bought tokens
The amount of
sellToken to sell in each individual part of the TWAP. Must be greater than 0.Example: If you want to sell 1000 tokens total in 10 parts, set this to 100.The minimum amount of
buyToken to receive for each part. Acts as a limit price. Must be greater than 0.Example: If each part sells 100 USDC and you want at least 0.05 ETH, set this to 50000000000000000 (0.05 * 10^18).The UNIX timestamp when the TWAP order starts. Set to
0 to use dynamic start time from the context (set when the order is first created).Must be less than type(uint32).max (year 2106).The total number of parts to split the order into. Must be greater than 1 and at most
type(uint32).max.Total trade size = partSellAmount * nThe frequency in seconds between each part. Must be greater than 0 and at most 365 days.Examples:
- 300 = 5 minutes
- 3600 = 1 hour
- 86400 = 1 day
The validity window for each part in seconds. Must be less than or equal to
t.- Set to
0for the part to be valid for the entire frequency period - Set to a smaller value to create a specific validity window
t = 3600 (1 hour) and span = 300 (5 minutes), each part is only valid for the first 5 minutes of its hour.The IPFS hash of the appData associated with the order. Can be used to attach metadata.
Validation Rules
The TWAP order validates the following conditions:sellTokenandbuyTokenmust be different tokens- Both tokens must have non-zero addresses
partSellAmountmust be greater than 0minPartLimitmust be greater than 0t0must be less thantype(uint32).maxnmust be greater than 1 and at mosttype(uint32).maxtmust be greater than 0 and at most 365 daysspanmust be less than or equal tot
Behavior
Part Calculation
The current part is calculated as:validTo timestamp, which ensures a unique orderUid and prevents double execution.
Validity Window
ThevalidTo timestamp for each part is calculated as:
- If
span = 0:validTo = t0 + (part + 1) * t - 1(valid until the next part starts) - If
span > 0:validTo = t0 + part * t + span - 1(valid for the span duration)
Dynamic Start Time
Ift0 is set to 0, the start time is dynamically determined from the ComposableCoW cabinet storage when the order is first queried. This allows the TWAP to start when it’s first activated rather than at a predetermined time.
Error Messages
The current time is before the TWAP start time (
t0). The order will poll again at t0.All parts of the TWAP have completed. The order is no longer valid.
The current time is outside the validity window for the current part.
Example Usage
Example 1: Basic TWAP
Sell 1000 USDC for ETH in 10 parts over 10 hours:Example 2: TWAP with Narrow Validity Window
Sell 5000 DAI for USDC in 20 parts, each valid for only 10 minutes:Implementation Details
Contract Address
The TWAP conditional order type is deployed at/src/types/twap/TWAP.sol.
Key Functions
Each part of a TWAP order generates a unique
orderUid based on its validTo timestamp. This ensures CoW Protocol only executes each part once, even if the order is repeatedly queried.