What is solving? A matehmatical, high-level description
At a high level, a solver is an algorithm that takes as inputs the orders that are valid for an auction, the state of the liquidity sources that the solver can access, the rules set by the protocol (including those specifying the protocol fees), and returns one or multiple solutions, where a solution selects a subset of the orders valid in an auction and specifies feasible an in and out amounts for each of those orders. The solutions proposed by each solver during a given auction are the outcome of a two-step optimization problem: optimal routing and then optimal bidding.
In this section, we describe mathematically the different components of the "solving" problem. We discuss optimal routing and optimal bidding in the solvers' strategy section.
User orders
Suppose that there are tokens. From a high-level perspective, we can define a user order as an acceptance set 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 and 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.
We also assume that that is, when submitting an order a user accepts that the order may not be filled. Also, to each order we define surplus_function , measuring "how good" a trade is from the point of view of the user who submitted order S. By definition .
Practically speaking, CoW Protocol allows only some types of orders, which we can think of as constraints on the set S that a user can submit. One such constraint is that only pairwise swaps are allowed, that is, all vectors in have zeros in dimensions. Furthermore, each order must fit within one of the categories we now discuss. To simplify notation, when discussing these categories, we assume that .
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 whenever the executed sell amount must be Y (or nothing). They can be partially fillable if 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
and a partially-fillable sell order has the form
In both cases, the surplus function is defined as
,
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
while partially-fillable limit buy orders have the form
Again, the surplus function is defined as
.
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