Overview
Solver engines are pure route-finding and optimization services:Responsibilities
- Route Finding: Determine optimal paths through available liquidity
- Order Matching: Identify coincidence of wants between orders
- Price Discovery: Compute uniform clearing prices
- Gas Optimization: Balance execution cost vs quality
- Constraint Satisfaction: Respect order limits, balances, and partial fill rules
Not Responsible For
- Calldata encoding
- Transaction simulation
- Settlement submission
- Liquidity collection
- On-chain interactions
Solver Types
Internal Solvers
Provided by CoW Protocol:- Baseline: Simple greedy solver for basic matching and routing
- Balancer: Specialized for Balancer pool routing
- Legacy solvers: Various historical implementations
External Solvers
Third-party optimization services:- 1inch: Aggregator API integration
- 0x: RFQ and aggregator integration
- ParaSwap: Multi-source aggregation
- Custom: Proprietary algorithms from solver teams
API Specification
Solve Auction
POST /solve
Request Body
Opaque auction identifier (null for non-auction requests like quotes)
Mapping of token addresses to token information
Array of CoW Protocol orders to solve
Array of available on-chain liquidity sources
Current gas price in Wei for scoring
ISO 8601 UTC timestamp by which solution must be returned
Addresses whose JIT order surplus counts toward score
Token Information
Order Structure
Liquidity Sources
See Driver API - Liquidity Collection for detailed liquidity source structures. Types include:constantProduct: Uniswap V2 style poolsweightedProduct: Balancer weighted poolsstable: Curve stable poolsconcentratedLiquidity: Uniswap V3 style poolslimitOrder: External (0x) limit orders
Response
Array of proposed solutions (can be empty if no viable solution found)
Solution Structure
Trade Types
Interaction Types
Example Response:200: Solutions computed (may be empty array if no solution found)400: Invalid request429: Solver too busy500: Internal error
Receive Notification
POST /notify
Request Body
Auction ID for which notification applies
Solution ID within the auction
Notification type
Notification Kinds
Status Codes:200: Notification received
Solution Requirements
Constraint Satisfaction
-
Order Limits:
- Sell orders:
executedSell ≤ sellAmount - Buy orders:
executedBuy ≥ buyAmount
- Sell orders:
-
Partial Fills:
- If
partiallyFillable == false: Must fill completely or not at all - If
partiallyFillable == true: Can fill any amount within limits
- If
-
Uniform Clearing Prices:
- All trades use same price vector
- Prices must satisfy all order limit prices
-
Token Conservation:
- Total tokens in = total tokens out (per token)
- Account for fees, surplus, and slippage
-
Gas Efficiency:
- Reasonable gas estimate
- Balance quality vs cost
Optimization Objectives
Primary: Maximize objective value:- User Surplus: Difference between clearing price and limit price for each order
- Protocol Fees: Sum of fees collected per fee policies
- Gas Cost: Estimated gas × gas price × native token price
- Maximize filled volume
- Minimize slippage
- Optimize gas usage
Fee Policy Application
Solver engines must apply protocol fee policies when computing solutions:Surplus Fee
factor × surplus, capped at maxVolumeFactor × volume.
Example:
- Order: Sell 1000 DAI, limit price 1 DAI = 0.001 ETH
- Execution: Receive 1.2 ETH for 1000 DAI (clearing price: 1 DAI = 0.0012 ETH)
- Surplus: (0.0012 - 0.001) × 1000 = 0.2 ETH
- Fee: min(0.5 × 0.2, 0.05 × 1000 × 0.0012) = min(0.1, 0.06) = 0.06 ETH
Volume Fee
factor × executed volume.
Example:
- Order: Sell 1000 DAI
- Execution: 1000 DAI at 0.0012 ETH per DAI
- Fee: 0.002 × 1000 × 0.0012 = 0.0024 ETH
Price Improvement Fee
factor × improvement over quote, capped at maxVolumeFactor × volume.
Baseline Solver Algorithm
The baseline solver provides a reference implementation:Algorithm Outline
-
Order Matching: Check for direct coincidence of wants
- If sell(A→B) and sell(B→A) exist, match them directly
-
Single Order Routing: For each unmatched order:
- Find best path through available liquidity
- Consider gas costs
- Apply fee policies
-
Price Computation: Compute uniform clearing prices
- Use marginal rates from executed liquidity
- Ensure all order limits satisfied
- Gas Estimation: Sum gas costs for all interactions
- Score Calculation: Compute objective value
Limitations
- Greedy approach (no global optimization)
- Handles one or two orders well
- Struggles with complex multi-order scenarios
- Doesn’t explore all possible routings
Advanced Solver Techniques
Batch Optimization
- Consider all orders simultaneously
- Find global optimum across order set
- More computationally expensive
AMM Rebalancing
- Use CoW orders to rebalance AMM pools
- Arbitrage between liquidity sources
- Improve overall liquidity efficiency
Ring Trades
- Create cycles: A→B→C→A
- Extract value from price differences
- Can improve surplus for all participants
JIT Liquidity
- Inject just-in-time orders to improve prices
- Requires careful surplus accounting
- Can bridge liquidity gaps
Smart Order Routing
- Split orders across multiple paths
- Reduce price impact
- Consider gas costs vs quality tradeoff
Testing Solvers
Unit Tests
- Constraint Validation: Verify all order limits respected
- Price Consistency: Check uniform clearing prices
- Token Conservation: Ensure balanced token flows
- Fee Application: Validate fee policy calculations
- Gas Estimates: Compare estimated vs actual gas
Integration Tests
- Driver Integration: Test with reference driver
- Liquidity Sources: Use real pool data
- Historical Auctions: Replay past auctions
- Performance: Measure solve time vs auction deadline
Benchmarking
- Compare scores against other solvers
- Measure win rate on historical data
- Track gas efficiency
- Monitor response times
Best Practices
- Respect Deadlines: Always respond before deadline
- Validate Input: Check for malformed auction data
- Handle Edge Cases: Empty orders, zero amounts, etc.
- Accurate Gas Estimates: Critical for correct scoring
- Apply Fee Policies Correctly: Misapplied fees lead to invalid solutions
- Consider Partial Fills: Don’t ignore partially fillable orders
- Optimize Incrementally: Start simple, add complexity gradually
- Log Decisions: Track why certain paths were chosen
- Monitor Performance: Identify bottlenecks in optimization
- Test Thoroughly: Validate constraints before returning solutions
Resources
- CIP-2: Internalization
- CIP-20: Solution Scoring
- CIP-67: Fair Combinatorial Auctions
- Baseline Solver Source
Example: Simple Sell Order Solution
Input Auction:- Fulfills the order completely (not partially fillable)
- Routes through the Uniswap V2 pool
- Returns ~0.997 WETH for 1000 DAI
- Exceeds the buy amount limit of 0.9 WETH
- Generates surplus that can be partially captured as protocol fee
