Uniswap v3 – What Does ‘Price’ Mean in Uniswap v3 Trading?

ethers.jsuniswapuniswapv3

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, how do I get the usdc price of eth?

Best Answer

So the whitepaper is great, but doesn't get into Token Decimals, since tokens will have different decimals, this must be taken into account

for tick to price (which is imprecise compared to sqrtPrice)

(1.0001**Math.abs(tick))/(10**Math.abs(token0Decimals-token1Decimals)) = Token0 price in relation to Token1

Price from sqrtPriceX96

and here is a script in mjs form, but math is extrapolatable

import { JSBI } from "@uniswap/sdk";
import { ethers } from 'ethers';
import * as fs from 'fs';

    // ERC20 abi
let ERC20Abi = fs.readFileSync('<path>/ERC20.json');
const ERC20 = JSON.parse(ERC20Abi);
    // V3 pair abi
let pool = fs.readFileSync('<path>/V3PairAbi.json');
const IUniswapV3PoolABI = JSON.parse(pool);
    // V3 factory abi
let facto = fs.readFileSync('<path>/V3factory.json');
const IUniswapV3FactoryABI = JSON.parse(facto);


const provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.alchemyapi.io/v2/<API_Key>")


const factory = "0x1F98431c8aD98523631AE4a59f267346ea31F984";


async function getPoolData(token0, token1, fee){
    const t0 = token0.toLowerCase() < token1.toLowerCase() ? token0 : token1;
    const t1 = token0.toLowerCase() < token1.toLowerCase() ? token1 : token0;
    const token0contract =  new ethers.Contract(t0, ERC20, provider);
    const token1contract =  new ethers.Contract(t1, ERC20, provider);
    const token0Decimal = await token0contract.decimals();
    const token1Decimal = await token1contract.decimals();
    const token0sym = await token0contract.symbol();
    const token1sym = await token1contract.symbol();
    const FactoryContract =  new ethers.Contract(factory, IUniswapV3FactoryABI, provider);
    const V3pool = await FactoryContract.getPool(token0, token1, fee);
    const poolContract =  new ethers.Contract(V3pool, IUniswapV3PoolABI, provider);
    const slot0 = await poolContract.slot0();
    const pairName = token0sym +"/"+ token1sym;
    return {"SqrtX96" : slot0.sqrtPriceX96.toString(), "Pair": pairName, "T0d": token0Decimal, "T1d": token1Decimal}
}


function GetPrice(testz){
    let sqrtPriceX96 = testz.SqrtX96;
    let token0Decimals = testz.T0d;
    let token1Decimals = testz.T1d;
    
    const buyOneOfToken0 = (sqrtPriceX96 * sqrtPriceX96 * (10**token0Decimals) / (10**token1Decimals) / JSBI.BigInt(2) ** (JSBI.BigInt(192))).toFixed(token1Decimals);
    const buyOneOfToken1 = (1 / buyOneOfToken0).toFixed(token0Decimals);
    console.log("price of token0 in value of token1 : " + buyOneOfToken0.toString());
    console.log("price of token1 in value of token0 : " + buyOneOfToken1.toString());
    //console.log("");
    
        // Convert to wei
    const buyOneOfToken0Wei = (Math.floor(buyOneOfToken0 * (10**token1Decimals))).toLocaleString('fullwide', {useGrouping:false});
    const buyOneOfToken1Wei = (Math.floor(buyOneOfToken1 * (10**token0Decimals))).toLocaleString('fullwide', {useGrouping:false});
    console.log("price of token0 in value of token1 in lowest decimal : " + buyOneOfToken0Wei);
    console.log("price of token1 in value of token1 in lowest decimal : " + buyOneOfToken1Wei);
    console.log("");
}


async function st(){
    const data = await getPoolData("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0xdAC17F958D2ee523a2206206994597C13D831ec7", 500);
    console.log(data)
    GetPrice(data)
}

st() 
Related Topic