Skip to main content

Overview

To use ComposableCoW, your Safe wallet must be configured with the ExtensibleFallbackHandler and set ComposableCoW as the domain verifier for CoW Protocol’s settlement domain.
ComposableCoW requires the ExtensibleFallbackHandler to enable EIP-1271 signature verification for conditional orders. This setup only needs to be done once per Safe.

Prerequisites

Before setting up ComposableCoW, ensure you have:
  • A deployed Safe wallet
  • Access to execute transactions on the Safe (threshold signers)
  • The deployed contract addresses for your network

Deployed Contracts

ComposableCoW and ExtensibleFallbackHandler are deployed at the same addresses across multiple networks:
ContractAddress
ExtensibleFallbackHandler0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5
ComposableCoW0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74
TWAP0x6cF1e9cA41f7611dEf408122793c358a3d11E5a5
GoodAfterTime0xdaf33924925e03c9cc3a10d434016d6cfad0add5
StopLoss0x412c36e5011cd2517016d243a2dfb37f73a242e7
These addresses are consistent across Ethereum Mainnet, Gnosis Chain, Arbitrum, Base, Optimism, Polygon, and other supported networks.

Setup Steps

1

Set the Fallback Handler

Configure your Safe to use the ExtensibleFallbackHandler:
// From within a Safe transaction
safe.setFallbackHandler(0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5);
This allows your Safe to use extensible signature verification for different domains.
2

Set ComposableCoW as Domain Verifier

Register ComposableCoW as the signature verifier for the CoW Protocol settlement domain:
ExtensibleFallbackHandler handler = ExtensibleFallbackHandler(fallbackHandler);

// Get CoW Protocol's domain separator from settlement contract
bytes32 domainSeparator = settlement.domainSeparator();

// Set ComposableCoW as the verifier for this domain
handler.setDomainVerifier(
    domainSeparator,
    0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74
);
This tells the Safe to use ComposableCoW for verifying CoW Protocol order signatures.
3

Verify Configuration

Confirm the setup is correct:
// Check fallback handler
address currentHandler = abi.decode(
    safe.getStorageAt(
        uint256(keccak256("fallback_manager.handler.address")),
        1
    ),
    (address)
);
require(currentHandler == 0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5);

// Check domain verifier
address verifier = ExtensibleFallbackHandler(currentHandler)
    .domainVerifiers(safe, settlement.domainSeparator());
require(verifier == 0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74);

Complete Setup Example

Here’s a complete example using Safe’s execTransaction to batch both setup steps:
import {Safe} from "safe/Safe.sol";
import {Enum} from "safe/common/Enum.sol";
import {ExtensibleFallbackHandler} from "safe/handler/ExtensibleFallbackHandler.sol";
import {ComposableCoW} from "composable-cow/ComposableCoW.sol";

contract SafeSetup {
    Safe public safe;
    ExtensibleFallbackHandler public constant HANDLER = 
        ExtensibleFallbackHandler(0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5);
    ComposableCoW public constant COMPOSABLE_COW = 
        ComposableCoW(0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74);
    
    function setupSafeForComposableCoW(
        address settlement
    ) external {
        // Step 1: Set fallback handler
        safe.execTransaction(
            address(safe),
            0,
            abi.encodeWithSelector(
                Safe.setFallbackHandler.selector,
                address(HANDLER)
            ),
            Enum.Operation.Call,
            0, 0, 0, address(0), payable(0),
            signatures
        );
        
        // Step 2: Set domain verifier
        bytes32 domainSeparator = CoWSettlement(settlement).domainSeparator();
        
        safe.execTransaction(
            address(safe),
            0,
            abi.encodeWithSelector(
                ExtensibleFallbackHandler.setDomainVerifier.selector,
                domainSeparator,
                address(COMPOSABLE_COW)
            ),
            Enum.Operation.Call,
            0, 0, 0, address(0), payable(0),
            signatures
        );
    }
}

Using MultiSend for Atomic Setup

You can combine both operations into a single transaction using Safe’s MultiSend library:
import {MultiSend} from "safe/libraries/MultiSend.sol";

function atomicSetup(address settlement) external {
    bytes memory transactions = abi.encodePacked(
        // Transaction 1: setFallbackHandler
        uint8(Enum.Operation.Call),
        address(safe),
        uint256(0),
        uint256(setFallbackHandlerData.length),
        setFallbackHandlerData,
        
        // Transaction 2: setDomainVerifier  
        uint8(Enum.Operation.Call),
        address(safe),
        uint256(0),
        uint256(setDomainVerifierData.length),
        setDomainVerifierData
    );
    
    safe.execTransaction(
        address(multiSend),
        0,
        abi.encodeWithSelector(
            MultiSend.multiSend.selector,
            transactions
        ),
        Enum.Operation.DelegateCall,
        0, 0, 0, address(0), payable(0),
        signatures
    );
}
Always verify contract addresses for your specific network. While the addresses are deterministic across networks, always confirm them before use.

Next Steps

Once your Safe is configured:
  1. Create conditional orders to start trading
  2. Learn about managing orders lifecycle
  3. Explore merkle root batching for gas efficiency

Common Issues

Fallback Handler Not Set

If you encounter signature verification failures, ensure the fallback handler is properly set:
address handler = abi.decode(
    safe.getStorageAt(
        uint256(keccak256("fallback_manager.handler.address")),
        1
    ),
    (address)
);

if (handler == address(0)) {
    revert("Fallback handler not set");
}

Wrong Domain Verifier

Verify the correct domain separator is being used:
bytes32 domainSeparator = settlement.domainSeparator();
address verifier = handler.domainVerifiers(address(safe), domainSeparator);

require(
    verifier == address(composableCow),
    "ComposableCoW not set as domain verifier"
);

Build docs developers (and LLMs) love