# CoW Protocol Settlement Contract v2 ## Meetings ### 2023-12-11 Federico + MFW Agenda: * Architectural separation * Core repositories * Peripheral repositories * Contract repository standards * Tooling * Downstream consumers (smart-contracts / Rust / JS) * Review / Test standards * Testing frameworks * Coverage requirements * Checklist of items to review * Project management * Repo config Epics * Feature Epics * Additional features * Abstracted intents ## Overview This document serves as a collection for feature ideas we may want to incorporate into a version 2 of CoW Protocol, with the goal to prioritise them and estimate their complexity and time it will take to complete. ## Starting Point I (Felix) would strongly suggest to base v2 off the existing contracts and incrementally implement the desired changes instead of starting again on a white canvas. I think this will be both faster as well as safer than starting from scratch. The existing contracts have proven to be very prone and flexible as they are, the chance of building something better by completely redesigning the architecture are small IMO. It may require porting the existing contracts and unit tests over to foundry first (since we likely no longer want to use hardhat) ## Design Goals Below a list of goals we are trying to achieve by developing this new contract - Facilitate easier deployments on L2 and reduce complexity of the current approach. - Reduce barrier for solvers to be fully decentralised (ie have their own bonding pool) - Reduce gas overhead for swapping on CoW Swap - Incorporate learnings/limitations from the v1 contracts ## Features Tagged by priority (highest priority P0 -> lowest priority P3) and complexity (lowest complexity C0 -> highest complexity C3) ### [P0][C0] Use Uniswap Permit2 Currently users need to approve the VaultRelayer for every ERC20 token they want to trade on CoW Protocol. This contract is non-upgradable and only allows the existing settlement contract to pull funds on behalf of a user. This means that users will need to resubmit all their allowances for v2. In order to easen the process going forward, and to piggy-back on existing allowances users may have already given on other protocol such as Uniswap, we can replace the VaultRelayer by [Permit2](https://github.com/Uniswap/permit2). In the future this would allow changing the settlement contract and only require a single *offchain* signature from users to port all of their alllowances > dappcon23: If writing a new version, implementation of `Permit2` makes sense, but it is not a basis for a rewrite in itself. Makes sense to implement and enable vampire marketing to cross-ecosystem users. ### [P0][C1] Enforce execution of pre/post hooks on smart contract level Currently, pre and post hooks are signed by users as part of the app-data, and thus committed and signed for via the appDataHash field on the order struct. This authorizes the actions from the perspective of the user, however ensuring authorisation and inclusion of both pre- and post-interactions can only be done by the driver, and thus in a colocated world only checked off-chain after the settlement is observed. While censoring hooks is a slashable offense under the solver rules, it puts an economic limit on the value that hooks can secure and increases the pressure on the bonds/bonding pool. It should be relatively simple to encode the desired interactions as part of the order struct, that creates the order hash which is signed by the user. > dappcon23: Makes sense to implement, but need to have some consideration to DOS. Definitely adds many additional use cases. > mfw78: perhaps split social consensus / on-chain guarantees in the order intent. > nick: We specifically discussed "taking flashloans" as a usecase for hooks. This means that we need to have hooks "wrap the settlement" in order for that to work (under the assumption that FlashLoan providers won't add custom integrations for CoW Protocol due to SC risk). ### [P1][C3] Have an individual "Trade Handler" Settlement contract per solver At the moment, all settlements are - regardless of the winning solver - routed via a single [settlement contract](https://etherscan.io/address/0x9008D19f58AAbD9eD0D60971565AA8510560ab41). Fees and slippage are accrued in this contract and can potentially be removed by any solver either directly (via a transfer within a settlement) or indirectly (by approving another contract to spend this balance on behalf of the settlement contract). In order to protect these balances, the protocol requires a rather large bond from each solver. In order to protect `solverA` from stealing balances of `solverB`, it would make sense to create different settlement contract instances (using the same bytecode), where each solver only has access to the balances/allowances of "their" settlement contract. A few teams (e.g. Seasolver and Barter) are already implementing the concept of a custom trade handler today, but have to pay a gas overhead for the extra transfer from the protocol's contract to the trade handler. While having individual settlement contracts may fragment the liquidity we have stored in buffers, it does allow solvers to gas efficiently add their own inventory into the buffers (something a lot of market makers asked for) and pushes the complexity of managing inventory to the solvers. Additionally, we could make it so that solvers can augment the "core" settlement contract logic (making sure users get at least as much as they asked for) with additional logic by allowing interactions to `delegatecall` into other contracts. As long as critical, shared state (e.g. nonces, filled amounts, etc) are stored in a separate contract solvers should be allowed to mess with the state (but not the code), as long as they can't "delete" our code checks We should try to ensure we still have a single entrypoint (e.g. for nonce/order invalidation) so that it remains easy to identify CoW Swap settlements on etherscan. Furthermore, this reduces the risk of fee loss because of a "bad approval". The risk is not entirely to the solver's individual buffers meaning that neither "protocol funds" would not be at risk, nor loss of trust (like we saw with the "Barter hack"). > dappcon23: Would allow for solver's bonds to be reduced to be equal to surplus. May remove dependency on `feeAmount` to simplify quoting. Provides solvers with more control, potentially with solver-defined optimised order routers (eg. uniswap, curve etc). Increases competition / greatly reduces barrier to entry. > nick: We can also completely get rid of "interactions" and make the individual solver trade handler be completely generic. This also allows solvers to create specific gas-efficient trade handlers, for example, for doing direct Uniswap swaps. We can also provide a "default trade-handler" that just does the ### [P1][C1] Allow solvers to specify a target for the user's sell tokens to be sent to In most settlements, we currently incur an extra transfer from the user's funds into the settlement contract and then from the settlement contract into the target AMM contract. We can remove this extra transfer if solvers could chose where the user funds should be sent to (the only transfer that needs to happen from the context of the settlement contract is the transfer out to the users) > dappcon23: Functionality would be enabled by a trade handler. > nick: There are some usecases where a "target address" would be slightly more efficient (Uniswap comes to mind), but I'm not sure it is worth the additional complexity. ### [P1][C1] Expose clearing prices of the batch Currently clearing prices are emitted as events but not available to be read by external smart contracts (e.g. ERC1271 orders). Exposing clearing prices either temporarily or permanently (gas costs!) would allow CoW Swap to serve as a reliable price oracle and enable use cases where execution is not necessarily depending on the limit price of the order, but instead on the batch clearing price. > dappcon23: for temporarily exposing clearing prices of the batch, becomes more usable with TLOAD/TSTORE on L1, and make use of SLOAD/SSTORE on L2. Useful for hooks, limited usability for signature verification (additional complications around solver implementations). > nick*: "protected pure market orders" (ethflow) / signature verification issues ### [P1][C1] Group ERC20 transfers per address If a user trades e.g. USDC->ETH and GNO->ETH in the same batch the final token transfer of ETH into the user's contract could be batched into a single transfer to save on gas and make batching more effective. This optimisation requires analysis and benchmarking to see whether it's worth it on average. > nick: gas costs are likely not worth it. Additionally it makes it difficult to reason the path of tokens in a batch. ### [P2][C0] Allow to specify a target block number ~~/hash~~ for a settlement to be mined Settlement will revert if the `parentBlock.hash` isn't the expected one. This will allow to make settlement transactions only valid for one block (one auction per block). The same could also be achieved with a settlement wrapper contract. > dappcon23: Very trivial to implement, and has obvious value when moving to one auction per block, though this feature is not a justification to redo contracts. Can be implemented as is now (pre-interaction), but if doing new contracts, put this in. ### [P2][C1] Make use of transient storage whereever possible Setting and removing storage within the same transaction will become significantly cheaper. We can use this to e.g. temporarily store limit prices and reduce some of the data we are proactively passing around. > dappcon23: Use TSTORE/TLOAD for L1, SSTORE/SLOAD for L2. > mfw78: Speaking to some core devs seems to indicate Cancun ~1Q24 ### [P2][C0] Get rid of feeAmount on order struct We are trying to move into a world where all CoW Swap orders are pure limit orders for which solvers decide how much fee to charge (by providing slightly less surplus). The fixed fee amount already doesn't work for partially fillable orders and will just create unnecessary complexity and confusion around the way that CoW Swap charges fees. > dappcon23: Repurpose `feeAmount` for referral / integration fees, but all CoW Protocol fees remain at `0`. Potentially expand `feeAmount` to be the amount and the fee token. > dappcon23*: It's desirable to be able to do subsidies. > nick: Another possibility would be to add a `(feeToken, feeAmount)` pair specifically for additional protocol/partner fees. ### [P3][C0] Expose a function to place a full order on chain Currently we only expose `setPresignature(uid)` on the settlement contract. While emitting an event that contains the order's pre-image in the calling contract is trivial, providing a canonical way for a smart contract to place an order that is guaranteed to get indexed by the backend would be quite convenient and is something a lot of projects have asked for. > dappcon23: Yes. ### [P3][C3] Allow ERC1155, ERC721 (NFT) tokens To allow trading NFTs and other more exotic token types > dappcon23: By use of `Permit2`, the contracts will be more agile and able to integrate these features at a later date more readily if desired. Not a reason to rewrite the contracts as is at the moment. ### [P3][C3] Allow basket orders Allow users to express trading a set of sell tokens for a set of buy tokens. > dappcon23: ### Other - nick: allow passing in additional solver information for allow list authorisation. This could enable more advanced "authentication schemes". For example, instead adding support for specifying a target `blockNumber` check into the settlement contract, we can do it with the "solver authenticator" contract. Not saying this *should* be done, just that it *can and should be considered*. - federico: appData to become a merkle root of additional order information - federico: offchain order cancellation. Suggested by the frontend to make it possible to guarantee that an offchain-cancelled order is indeed not executable anymore. (This is not the case right now for offchain cancellation and order replacement.)