On-chain range orders using Uniswap V3

Peteris Erins
Auditless

--

A surprising outcome of the Uniswap V3 design is the possibility of executing range orders. Both take-profit orders (sell asset X once it hits a high-enough price) and buy limit orders (buy asset X once it hits a low-enough price) are possible.

One of the feedback points on our recent post on Impermanent Loss in Uniswap V3 was that range orders are a perfect example where impermanent loss actually works in your favor:

This is true and a great starting point to explore how price prediction may affect traders' perception of impermanent loss. In this post we will try to answer 3 questions:

  • How concentrated liquidity positions support range orders?
  • What is the effective price of the range order?
  • What are the pros and cons of on-chain range orders as they are implemented with Uniswap?

How concentrated liquidity positions support range orders

The possibility of range orders may come as a surprise to those of you familiar with Automated Market Maker (AMM) designs. Without an order book, how could we keep track of different orders and their respective price levels?

The answer is concentrated liquidity positions. The protocol does keep track of each concentrated liquidity position and it's possible to use them as range orders.

It works like this:

If you'd like to place a sell order once the price of ETH in DAI hits p_a, instead set up a small concentrated liquidity order in the range [p_a, p_a + Δ]. Since the current price will be out of range, all the assets will be held in ETH.

Once the price enters the range, your liquidity will become active as the price crosses the tick. By the time the price exits at p_a + Δ, all your position will consist only of DAI, finalizing the range order.

At that point, you should remove your liquidity or your position may be reentered if the price falls again. In that sense you could call these impermanent range orders.

What is the effective price of the range order

Definitions

We consider a market with liquidity L in the range and amounts x and y of assets ETH and DAI respectively in a concentrated liquidity position.

We will measure prices of ETH in terms of DAI. We define [p_a, p_b] to be the price interval for our concentrated liquidity position.

For our range order, we'd like the interval to be a small as possible (we will see why that is in a minute). We can make it equal to one tick such that sqrt(p_b) = sqrt(p_a)+ t where t is the tick value. Remember that Uniswap V3 uses square roots of prices for tracking so tricks represent spaces in between square root values.

Derivation

Recall the reserve equation for concentrated liquidity:

From this equation, we can figure out the ETH and DAI reserves at either end of the curve.

First set ETH amount to 0 (x = 0), this will correspond to the price p_b (exiting the range):

Then set DAI amount to 0 (y = 0), this will correspond to the price p_a (entering the range):

Finally our effective price at which we get to sell ETH is the exchange rate between ETH and DAI or

Compare this to the price that traders get which would be:

The calculation is virtually the same for sell orders.

Conclusions

As we see, the price is slightly higher than the price p_a offered to traders (depending on the tick size), however, in this case we are the liquidity provider not the trader so we will also benefit from fees depending on how much overall liquidity is provided in the position.

What are the pros and cons of on-chain range orders as they are implemented with Uniswap?

First, the pros:

  • Range orders are implemented fully on-chain. This means that it is guaranteed to execute in periods of rapid price movement and you don't have to worry about trust and timing of off-chain execution. This also allows vaults to set up range orders which some are exploring already.
  • Potential to gain fees makes range order potentially more lucrative
  • Gas fees can be paid when entering the LP position, but don't have to be paid when market is experiencing high volatility

There are also some cons, some of which could be overcome in future designs:

  • Final pricing of the range order is not known as it depends on the fees. At least a lower bound on the price can be set depending on the tick and fees can be seen as a bonus
  • The range order is impermanent. If price jumps up and down before the LP can remove the liquidity position, the range order will be reserved (but fees gained will be retained)
  • The range order is inefficient as assets are locked up in the pool. For example, if you had 300 DAI and you wanted to buy 300 DAI worth of ETH, UNI or YFI, whichever hits a price target first, that order is impossible on chain (but possible off chain). Instead, you could only have 3 separate range orders for 100 DAI each.

Nevertheless, given this is a “free” feature that Uniswap V3 wasn't necessarily designed to solve, I think it's an incredibly useful addition as a gas-efficient on chain range order.

Want to read more stories like this?

Follow me on Twitter at p_e for frequent content on smart contracts and the crypto industry.

Subscribe to my Substack to get one actionable tip on how to build great crypto products every week.

--

--

Peteris Erins
Auditless

Founder @auditless Prev @mckinsey @twitter @google · @p_e · peteriserins.com