I'm trying to figure out the uncollected fees for my Uniswap v3 position programmatically. If I interpret the v3 whitepaper correctly it should be liquidity multiplied by the difference of feeGrowthGlobal0X128 and feeGrowthInside0LastX128.

What math shall I actually do to the feeGrowth* values that Uniswap contracts return to me? They are supposed to be Q128.128 values, so my expectation was I need to divide thm by 2**128 in order to get to actual number. Apparently it's wrong as the results I'm getting are far from what I see on the pool page.

For example, feeGrowthGlobal0X128 for the USDC/ETH v3 pool (0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8) is currently 706909750615834684891740623881648

What do I need to do with this number to come to "fees accumulated per unit of virtual liquidity"?

  • I think I have figured that out. If the price is inside your position range you need to take feeGrowthGlobal0X128 and subtract the following 3 values: 1) feeGrowthOutside0X128 returned by ticks() function for the lower tick of your position 2) feeGrowthOutside0X128 returned by ticks() function for the upper tick of your position 3) feeGrowthInside0LastX128 returned by positions() for your position You need to divide each fee growth number by 2**128, and multiply the result of the subtraction above by liquidity and then by 1e6 (no idea why TBH). You get the actual fees in token0 earned. Jun 15 at 17:41
  • I am not able to reproduce... could you write it down as a single equation perhaps :)? It would make a good answer to your question. In my case it just doesn't seem to line up with the right numbers no matter how I try. Jul 6 at 23:42
  • @vlad.london's method worked for me. The diving by 1e6 part depends on the decimals of the token in question. Many tokens are 18 decimals, so you would do 1e18 then I believe.
    – Travis M
    Jul 15 at 0:00

There is a bunch of functions on the smart contract that explains how to use the liquidity field: In Uniswap V3 core repository, in Position.sol line 60:

// calculate accumulated fees
  uint128 tokensOwed0 =
           feeGrowthInside0X128 - _self.feeGrowthInside0LastX128,

This would translate to this in javascript, using bignumber.js

const tokensOwed0 = feeGrowthInside0LastX128
    .div(new bn(2).pow(128));
const tokensOwed1 = feeGrowthInside1LastX128
    .div(new bn(2).pow(128));

You may need to divide further by the decimals of the underlying ERC20


For those looking for a worked out example. Run this query on thegraph.com:

  positions(where: {id:"YOURPOOLIDHERE"}) 
    token0 {symbol decimals}
    pool {feeGrowthGlobal0X128}
    tickLower {feeGrowthOutside0X128} #feeGrowthOutside0X128_lower
    tickUpper {feeGrowthOutside0X128} #feeGrowthOutside0X128_upper

Then, as @vlad.london described:

feetoken0 = ((feeGrowthGlobal0X128 - feeGrowthOutside0X128_lower - feeGrowthOutside0X128_upper - feeGrowthInside0LastX128)/(2**128))*liquidity/(1*10**decimals)
  • I checked with pool app.uniswap.org/#/pool/86957 and I don't get the correct fees using your formula. Am I missing something?
    – Sydney
    Sep 12 at 14:17
  • Did you by any chance Add Liquidity after the initial pool creation? Sep 15 at 4:10
  • I don't know because it's not my pool, but I guess the formula should work even if liquidity has been added.
    – Sydney
    Sep 15 at 6:02
  • formula works out for me! thanks @el3ctric'mp
    – jorijnsmit
    Nov 9 at 11:52
  • This formula only works if the current Pool price is within range.
    – James
    Nov 24 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.