# How to get a virtual and real reserves from UniSwap V3 pair?

I need help with math of UniSwap V3 virtual and real reserves. Need to find the true reserves of a pair (value of token0 = value of token1). Example:

Let's say we have this DAI/WETH pair: 0x60594a405d53811d3BC4766596EFD80fd545A270 balance of DAI was - 2591437269710515203595384 & balance of WETH was - 2838497576725882781612 As we can see here, reserve's of tokens in this pool disbalanced DAI value in pool - 2,594,028.706980225 \$ - 43 % WETH value in pool - 3,461,888.414526421 \$ - 57 %

If I'am not mistaken, because of concentrated liquidity we have a different virtual reserve's in every "concentrated" zone. Also, those virtual reserve's should be balanced (50/50 - value) by x*y=k. Does anyone know how to find those virtual and/or real reserve's?

I've succesfully calculated a price of both token's: token0Price= sqrtRatioX96 ** 2 / 2 ** 192 = 2267580935849786082246943435 **2 / 2 **192 = 5.141923300629392e+54 / 6.277101735386681e+57 = 0.0008191556417896165

token1Price = 2 ** 192 / sqrtRatioX96 ** 2 = 6.277101735386681e+57 / 2267580935849786082246943435 **2 = 6.277101735386681e+57 / 5.141923300629392e+54 = 1220.7692274636495 And price's are fine.

Also, I've got: Reserves token0 x = L / sqrt(P) x = 776218541774739337116335 / sqrt(0.0008191556417896165) x = 776218541774739337116335 / 0.02862089519 x = 2.7120694046143822e+25 x = 27120694046143822000000000

Reserves token1 y = L * sqrt(P) Suppose that sqrt(P) is sqrt(token1Price) then: y = 776218541774739337116335 * sqrt(1220.7692274636495) y = 776218541774739337116335 * 34.9395081171 y = 2.7120694040982028e+25 y = 27120694040982028000000000

x = 27120694046143822000000000 y = 27120694040982028000000000

Yeah, it's look like 50/50, but not by it's token reserves value. I'm not sure, that's my math is correct.

Thank you!

• The virtual reserves in terms of `x` and `y` are very rarely needed; liquidity is almost always what you want to calculate and use. Real reserves in a pool are complex to calculate because of the non-uniform liquidity. See my answer here stackoverflow.com/a/71815432/2435820
– kfx
Nov 22, 2022 at 11:19

Here is a mjs file I created for the token balance of a V3 position, the math should be easily extractable

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

// ERC20 json abi file
const ERC20 = JSON.parse(ERC20Abi);

// V3 pool abi json file
const IUniswapV3PoolABI = JSON.parse(pool);

// V3 factory abi json
const IUniswapV3FactoryABI = JSON.parse(facto);

// V3 NFT manager abi
const IUniswapV3NFTmanagerABI = JSON.parse(NFT);

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

// V3 standard addresses (different for celo)
const NFTmanager = "0xC36442b4a4522E871399CD717aBDD847Ab11FE88";

async function getData(tokenID){
let FactoryContract = new ethers.Contract(factory, IUniswapV3FactoryABI, provider);

let NFTContract =  new ethers.Contract(NFTmanager, IUniswapV3NFTmanagerABI, provider);
let position = await NFTContract.positions(tokenID);

let token0contract =  new ethers.Contract(position.token0, ERC20, provider);
let token1contract =  new ethers.Contract(position.token1, ERC20, provider);
let token0Decimal = await token0contract.decimals();
let token1Decimal = await token1contract.decimals();

let token0sym = await token0contract.symbol();
let token1sym = await token1contract.symbol();

let V3pool = await FactoryContract.getPool(position.token0, position.token1, position.fee);
let poolContract = new ethers.Contract(V3pool, IUniswapV3PoolABI, provider);

let slot0 = await poolContract.slot0();

let pairName = token0sym +"/"+ token1sym;

let dict = {"SqrtX96" : slot0.sqrtPriceX96.toString(), "Pair": pairName, "T0d": token0Decimal, "T1d": token1Decimal, "tickLow": position.tickLower, "tickHigh": position.tickUpper, "liquidity": position.liquidity.toString()}

return dict
}

const Q96 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(96));
const MIN_TICK = -887272;
const MAX_TICK = 887272;

function getTickAtSqrtRatio(sqrtPriceX96){
let tick = Math.floor(Math.log((sqrtPriceX96/Q96)**2)/Math.log(1.0001));
return tick;
}

async function getTokenAmounts(liquidity,sqrtPriceX96,tickLow,tickHigh,token0Decimal,token1Decimal){
let sqrtRatioA = Math.sqrt(1.0001**tickLow);
let sqrtRatioB = Math.sqrt(1.0001**tickHigh);

let currentTick = getTickAtSqrtRatio(sqrtPriceX96);
let sqrtPrice = sqrtPriceX96 / Q96;

let amount0wei = 0;
let amount1wei = 0;
if(currentTick <= tickLow){
amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtRatioA)/(sqrtRatioA*sqrtRatioB)));
}
else if(currentTick > tickHigh){
amount1wei = Math.floor(liquidity*(sqrtRatioB-sqrtRatioA));
}
else if(currentTick >= tickLow && currentTick < tickHigh){
amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtPrice)/(sqrtPrice*sqrtRatioB)));
amount1wei = Math.floor(liquidity*(sqrtPrice-sqrtRatioA));
}

let amount0Human = (amount0wei/(10**token0Decimal)).toFixed(token0Decimal);
let amount1Human = (amount1wei/(10**token1Decimal)).toFixed(token1Decimal);

console.log("Amount Token0 wei: "+amount0wei);
console.log("Amount Token1 wei: "+amount1wei);
console.log("Amount Token0 : "+amount0Human);
console.log("Amount Token1 : "+amount1Human);
return [amount0wei, amount1wei]
}

async function start(positionID){
let data = await getData(positionID);
let tokens = await getTokenAmounts(data.liquidity, data.SqrtX96, data.tickLow, data.tickHigh, data.T0d, data.T1d);
}

start(5)
``````
• Thank's al lot!) Will test! Dec 12, 2022 at 12:52
• yeah, no problem. feel free to ask questions, and I'm a uniswap friend in the uniswap discord Dec 15, 2022 at 4:09