Ideas for ensuring fair solutions: envy-freeness of AMMs and capped surplus

This proposal is joint work of the CoW Protocol solver team (@marco, @harisang, Alex and myself) and our friend @voyta.eth.


An implicit promise of CoW Protocol is that users should get an equal or better deal than if they traded against publicly available liquidity offered by prominent protocols, such as Uniswap, Balancer, or Curve. This blog post makes this promise more explicit, and suggests a simple method that solvers may implement to minimize their chances of breaking this promise.


The objective function for solvers to maximize as defined by the current rules of the competition comprises the total user surplus. As of the date of this post, CoW Protocol settles only a minority of total volume on Ethereum, but this total user surplus does not directly consider the clearing exchange rates outside CoW Protocol. This is of particular concern in batches where user orders can be matched directly against each other within a certain price interval. In these cases, solvers currently have some freedom to choose the clearing price, and hence to determine how the achieved surplus is distributed to the users. This, in turn, may lead to solutions that can objectively be considered “unfair” with respect to the external market prices.

In our view, the uniform clearing prices (exchange rates) computed by a solver should be in line with what the users would get elsewhere. In other words, solutions should only be considered valid if they cannot be significantly improved by using publicly available liquidity.

The goal of this post is to propose a notion of “fairness” of a settlement based on the state of a set of baseline on-chain liquidity sources (AMMs). We will refer to this concept as “envy-freeness of AMMs”. While it is yet to be researched how this can be most effectively added to the rules of the solver competition, we describe “capped surplus” as a simple modification of the objective function that can help solvers find “fair” solutions.

Please note that this post is about fair surplus distribution in the context of CoWs (that is, directly matching user orders on a token pair or cycle), whereas this other blog post by @harisang investigates fairness for multiple independent trading cycles of user orders and AMMs.

Envy-freeness of AMMs

For limit orders, envy-freeness mandates that all orders whose limit prices satisfy the given clearing price need to be matched. That is, “envy” refers to the quoted clearing price, but extends to the mutual relationship between orders: whenever some order is matched, all orders offering a lower (“less ambitious”) limit price must also be matched.

The concept of envy-freeness can easily be adapted to AMMs: for any given clearing price, an AMM can be “envious” if it offers a better price but was not used. In the following, we will show how this can be useful for ensuring fairness for user orders.

The main idea of AMM envy-freeness is easiest to understand for two-dimensional order books. As an example, let’s consider the following scenario, where the “external market price” is represented by a single AMM, with its spot price between the limit prices of two perfectly matching orders:

The picture can be read as follows:

  • We’re looking at a pair that involves token A (traded against some other token)
  • Sell order o1 is selling A at any price above its limit price (indicated by the green arrow)
  • Buy order o2 is buying A at any price below its limit price (red arrow)
  • There’s an AMM (whose trading curve is plotted in orange) that also sells (the upper curve) and buys A (the lower curve)

In a settlement, the AMM does not need to be used at all. Any clearing price between the two orders’ limit prices yields the same amount of total user surplus and thus the same objective function value. Hence, it is currently up to the solvers to decide how the surplus is distributed. For example, setting the clearing price to the limit price of o2 would give all surplus to o1. However, this solution immediately appears “unfair” when taking the external market information (as provided by the AMM) into account. This is because o2 would have received more surplus if it had traded against the AMM. Seen from another angle, the AMM would have liked to trade at that clearing price, and thus is “envious” if it is not used. With this, it becomes obvious that the clearing price should be equal (or at least very close) to the AMM spot price: both o1 and o2 receive at least as much as if they traded against the AMM and are protected from being exploited, and the AMM itself is “envy-free”.

As a slight variation of the above, consider that the order o2 is now larger than o1:

In this case, the only way to find a solution is to use the AMM, which puts the clearing price (i.e., the effective exchange rate) somewhere between the original and the new AMM spot price.

Now let’s consider what could happen if the AMM spot price was lower than o1’s limit price:

In this case, depending on the size and type (buy vs sell) of o1, there can be a choice between matching o2 against o1 alone, matching o2 against the AMM alone, or match o2 against both o1 and the AMM. If o2 is matched against o1 alone then the AMM would be (legitimately) envious of o1 - informally, it would have liked to trade with o2 since it could match, and even improve, the price offered by o1. To avoid making the AMM envious, the clearing price of this batch can never be higher than its new spot price, which ends up protecting order o2.

More formally, the envy-freeness constraint we would need to check reads:

p(A) <= new_spot_price(xAMM, yAMM) (1)

where xAMM and yAMM are the buy and sell amounts of the AMM, and p are found prices.

Asking for all solutions to be strictly envy-free could unfortunately lead to many acceptable solutions being rejected. A solver might choose to not use an AMM that is envious for legitimate reasons: because it is not cost-effective to do so, because it would imply trading AMMs against other liquidity, among others. This means that the protocol cannot require strict envy-freeness of AMMs in general, but would most likely have to work with some relaxation (whose specifics are yet to be researched). Generally, the addition of some envy-freeness condition to the rules of the solver competition that can be checked by the backend seems highly desirable, but its specifics still need further research. Meanwhile, as a simpler alternative, the following slight change to the objective function can help achieve a fairer surplus distribution in most cases.

Capped surplus

In solutions with multiple user orders, we generally want the clearing prices to reflect the current exchange rates on the external market. That is, none of the orders should receive a better-than-market price by taking advantage of another. As mentioned above, regular surplus does not take external market information into account. Alternatively, one could consider a slight modification of the objective function, where the surplus that an order can contribute to the objective function value is “capped” at the external market price.

Going back to the first example of two perfectly matching orders, where the AMM represents the state of the external market, each order would only be allowed to contribute surplus up to the AMM spot price:

If the clearing price equals the AMM spot price (as in the left picture), the total (capped) surplus is maximized. By contrast, setting the clearing price below the AMM spot price (as in the right picture), yields a lower total (capped) surplus value.

As another example, let’s assume that order o2 requires a very ambitious limit price (requesting more than it would get on the external market):

Now, the capped surplus of order o2 will always be zero as its limit price is beyond the AMM spot price. Thus, only order o1 can contribute to the objective function value, which pushes the clearing price towards o2’s limit price (as in the left picture), protecting o1 from being exploited.

Formally, we define capped surplus as follows:

capped_surplus := min(external_prices_based_surplus; surplus)


  • external_prices_based_surplus is a theoretical surplus that would have been obtained if the trade was executed at the external exchange rate, which is determined and provided by the backend as part of the instance. Typically, this is not attainable for a user order given that there is some price impact, AMM fees, etc.

  • surplus refers to the status-quo user surplus, based on the user’s limit price and the execution price.


Both ideas that we presented help prevent a broad range of unfair solutions and surplus shifts, but in different ways: while envy-freeness of AMMs enforces fairness as a constraint, capped surplus tries to guide the solution to fair grounds via the objective function.

Currently, the solver team believes that envy-freeness of AMMs is a more elegant and long-term viable concept, although it is pending a formal specification and subsequent implementation testing.

In terms of drawbacks, we can think of the following:

Envy-freeness of AMMs

  • Potentially somewhat complex implementation, resulting from technicalities such as cost of using an AMM (gas costs are not part of the above equation (1)), arbitrage, etc…
  • Might be difficult to incorporate for solvers as it requires a detailed AMM modeling
  • Unclear how to verify for private liquidity of solvers (i.e., liquidity sources that were not provided by the backend as part of the batch instance, but “found” and used by the solvers themselves)

Capped surplus

  • Potential for surplus shifting is not fully eliminated (only soft enforcement via objective; does not necessarily guarantee fairness for each order individually)
  • Heavily relies on the accuracy of the external market prices that are used (surplus shifting potential remains in cases where the given external prices are not consistent with on-chain liquidity)
  • Centralization concerns - the external price is an essential input provided in a centralized way, while long-term CoW Protocol would like to abandon such centralizing elements

We are looking forward to feedback!


I really like the capped surplus idea, it’s so much simpler yet still gets close to the core objective.

Just a thought on getting around centralized market prices. You could set the cap not based on a single set of clearing prices, but using the best marginal exchange rate available in the same direction as the user order.

For example, take a user order offering to sell 2K USDC for 1 ETH, and the best marginal AMM rate at which you could sell 1 ETH for UDSC is 1.95K, then the surplus will be capped once the exchange rate drops below 1.95K.

To put this in context of the image above, it would correspond to setting the surplus cap of o1 at the point where the top AMM curve crosses the y-axis, and the surplus cap of o2 where the bottom AMM curve crossed the y-axis. (Note, this means that the surplus caps are crossed, ie there is a range of clearing prices where o1’s surplus increases and o2’s surplus decreases and vice versa. )

The logic here is that this caps are set at the boundary price at which an AMM for a given token pair could become envious. That is, if your surplus is not getting capped under this rule, you are guaranteed envy-free (and this cap is the most relaxed value that will give this guarantee without further conditions).

It solves the issue of external market pricing accuracy and can be agreed on by decentralized actors relatively easily.


Thanks @tbosman for your comment!

I like the idea of considering the marginal prices that AMMs can offer! How would you select and curate the list of AMMs to be considered? Just the “baseline” AMMs that we pass as part of the instance?

Hi @tbosman,

Just noting that, if I understand your idea correctly, ,

(Note, this means that the surplus caps are crossed, ie there is a range of clearing prices where o1’s surplus increases and o2’s surplus decreases and vice versa. )

means that the sum of both surpluses is constant in that range, which implies that any price within that range is ranked the same.


Yeah I would say definitely the baseline AMMs. Would be harsh to expect solvers to take into account other liquidity as hard constraint in general.

But perhaps, we could add any new source that was actually used in the solution the solver submitted? Like, if you use a source of liquidity with an exchange rate that is better than the best marginal available in the input, that marginal is updated to that rate for the purpose of capping.

Yes, correct.

If I understand correctly, this would cap surplus on the AMM price, instead of the spot price, right? Or speaking visually it would look like this:

instead of:

While I agree, that this could be sufficient for protection (and therefore could be a hard constraint), I wonder if it’s an issue that improving user orders price compare to “baseline” (which will be by no means complete or necessarily competitive with other DEX aggregators) would not improve the objective value and therefore not incentivise using non-obvious liquidity to truly improve the user’s execution.

Actually what I mean is that the surplus of o2 will go all the way down to the lower AMM line, i.e. the marginal price at which we can sell to the AMM.

(In general, the surplus should always be at least as high as when using the spot price, because for both orders you are using the more favorable bound out of the two possible marginals.)

This will still incentivize solvers to find better priced liquidity, up to the point that that price is would constitute an arbitrage opportunity with the baseline liquidity (which shouldn’t be a common occurrence )

Like this?

Yes, exactly! And if the clearing price was a lot higher, than the green surplus would be capped at the top AMM line

What’s the advantage of providing incentive for the Objective to provide o2 with a better rate than is the AMM spot price though? If there are concerns with external price, and we assume we know AMM curves, then AMM spot price seems like a more natural cap.

As pointed out by Marco, this does not perfectly discriminate between solutions, one property we need. If there is a perfect COW-trade, I’d say that AMM spot price is the fair exchange rate.

I guess my primary motivation was to have a quantity that is unambiguous from the liquidity provided. There is no single AMM spot price if there are multiple that cover the same pair, so which one do you take? Maybe if you want a single cap for both directions you could just take the midpoint of the best marginal?

I see your point out the solution being uniquely defined, that is pretty convenient.

Right, that sounds good. I’m guessing the deriving a robust function of estimating the AMM spot price would depend on implementation details of contributing AMMs, could be something like midpoint of the best AMM, or midpoint between (potentially weighted) bid/ask for very small volume of different AMMs, or something similar.