> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cow.bleu.builders/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common issues when setting up ComposableCoW programmatic orders and how to diagnose and fix them.

# Troubleshooting

This guide covers the most common issues developers hit when setting up ComposableCoW, based on frequent questions in the CoW Protocol Discord.

## Setup issues

### `setDomainVerifier` transaction reverts

The most common setup error. The call to `setDomainVerifier` must be made **from the Safe to itself** — not to the ExtensibleFallbackHandler.

<Warning>
  `setDomainVerifier` is a function on the **ExtensibleFallbackHandler**, but it must be called via the Safe's `execTransaction`. The Safe calls itself, and the fallback handler intercepts the call.
</Warning>

**Correct flow:**

1. Safe executes a transaction where `to` = **the Safe's own address**
2. The call data encodes `setDomainVerifier(domainSeparator, composableCowAddress)`
3. The ExtensibleFallbackHandler (set as the Safe's fallback handler) processes it

**Wrong:** Calling `setDomainVerifier` directly on the ExtensibleFallbackHandler address — this will revert or have no effect.

### Correct setup sequence

The setup must happen in this exact order:

1. **Set the fallback handler** on the Safe to ExtensibleFallbackHandler (`0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5`)
2. **Register ComposableCoW as domain verifier** by calling `setDomainVerifier` from the Safe to itself
3. **Create programmatic orders** via `ComposableCoW.create()`

If step 1 is not done before step 2, the `setDomainVerifier` call will silently fail (no fallback handler to intercept it).

### Verifying setup is correct

Check both configurations on-chain:

**1. Verify fallback handler:**

```bash theme={null}
# Read the Safe's fallback handler slot
cast storage <SAFE_ADDRESS> \
  0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5
```

Expected: `0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5` (ExtensibleFallbackHandler)

**2. Verify domain verifier:**

```bash theme={null}
# Call domainVerifiers on the Safe (via fallback handler)
cast call <SAFE_ADDRESS> \
  "domainVerifiers(address,bytes32)(address)" \
  <SAFE_ADDRESS> \
  <DOMAIN_SEPARATOR>
```

Expected: `0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74` (ComposableCoW)

The domain separator for CoW Protocol is chain-specific. You can read it from the settlement contract:

```bash theme={null}
cast call 0x9008D19f58AAbD9eD0D60971565AA8510560ab41 "domainSeparator()(bytes32)"
```

### MultiSend atomic setup

To do both steps atomically in a single Safe transaction:

```solidity theme={null}
// Transaction 1: Set fallback handler
to: <SAFE_ADDRESS>
data: setFallbackHandler(0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5)

// Transaction 2: Register domain verifier (Safe calls itself)
to: <SAFE_ADDRESS>
data: setDomainVerifier(<DOMAIN_SEPARATOR>, 0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74)
```

Bundle via Safe's MultiSend contract.

## Order not appearing in explorer

After creating a programmatic order, it should appear in [CoW Explorer](https://explorer.cow.fi). If it doesn't:

### 1. Check if the watch-tower picked it up

The [watch-tower](/watch-tower/introduction) monitors `ConditionalOrderCreated` events. If it hasn't indexed your order:

* **Was the transaction confirmed?** Check the tx hash on the block explorer
* **Did the event fire?** Look for `ConditionalOrderCreated` in the transaction logs
* **Is the watch-tower running for your chain?** The public watch-tower covers Ethereum, Gnosis Chain, Arbitrum One, Base, Polygon, Avalanche, BNB Chain, Linea, Plasma, Ink, and Sepolia
* **Is there a delay?** The watch-tower processes blocks periodically — wait a few minutes

### 2. Check if the order is currently valid

The watch-tower calls `getTradeableOrder()` on your handler. If it reverts, the order won't be posted. Common reasons:

* **Balance insufficient** — the Safe doesn't hold enough sell tokens
* **Time condition not met** — for TWAP, the current part hasn't started yet
* **Guard rejection** — a swap guard is blocking the order

### 3. Run your own watch-tower for debugging

```bash theme={null}
# Clone and run with debug logging, monitoring only your Safe
git clone https://github.com/cowprotocol/watch-tower
cd watch-tower
yarn install

LOG_LEVEL=DEBUG yarn cli run \
  --config-path ./config.json \
  --only-owner <YOUR_SAFE_ADDRESS> \
  --one-shot
```

The `--one-shot` flag processes once and exits. `--dry-run` shows what orders would be posted without actually posting them.

## Foundry / Forge dependency issues

When installing ComposableCoW with Forge, Safe library dependencies may not resolve automatically.

### Missing `SignatureVerifierMuxer.sol`

```bash theme={null}
forge install cowprotocol/composable-cow
```

If this fails to resolve Safe dependencies, add the remappings manually:

```toml theme={null}
# foundry.toml or remappings.txt
[profile.default]
remappings = [
    "composable-cow/=lib/composable-cow/src/",
    "safe/=lib/composable-cow/lib/safe-contracts/contracts/",
    "safe-contracts/=lib/composable-cow/lib/safe-contracts/contracts/",
]
```

You may also need to install the Safe contracts explicitly:

```bash theme={null}
cd lib/composable-cow
forge install safe-global/safe-contracts --no-commit
```

## Order stopped being polled unexpectedly

If your programmatic order was being polled by the Watch Tower but silently stopped without being cancelled or fulfilled, the most likely cause is an **unrecognized revert error** from your handler contract.

### Root cause

When the Watch Tower calls `getTradeableOrderWithSignature` on your handler and the call reverts, it attempts to decode the revert data against a set of known custom errors:

* `OrderNotValid(string)`
* `PollTryNextBlock`
* `PollTryAtBlock(uint256)`
* `PollTryAtEpoch(uint256, uint256)`
* `PollNever(string)`

If the revert bytes do not match any of these, the Watch Tower classifies the result as `UNEXPECTED_ERROR` and **permanently stops polling the order**. There is no notification to the order creator.

### Common triggers

* **Arithmetic overflow/underflow** — Solidity 0.8+ reverts with a `Panic(uint256)` error code, which the Watch Tower does not recognize as a polling hint
* **Failed external calls** — If your handler calls another contract that reverts with its own custom error, those bytes propagate up and won't match the known set
* **Generic `revert()` or `require(false)`** — These produce empty or non-standard revert data
* **Out-of-gas in sub-calls** — Can produce unexpected revert behavior

### Debugging steps

1. **Reproduce the revert locally.** Call `getTradeableOrderWithSignature` with the same parameters the Watch Tower uses (owner, params, offchainInput, proof) using `cast call` or a Foundry test:
   ```bash theme={null}
   cast call <COMPOSABLE_COW> \
     "getTradeableOrderWithSignature(address,(address,bytes32,bytes),bytes,bytes32[])" \
     <OWNER> "(handler,salt,staticInput)" "0x" "[]" \
     --rpc-url <RPC_URL>
   ```

2. **Inspect the revert data.** If the call fails, check the raw revert bytes. Compare the first 4 bytes (the error selector) against the known selectors:
   * `OrderNotValid`: `0x16f2d3f3`
   * `PollTryNextBlock`: `0x44882c68`
   * `PollTryAtBlock`: `0x2d6e06d5`
   * `PollTryAtEpoch`: `0x4184e129`

3. **Check for arithmetic edge cases.** Review your handler for divisions that could hit zero denominators, multiplications that could overflow, or timestamp arithmetic that could underflow.

4. **Run a local Watch Tower** with `--one-shot --only-owner <YOUR_SAFE>` and `LOG_LEVEL=DEBUG` to see the exact error classification.

### Best practice: defensive error handling

Wrap your handler's core logic in a try/catch so that any unexpected failure maps to a recognized error:

```solidity theme={null}
function getTradeableOrder(
    address owner,
    address sender,
    bytes32 ctx,
    bytes calldata staticInput,
    bytes calldata offchainInput
) external view override returns (GPv2Order.Data memory order) {
    try this._getTradeableOrder(owner, sender, ctx, staticInput, offchainInput)
        returns (GPv2Order.Data memory result)
    {
        return result;
    } catch Error(string memory reason) {
        // Solidity require() / revert(string) — surface as OrderNotValid
        revert IConditionalOrder.OrderNotValid(reason);
    } catch (bytes memory) {
        // Panic, custom error from sub-call, or any other revert
        revert IConditionalOrder.OrderNotValid("unexpected internal error");
    }
}
```

This ensures the Watch Tower always receives a recognized error and continues polling the order on subsequent blocks.

<Warning>
  This is a critical pattern for any custom handler. Without it, a single unexpected revert permanently removes your order from the Watch Tower's polling cycle with no notification. See [Watch Tower Polling — On-chain errors](/watch-tower/concepts/polling#on-chain-errors) for full details.
</Warning>

## Salt and replay protection

Each programmatic order needs a unique salt. If you reuse a salt for the same handler + parameters + Safe, the order will be a duplicate.

* Use `keccak256(abi.encodePacked(block.timestamp, nonce))` or similar for unique salts
* The salt is used to compute the order's storage key in ComposableCoW
* Cancelling an order frees its salt for reuse

## Contract addresses (all chains)

| Contract                  | Address                                      |
| ------------------------- | -------------------------------------------- |
| ComposableCoW             | `0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74` |
| ExtensibleFallbackHandler | `0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5` |
| GPv2Settlement            | `0x9008D19f58AAbD9eD0D60971565AA8510560ab41` |

These addresses are the same on Ethereum, Gnosis Chain, Arbitrum One, Base, Polygon, Avalanche, BNB Chain, Linea, Plasma, Ink, and Sepolia.

## Related resources

* **[Setup Guide](/composable-cow/guides/setup)** — Initial configuration walkthrough
* **[Architecture](/composable-cow/architecture)** — How the system works
* **[Watch Tower](/watch-tower/introduction)** — The service that monitors and posts programmatic orders
* **[Debugging Programmatic Orders](/composable-cow/guides/debugging)** — Decision tree for "why didn't my order execute?"
