ethereumuniswap

Uniswap V3: what does price mean at a given tick?


I'm looking at the uniswap docs which states this example:

An example of finding the price of WETH in a WETH / USDC pool, where WETH is token0 and USDC is token1:

You have an oracle reading that shows a return of tickCumulative as [70_000, 1_070_000], with an elapsed time between the observations of 10 seconds.

We can derive the average tick over this interval by taking the difference in accumulator values (1_070_000 - 70_000 = 1_000_000), and dividing by the time elapsed (1_000_000 / 10 = 100_000).

With a tick reading of 100_000, we can find the value of token1 (USDC) in terms of token0 (WETH) by using the current tick as i in the formula p(i) = 1.0001**i (see 6.1 in the whitepaper).

1.0001**100_000 ≅ 22015.5 USDC / WETH

The price of WETH is not $22015.50. I though maybe they just use an example with easy numbers. So I decided to try the example from the whitepaper on the USDC/WETH pool

enter image description here

Calling slot0 on the contract returns:

enter image description here

Making the price

1.0001 ** 205930 = 876958666.4726943

Clearly the price for ETH is not 876958666 USDC. The current tick is 205930, but the price for ETH is just 1200.49 USDC. How do I get the correct USDC price of ETH from the tick?


Solution

  • On the mainnet, the USDC ERC-20 token has 6 decimals, ETH has 18 decimals. However, the price tracked by Uniswap internally is not aware of these decimals: it's actually the price of one micro-USDC (i.e. 0.000001 USDC) per one wei.

    This price is calculate by computing the exponent of the Uniswap v3 tick basis constant 1.0001. If the price tick is 205930, you get your result:

    1.0001 ** 205930 = 876958666.4726943
    

    To adjust this internal price to a human readable price, you must multiply it by 10**6 (the decimals of USDC) and divide by 10**18 (the decimals of [W]ETH), which is equal to multiplying the price by 10**-12.

    876958666.4726943 * (10 ** -12) = 0.0008769586664726943
    

    Finally, you probably want the inverse this number. The small number that you just got is the price of USDC in terms of ETH, but we usually want to track the price of ETH in terms of USD[C]. This is because price in Uniswap is defined to be equal to token1/token0, and this is a USDC/WETH pool, meaning that token0 is USDC and token1 is WETH.

    This computes the inverse:

    1 / 0.0008769586664726943 = 1140.3045984164828
    

    The answer is approximately 1140.30 USDC per one ETH.

    If you do this Solidity, take into account that it does not have floating-point numbers, all calculations are done with fixed-point numbers. Specifically Uniswap uses binary fixed-point numbers (Q numbers), and keeps track of square root of the price multiplied by 2**96.