User orders
Suppose that there are {1,2,…k} tokens. From a high-level perspective, we can define a user order as an acceptance set S⊂Rk specifying the trades a user is willing to accept (where negative entries of a vector represent tokens sold, while positive entries represent tokens bought). So, for example, if k=2 and [x−y]∈S then a user is happy to receive x units of token 1 in exchange for y units of token 2.This is from the user’s perspective, and is therefore net of fees.
Sell Orders
A sell order specifies a maximum sell amount of a given token Y > 0, a buy token b, and a limit price π, that corresponds to the worst-case exchange rate that the user is willing to settle for. The limit price can be specified explicitly (as in the case of limit orders) or derived from an underlying quote and a slippage tolerance parameter (as in the case of market orders). Sell orders can be fill-or-kill which means that the executed sell amount must be Y (or nothing). They can be partially fillable which means that the executed sell amount can be smaller or equal to Y. Formally, if x denotes the (proposed) buy amount and y denotes the (proposed) sell amount of the order, a fill-or-kill limit sell order has the form S={[x−y] s.t. πy≤x and y∈{0,Y}}, and a partially-fillable sell order has the form S={[x−y] s.t. πy≤x and y∈[0,Y]}. In both cases, the surplus function is defined as U(x,−y)=x−y/π, i.e., it is the additional amount of buy tokens received by the user relative to the case in which they trade at the limit price, and is naturally expressed in units of the buy token. A final observation is that orders can be valid over multiple auctions. For a fill-or-kill, this means that an order that is not filled remains valid for a certain period (specified by the user). For a partially-fillable order, this also means that only a fraction of it may be executed in any given auction.Buy Orders
A buy order is specified by a maximum buy amount X > 0 and a limit price π corresponding to the worst-case exchange rate the user is willing to settle for. With x denoting the buy amount and y denoting the sell amount of the order, fill-or-kill limit buy orders have the form S={[x−y] s.t. y≤x⋅π and x∈{0,X}} while partially-fillable limit buy orders have the form S={[x−y] s.t. y≤x⋅π and x∈[0,X]}. Again, the surplus function is defined as U({x,−y})=x⋅π−y. Also here, orders can be executed over multiple auctions.CoW AMM orders
To trade with a CoW AMM pool, a solver needs to specify both a buy (or “in”) amount X > 0 and a sell (or “out”) amount Y > 0 for the pool. Similarly to a sell order, the acceptance set of a CoW AMM pool and its surplus functions are S={[x−y] s.t. πy≤x and y∈{0,Y}}, U(x,−y)=x−y/π. The main difference is that the limit price π corresponds to the price at which a zero-fee traditional AMM would trade. For example, in the case of a simple, constant product CoW AMM pool with reserves X and Y , we have π=X/(Y−y) Finally, unlike sell and buy orders that are not valid anymore once executed, CoW AMM orders are always present. That is, as soon as a CoW AMM pool is created, a CoW AMM order for that pool is valid in all subsequent auctions.Protocol Fees
Each user order may have an associated fee paid to the protocol. At a high level, these fees can be represented by a function that, for a given order S maps all possible trades to a non-negative vector of tokens, that is fS:S→R+k with fS(0)=0.Solvers are also expected to charge a fee to cover the costs of executing an order (for example, gas). We discuss such fees later in the context of solvers’ optimal bidding, but we do not account for them here as they are not part of the protocol.
Solution
Solvers propose solutions to the protocol, where a solution is a set of trades to execute. Formally, suppose there are I users and CoW AMM orders and J external liquidity sources. A solution is a list of trades {o1,o2,…oI,l1,l2,…,lJ} for each user, CoW AMM pool and external liquidity source such that:- Incentive compatibility and feasibility: the solution respects the orders’ acceptance set.
- Uniform directional clearing prices: all users trading the same token pair in the same direction must face the same prices. Importantly, this constraint is defined at the moment when the swap occurs. So, for example, suppose user i receives x units of token 1 in exchange for y units of token 2 and that the protocol takes a fee in the sell token f2. Define p1,2=xy−f2 as the price at which the swap occurs. Uniform directional clearing prices means that p1,2 is the same for all users buying token 1 and selling token 2. Deviations from uniform directional prices are allowed to account for the extra gas cost of orders triggering hooks.
- All other competition rules: These are a set of principles that solvers should follow, which were voted by CIPs.
- o is a sell order or a CoW AMM order: score(o)=(U(o)+f(o))⋅p(b), where p(b) is an externally provided price of the buy token relative to a numéraire.
- o is a buy order: score(o)=(U(o)+f(o))⋅p(b)⋅π, where p(b) is an externally provided price of the buy token relative to a numéraire and π is the limit price of the order.