Signature Construction
ComposableCoW orders use EIP-1271 (smart contract) signatures rather than EOA signatures. This guide explains how to construct the signature bytes that the settlement contract needs to verify your programmatic order.This guide assumes you have already set up your Safe with the ExtensibleFallbackHandler and ComposableCoW as domain verifier, and created a programmatic order via
create() or createWithContext().How signature verification works
When the CoW Protocol settlement contract executes a trade for a ComposableCoW order, the following verification chain runs:ConditionalOrderParams and any offchain input, then uses these to regenerate the expected order and verify it matches.
Signature encoding
The signature for a ComposableCoW order is an ABI-encoded byte string containing two values:| Component | Type | Description |
|---|---|---|
params | ConditionalOrderParams | The handler address, salt, and staticInput used when creating the order |
offchainInput | bytes | Any additional off-chain data the handler needs (empty bytes if none) |
ConditionalOrderParams struct consists of:
| Field | Type | Description |
|---|---|---|
handler | address | The programmatic order handler contract (e.g., TWAP at 0x6cF1e9cA41f7611dEf408122793c358a3d11E5a5) |
salt | bytes32 | Unique identifier for this order |
staticInput | bytes | ABI-encoded parameters specific to the handler |
Step-by-step construction
Use the exact same
handler, salt, and staticInput values that you passed to ComposableCoW.create() or createWithContext() when you created the order.The params must match exactly. Even a single byte difference in
staticInput produces a different order hash, and ComposableCoW will reject the signature because the order was never authorized.Determine whether your handler requires offchain input. Most standard handlers (TWAP, StopLoss) use empty bytes (
0x). Custom handlers may require additional data that is not stored on-chain but is needed to generate the tradeable order.If your handler’s
getTradeableOrder() function uses the offchainInput parameter, you must provide the expected value. Otherwise, pass empty bytes.When submitting the order to the CoW Protocol Order Book API, set the
signingScheme field to eip1271:The
from field must be the address of the Safe that owns the programmatic order, not any EOA signer of the Safe.Full example
Putting it all together, here is a complete example of constructing and submitting a ComposableCoW order signature:Common pitfalls
| Pitfall | Symptom | Fix |
|---|---|---|
Wrong signingScheme | API rejects the order or signature verification fails | Set signingScheme to eip1271, not eip712 or ethsign |
Wrong from address | isValidSignature is called on the wrong contract | Use the Safe address, not an EOA signer address |
Mismatched ConditionalOrderParams | ComposableCoW cannot find the order in singleOrders mapping | Ensure handler, salt, and staticInput exactly match what was passed to create() |
| Handler returns unexpected order | Order digest mismatch during verification | Verify the handler’s getTradeableOrder() output matches the order you are submitting |
| Missing offchain input | Handler reverts when generating the tradeable order | Provide the offchain data your handler expects, or empty bytes if none |
| Safe not configured | isValidSignature reverts or returns wrong value | Ensure ExtensibleFallbackHandler is set and ComposableCoW is registered as domain verifier (Setup guide) |
Verifying locally
Before submitting to the API, you can verify your signature will pass validation by calling theisValidSignature function directly on the Safe:
This call simulates the exact check the settlement contract performs during order execution. If it returns the magic value (
0x1626ba7e), your signature will be accepted.Next steps
- Creating orders — learn how to create the programmatic order on-chain
- Managing orders — revoke or update existing orders
- Signing schemes — understand all CoW Protocol signing methods
- Troubleshooting — debug common issues