# CoW Protocol Deep Dive: Smart Contract Integration Guide ## Executive Summary CoW Protocol is an **intent-based trading system** that protects users from MEV (Maximal Extractable Value) through batch auctions and competing solvers. Unlike traditional order books, users submit signed intents (not executable transactions) that solvers optimize for best execution. For **MycoFi's community token economies**, this means: - Bonding curve trades can be executed via batch auctions - MEV protection prevents sandwich attacks on token purchases/sales - Solvers compete to offer best prices automatically - Users don't pay gas upfront (solvers pay, deduct from surplus) --- ## 1. Key Contracts & Their Roles ### Core Settlement Infrastructure | Contract | Address | Network | Role | |----------|---------|---------|------| | **GPv2Settlement** | `0x9008D19f58AAbD9eD0D60971565AA8510560ab41` | All (including Base 8453) | Primary settlement contract; executes orders, manages interactions, enforces token transfers | | **GPv2VaultRelayer** | `0xc92e8bdf79f0507f65a392b0ab4667716bfe0110` | All networks | Pulls user tokens from Balancer Vault; **only address authorized to access Vault allowances** | | **GPv2Authenticator** | `0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE` | Ethereum, Base | ERC-1271 signature verification for smart contract orders | | **ComposableCoW** | Varies by network | All | Handler registry for conditional orders; creates/stores order definitions | ### Your Custom Contracts (payment-infra) | Contract | Purpose | Interfaces | |----------|---------|-----------| | **MycoBondingCurve** | Polynomial pricing curve for $MYCO token | ERC20 interaction, price calculation, buy/sell mechanics | | **MycoToken** | Community token with mint/burn controls | ERC20, Burnable | | **BondingCurveAdapter** | Bridge between CoW settlement and bonding curve | Pre-interaction hook for solvers; provides quotes | | **MycoConditionalOrder** | Stateless handler for bonding curve orders | IConditionalOrder (ComposableCoW interface) | ### Architecture Flow ``` User Intent (signed) ↓ ComposableCoW (stores static params) ↓ Watch Tower (polls getTradeableOrder) ↓ Solvers (compete to provide best execution) ↓ GPv2Settlement.settle() (winning solver executes) ├→ Pre-interactions (BondingCurveAdapter executes buy/sell) ├→ VaultRelayer pulls tokens from Vault ├→ Settlement transfers output └→ Post-interactions (optional) ``` --- ## 2. Intent-Based Trading Model ### How Orders Work (Different from Traditional DEX) **Traditional order book:** ``` User creates transaction → Mempool exposed → Bots sandwich → Execute ↓ MEV risk ``` **CoW Protocol (Batch Auction):** ``` User signs intent message (off-chain, private) → Batch accumulates (~30 sec) → Solvers solve together → Single on-chain transaction (solver pays gas) ↓ MEV protected ``` ### Key Differences from Uniswap-style Swaps | Aspect | Traditional AMM | CoW Protocol | |--------|-----------------|-------------| | **Order Type** | Executable transaction | Signed intent message | | **Visibility** | Mempool (public) | Private until batch closure | | **Gas Payment** | User upfront | Solver (deducted from surplus) | | **Price Discovery** | AMM curve | Solver competition | | **Settlement** | Immediate | Batch interval (~30s) | | **MEV Risk** | High (reordering, sandwiching) | Low (uniform clearing prices) | ### The Batch Auction Process 1. **Collection Phase** (0-30 seconds) - Users submit signed intents (off-chain) - Orders accumulate in CoW API orderbook - Private until batch closes 2. **Auction Phase** (at 30-second boundary) - Protocol broadcasts all pending orders - Solvers receive batch and begin solving - Typically <5 seconds to find solution 3. **Solution Phase** - Solvers compute optimal settlement - May involve: - Direct peer-to-peer matching (Coincidence of Wants) - Routing through Uniswap, Curve, other DEXs - Combined strategies for maximum surplus 4. **Execution Phase** - Winning solver submits on-chain transaction - GPv2Settlement.settle() executes atomically - All tokens transferred, fees deducted, user receives output ### Order Intent Structure Users don't create `GPv2Order.Data` directly. Instead, they define **intents** that specify: - Token pair (e.g., USDC ↔ MYCO) - Amount and direction - Minimum acceptable output (slippage protection) - Time window for validity - Execution preferences (partial fill? post-only?) Solvers then create concrete GPv2Order.Data from these intents. --- ## 3. Hooks System: Pre/Post Interaction Hooks ### What Are Hooks? Hooks are **external contract calls** executed at specific points during settlement: ```solidity // Settlement execution phases: settle() ├─ PRE-INTERACTION HOOKS (before token transfers) │ └─ Can execute setup logic, swap prep ├─ Token transfers from VaultRelayer ├─ CUSTOM INTERACTION HOOKS (during settlement) │ └─ Your BondingCurveAdapter.executeBuyForCoW() ├─ Token transfers to user └─ POST-INTERACTION HOOKS (after settlement complete) └─ Can execute cleanup, notifications ``` ### Your Use Case: BondingCurveAdapter as Hook In `/payment-infra/contracts/contracts/cow/BondingCurveAdapter.sol`: ```solidity modifier onlySettlement() { if (msg.sender != settlement) revert OnlySettlement(); _; } function executeBuyForCoW( uint256 usdcAmount, uint256 minMycoOut ) external onlySettlement nonReentrant returns (uint256 mycoOut) { // Settlement calls this during pre-interactions // USDC already transferred by Settlement → Adapter mycoOut = bondingCurve.buy(usdcAmount, minMycoOut); // MYCO minted to Adapter, Settlement pulls it during next phase return mycoOut; } ``` **Token flow:** ``` Settlement receives USDC from user via VaultRelayer ↓ Settlement calls BondingCurveAdapter.executeBuyForCoW(USDC_amount, min_myco) ├─ Adapter.buy() on BondingCurve with USDC └─ BondingCurve mints MYCO to Adapter Settlement registers MYCO balance owed to adapter ↓ Settlement transfers MYCO from Adapter → User ``` ### Hook Types (Coming to ComposableCoW) Soon, handlers can define optional hooks: ```solidity interface IConditionalOrder { struct Hooks { address preHook; // Executed before order starts execution address postHook; // Executed after order completes bytes preHookData; // Encoded params for pre-hook bytes postHookData; // Encoded params for post-hook } } ``` Common hook use cases: - **Pre-hooks**: Approve tokens, verify conditions, signal price feeds - **Post-hooks**: Update position tracking, trigger notifications, execute follow-up actions --- ## 4. Building Custom Order Types: IConditionalOrder Interface ### Core Interface (in your codebase) ```solidity interface IConditionalOrder { error PollTryNextBlock(string reason); // Retry at next block error PollNever(string reason); // Stop polling error OrderNotValid(string reason); // Order invalid function getTradeableOrder( address owner, // Safe wallet address sender, // Usually Watch Tower bytes calldata staticInput, // Your encoded params bytes calldata offchainInput // Watch Tower's live data ) external view returns (GPv2Order.Data memory); function verify( address owner, address sender, bytes32 _hash, bytes32 domainSeparator, bytes calldata staticInput, bytes calldata offchainInput, GPv2Order.Data calldata order ) external view; } ``` ### Your Implementation: MycoConditionalOrder **File:** `/payment-infra/contracts/contracts/cow/MycoConditionalOrder.sol` ```solidity struct OrderData { TradeDirection direction; // BUY or SELL uint256 inputAmount; // USDC (buy) or MYCO (sell) uint256 minOutputAmount; // Slippage floor address receiver; // Order recipient uint256 validityDuration; // Seconds valid } struct OffchainData { uint256 quotedOutput; // From BondingCurveAdapter.quoteBuy/quoteSell uint32 validTo; // Quote expiry } function getTradeableOrder( address owner, address, bytes calldata staticInput, bytes calldata offchainInput ) external view override returns (GPv2Order.Data memory order) { OrderData memory params = abi.decode(staticInput, (OrderData)); OffchainData memory quote = abi.decode(offchainInput, (OffchainData)); // Validate quote freshness and minimums if (block.timestamp > quote.validTo) { revert OrderNotValid("Quote expired"); } if (quote.quotedOutput < params.minOutputAmount) { revert OrderNotValid("Quote below minimum"); } // Generate GPv2Order from params + live quote // Settlement will use this order to execute return GPv2Order.Data({ sellToken: direction == BUY ? usdcToken : mycoTokenAddr, buyToken: direction == BUY ? mycoTokenAddr : usdcToken, receiver: receiver, sellAmount: params.inputAmount, buyAmount: quote.quotedOutput, // From Watch Tower's latest quote validTo: quote.validTo, appData: APP_DATA, feeAmount: 0, kind: GPv2Order.KIND_SELL, // Always KIND_SELL (specify exact input) partiallyFillable: false, // All-or-nothing sellTokenBalance: GPv2Order.BALANCE_ERC20, buyTokenBalance: GPv2Order.BALANCE_ERC20 }); } ``` ### The Watch Tower Integration The **Watch Tower** is CoW Protocol's off-chain service that: 1. **Polls** your `getTradeableOrder()` periodically 2. **Calls** `BondingCurveAdapter.quoteBuy()` / `.quoteSell()` for live quotes 3. **Encodes** quote as `OffchainData` (quotedOutput + validity) 4. **Submits** complete order to solver network Your handler is **stateless** — all logic is in `getTradeableOrder()` called each poll. ### Custom Order Type Examples in Your Repo | File | Type | Purpose | |------|------|---------| | `MycoConditionalOrder.sol` | Basic bonding curve | Buy/sell MYCO with live quotes | | `MycoLimitOrder.sol` | Limit order wrapper | Execute only if price reaches target | | `MycoTWAPOrder.sol` | Time-Weighted Average Price | Split large trades across time | | `MycoDCAOrder.sol` | Dollar-Cost Averaging | Recurring buys at intervals | --- ## 5. MEV Protection Mechanisms ### The Three Pillars of CoW's MEV Protection #### 1. **Private Order Flow** - Your intent **never enters public mempool** - Only visible to authorized solvers and CoW Protocol infrastructure - **Attack prevented:** Mempool monitoring bots can't sandwich you #### 2. **Uniform Clearing Prices (UCP)** - All trades of same pair in batch execute at **same price** - If Alice and Bob both buy MYCO with USDC in same batch: ``` MYCO/USDC = $0.50 (cleared price for this batch) Alice: pay $500 USDC → get 1000 MYCO at $0.50 Bob: pay $300 USDC → get 600 MYCO at $0.50 ``` - **Attack prevented:** Reordering doesn't help attacker; everyone gets same price #### 3. **Coincidence of Wants (CoW)** - Orders matched **peer-to-peer**, not through AMM - Alice wants MYCO, Bob has MYCO → direct transfer - **Attack prevented:** No AMM curve manipulation; prices not affected by MEV order flow ### Why This Matters for MycoFi Bonding Curves **Without CoW Protocol:** ``` User submits bonding curve buy to mempool ↓ MEV bot sees pending tx, inserts "MEV sandwich" ├─ Bot buys MYCO first (pushes price up) ├─ User's tx executes at higher price └─ Bot sells MYCO (profits from price difference) Result: User loses 1-5% due to MEV extraction ``` **With CoW Protocol:** ``` User signs intent (private, off-chain) ↓ Batch collected with other MYCO buyers ↓ Solvers compete (may match directly between users) ├─ If CoW: Alice ↔ Bob swap directly (no AMM) └─ If AMM: Best solver routing wins Result: Uniform clearing price, no sandwich attacks ``` --- ## 6. Deployment Addresses (Base & Other L2s) ### Base (Chain ID: 8453) | Contract | Address | |----------|---------| | **GPv2Settlement** | `0x9008D19f58AAbD9eD0D60971565AA8510560ab41` | | **GPv2VaultRelayer** | `0xc92e8bdf79f0507f65a392b0ab4667716bfe0110` | | **Balancer Vault** | (same as Ethereum) | | **ComposableCoW Handler** | (deploy custom) | | **BondingCurveAdapter** | (deploy custom) | ### Ethereum Mainnet (Chain ID: 1) | Contract | Address | |----------|---------| | **GPv2Settlement** | `0x9008D19f58AAbD9eD0D60971565AA8510560ab41` | | **GPv2VaultRelayer** | `0xc92e8bdf79f0507f65a392b0ab4667716bfe0110` | | **Authenticator** | `0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE` | ### Other L2 Networks - **Arbitrum**, **Optimism**, **Gnosis Chain** — Same GPv2Settlement address (cross-chain deployment) - CoW Protocol designed for **address consistency** across networks ### Deployment Requirements To integrate your bonding curve with CoW on Base: 1. **Deploy MycoBondingCurve** with USDC/MYCO addresses 2. **Deploy BondingCurveAdapter** pointing to: - `_bondingCurve`: Your MycoBondingCurve - `_settlement`: `0x9008D19f...` (GPv2Settlement) - `_usdc`: USDC on Base (typically `0x833589fC4D06F649c466dB920d0135aa6Df1cDEA`) - `_mycoToken`: Your MYCO token 3. **Deploy MycoConditionalOrder** handler 4. **Register in ComposableCoW** with conditional order params --- ## 7. SDK/API for Programmatic Order Submission ### CoW SDK vs. API | Method | Best For | Complexity | |--------|----------|-----------| | **CoW SDK** (`@cowprotocol/sdk`) | Frontend, TypeScript clients | Easy (high-level) | | **REST API** | Backend services, webhooks | Medium (direct HTTP) | | **Conditional Orders** | Automated bots, recurring orders | Complex (Watch Tower integration) | ### Programmatic Submission via SDK ```typescript import { CoWSDK } from "@cowprotocol/sdk"; const sdk = new CoWSDK({ chainId: 8453, // Base signer: ethers.Wallet // User's signer }); // Quote const quote = await sdk.cowApi.getQuote({ sellToken: USDC, buyToken: MYCO, sellAmount: ethers.parseUnits("1000", 6), // 1000 USDC kind: "sell" // Fixed input }); // Submit order const order = await sdk.postSwapOrderFromQuote({ quote: quote, signer: userSigner, receiver: userAddress }); console.log("Order UID:", order.uid); // Wait for execution in next batch (~30s) ``` ### REST API Rate Limits ``` Quote requests: 10 requests/second Order submission: 5 requests/second General endpoints: 100 requests/minute ``` ### API Endpoints (Mainnet & Base) ``` POST /orders # Submit order GET /orders/{uid} # Order status POST /quote # Get quote GET /tokens # List supported tokens ``` ### Conditional Orders API For Watch Tower polling of your bonding curve orders: ```typescript // Create conditional order (stored in ComposableCoW) const conditionalOrder = await composableCoW.create({ handler: mycoConditionalOrderAddress, salt: generateSalt(), staticInput: abi.encode(['OrderData'], [{ direction: 0, // BUY inputAmount: ethers.parseUnits("1000", 6), minOutputAmount: ethers.parseUnits("2000", 18), receiver: userAddress, validityDuration: 86400 // 24 hours }]) }); // Watch Tower polls getTradeableOrder automatically // No manual submission needed! ``` --- ## 8. Integration with MycoFi Bonding Curves ### Your Current Architecture (Summary) ``` User → BondingCurveAdapter (quotes) BondingCurve (executes buy/sell) MycoConditionalOrder (defines order type) ComposableCoW (stores in handler registry) GPv2Settlement (executes on-chain) ``` ### Step-by-Step Integration Checklist - [ ] **Phase 1: Setup** - [ ] Deploy MycoBondingCurve on Base - [ ] Deploy MycoToken with mint/burn controls - [ ] Set up USDC approval from bonding curve to adapter - [ ] **Phase 2: Adapter Integration** - [ ] Deploy BondingCurveAdapter pointing to GPv2Settlement - [ ] Test `executeBuyForCoW()` and `executeSellForCoW()` - [ ] Verify quote functions (`quoteBuy`, `quoteSell`) - [ ] **Phase 3: Conditional Order** - [ ] Deploy MycoConditionalOrder handler - [ ] Implement Watch Tower polling simulation (local testing) - [ ] Verify `getTradeableOrder()` generates valid GPv2Order.Data - [ ] **Phase 4: End-to-End Testing** - [ ] Register handler in ComposableCoW test instance - [ ] Submit test conditional order - [ ] Verify execution in mock settlement - [ ] **Phase 5: Watch Tower Integration** - [ ] Register with CoW Protocol Watch Tower (request access) - [ ] Provide handler address and metadata - [ ] Monitor first live orders ### Advanced: Multi-Curve Settlements If you want multiple bonding curves (different tokens): ```solidity contract MultiTokenCurveHandler is IConditionalOrder { mapping(address token => address curve) public curveRegistry; mapping(address token => address adapter) public adapterRegistry; function getTradeableOrder( address owner, address, bytes calldata staticInput, bytes calldata offchainInput ) external view override returns (GPv2Order.Data memory) { (address token, uint256 amount, uint256 minOut) = abi.decode(staticInput, (address, uint256, uint256)); address adapter = adapterRegistry[token]; uint256 quote = IBondingCurveAdapter(adapter).quoteBuy(amount); return GPv2Order.Data({...}); } } ``` --- ## 9. Key Gotchas & Best Practices ### Critical Safety Points 1. **VaultRelayer Authorization** - Users approve **Balancer Vault**, not Settlement directly - Settlement calls VaultRelayer to pull tokens - If you approve Settlement: malicious solver could drain funds 2. **Quote Expiry** - Watch Tower quotes expire quickly (~30-60s) - Always check `block.timestamp > quote.validTo` in `getTradeableOrder` - Revert with `OrderNotValid` if stale 3. **Reentrancy** - BondingCurveAdapter uses `nonReentrant` guard - Settlement is reentrant-safe but individual hooks aren't - Lock your curve during settlement 4. **Slippage Management** - `minOutputAmount` is **hard floor** in conditional order - If quote falls below min, Watch Tower retries next block - Don't rely on percentage-based slippage in immutable adapter ### Testing Strategy ```solidity // 1. Unit test bonding curve in isolation test("buy increases price") { ... } // 2. Test adapter with mock settlement function testAdapterBuy() { usdc.transfer(adapter, 1000e6); uint256 mycoOut = adapter.executeBuyForCoW(1000e6, 2000e18); assert(mycoToken.balanceOf(adapter) >= 2000e18); } // 3. Test conditional order logic function testGetTradeableOrder() { bytes memory staticInput = abi.encode(OrderData(...)); bytes memory offchainInput = abi.encode(OffchainData(...)); GPv2Order.Data memory order = handler.getTradeableOrder( owner, sender, staticInput, offchainInput ); assert(order.buyAmount >= minOut); assert(order.validTo > block.timestamp); } // 4. Fork test against real Base settlement function testLiveSettlement() { // Use foundry forge-std for Base fork } ``` --- ## 10. Resources & References ### Official Documentation - [CoW Protocol Docs](https://docs.cow.fi/) - Main reference - [ComposableCoW GitHub](https://github.com/cowprotocol/composable-cow) - Conditional order framework - [CoW Contracts Repository](https://github.com/cowprotocol/contracts) - Settlement contract source ### Concepts - [Understanding MEV Protection](https://cow.fi/learn/understanding-mev-protection) - How CoW prevents sandwich attacks - [Understanding Batch Auctions](https://cow.fi/learn/understanding-batch-auctions) - Order collection and solving - [Fair Combinatorial Auction](https://docs.cow.fi/cow-protocol/concepts/introduction/fair-combinatorial-auction) - Solver optimization model ### SDKs & APIs - [CoW SDK](https://docs.cow.fi/cow-protocol/reference/sdks/cow-sdk) - TypeScript/JavaScript - [API Integration](https://docs.cow.fi/cow-protocol/integrate/api) - REST endpoints - [Order Book Package](https://www.npmjs.com/package/@cowprotocol/sdk-order-book) - Direct API client ### Your Implementation Guides - [Flow of an Order](https://docs.cow.fi/cow-protocol/concepts/how-it-works/flow-of-an-order) - Lifecycle - [Solvers](https://docs.cow.fi/cow-protocol/concepts/introduction/solvers) - How optimization works - [Intents](https://docs.cow.fi/cow-protocol/concepts/introduction/intents) - Intent-based model ### Articles & Explainers - [CoW Swap Explained: Intent-Based DEX Trading With MEV Protection](https://eco.com/support/en/articles/13064300-cow-swap-explained-intent-based-dex-trading-with-mev-protection) - [CoW Protocol Batch Auctions Explained](https://metalamp.io/magazine/article/cow-protocol-batch-auctions-how-orderbook-autopilot-and-solvers-ensure-fair-trading) - [How CoW Protocol Actually Works](https://cow.fi/learn/how-cow-protocol-actually-works) --- ## 11. Next Steps for MycoFi Implementation ### Immediate (MVP) 1. Review your current `MycoConditionalOrder` and `BondingCurveAdapter` 2. Test against Base Sepolia testnet 3. Get Watch Tower access from CoW Protocol team 4. Deploy handler registry entry ### Short-term (Production) 1. Multi-token support (different community tokens) 2. DCA/TWAP variants for recurring buys 3. Limit order types (buy below price, sell above) 4. Revenue sharing mechanism (solver rewards) ### Long-term (Advanced) 1. Bonding curve governance (adjust parameters via DAO) 2. Cross-chain settlements (Arbitrum + Optimism) 3. Custom solver incentives (reward MEV-minimizing solvers) 4. Integration with rSpace for account-bound trading --- **Document Version:** 1.0 **Last Updated:** 2026-04-03 **Status:** Research Complete - Ready for Implementation