Impermanent Losses in Uniswap-Like Markets
Liquidity providers to the Uniswap exchange and other Constant Function Market Makers such as Curve.fi and Balancer.io are known to suffer from “impermanent losses” — a phenomenon where certain trading patterns result in a loss of value of the liquidity pool, despite its growth from trading fee income. In this article, we try to look at the nature of impermanent losses from an intuitive perspective, and investigate the possibility of designing a fee mechanism that would eliminate them.
For an introduction to Uniswap and an additional point of view on impermanent losses, we refer the reader to this insightful article, while this paper offers a deeper look at Uniswap’s underlying mathematics.
Impermanent losses in Uniswap under zero fees
The Uniswap model of a market for assets x and y is based on simple formula, aka the “invariant”:
q(x)*q(y) = k
where q(x) and q(y) are Uniswap’s reserves in the corresponding assets, and k is a constant. The rules of the game are that any transaction (−△q(x), △q(y)) where quantity △q(x) is withdrawn by the trader in return for △q(y) is permissable if the following expression is satisfied:
Current market price of x in terms of y (aka the marginal price) is the negative of derivative of q(y) with respect to q(x), which for Uniswap also happens to equal their ratio:
−dq(y)/dq(x) = k/q(x)² = q(y)/q(x)
Now let us consider what happens to the marginal price when a user withdraws △q(x) and adds △q(y). It is easy to see from the above formula that price of x is declining in q(x). In other words, by withdrawing △q(x) from reserves, the trader is raising the price of x.
Marginal price, however, is only relevant in the theoretical case where the user is trading in infinitesimally small quantities, and for valuation of the liquidity pool. The actual price paid by the trader is somewhere between the marginal prices before and after the trade. In other words, the protocol is permitting a trade at a price below one at which the liquidity pool will be valued immediately after that trade concludes, thereby giving rise to impermanent losses. This fact is illustrated on the chart below:
Impermanent losses would be erased if a trader then transacted in the same amounts and in the opposite direction, reverting the reserves to their original state. However, until and unless that happens, the losses stand.
Is it possible to eliminate impermanent losses?
In practice, Uniswap liquidity providers are rewarded with fees that partially compensate them for incurring impermanent losses. This naturally begs the question — is it possible to design a fee mechanism such that liquidity providers would never incur impermanent losses?
One way to tackle this problem is to set the fee for every trade to equal the impermanent loss. This approach makes an unrealistic assumption that each trade encapsulates the entirety of price movement to the new market equilibrium. As a result, it should not be viewed as a “solution”, and we will pursue it mainly as a mathematical excersise with a potential to provide useful insights.
First, let us adjust Figure 1 to incorporate a fee ℰ>0, deducted by the protocol from assets that traders contribute to reserves in order to withdraw others. In simple terms, when a trader adds △q(y), the protocol pretends that the actual amount is △q(y)−ℰ, and calculates the corresponding △q(x) accordingly. Then, having gained ℰ “for free”, the protocol upgrades the invariant’s constant from k_0 to k_1. Please note that to improve legibility we will use q(x) and q(y) to represent both starting reserve levels and the general reserve variables.
To derive ℰ that always cancels out the impermanent loss, we set the actual price paid by the trader to equal the post-trade marginal price:
(q(y)+△q(y)) / (q(x)−△q(x)) = △q(y) / △q(x)
We introduce ℰ into the above equation by noting that the protocol calculates △q(x) by feeding △q(y)−ℰ into the pre-trade invariant. This allows us to solve for ℰ with the following result:
ℰ/△q(y) = (△q(y)/q(y)) / (1+△q(y)/q(y))
To simplify interpretation, we redefine the fee as a percentage of added assets, such that %_fee=ℰ/△q(y). Further, we set z=△q(y)/q(y) to represent added assets as percentage of pool size. That gives us the following expression:
%_fee = z/(1+z)
This function is strictly increasing, and matches Uniswap’s fixed percentage fee of 0.3% when the trader contributes assets in the amount of roughly 0.3% of their reserve. Below that trade size, Uniswap charges a fee that is higher than the associated impermanent loss.
Finally, we note again that our fee mechanism is certain to have other, undesirable properties. For instance, we strongly suspect that it violates the “path independence” condition — loosely speaking, breaking up a trade into pieces may no longer yield the same result as transacting in one go. As a result, the mechanism would almost certainly be open to attacks unless deployed in context of a more holistic approach. For a deeper examination of the issue, we refer the reader to this recent work.