如何计算Uniswap v3池的链上锁定总价值(TVL)?

发布于 2025-01-20 06:57:39 字数 470 浏览 4 评论 0原文

我想计算uniswap v3中特定池中锁定的总价值。我不能为此使用子图API。

我可以使用uniswapv3pool合同功能获得当前的流动性/范围流动性:

in_range_liquidity = uniswapV3pool_contract.functions.liquidity().call()

我获得结果10608850786221311055流动性。我需要处理它以获取美元价值或其他东西吗?

最后,这只是当前的流动性,我需要总锁定值,其中包括池中的活动和非活动流动性。

I want to calculate the total value locked in a particular pool in Uniswap v3. I can't use the subgraph API for this.

enter image description here

I can get current liquidity / in range liquidity using uniswapV3pool contract function:

in_range_liquidity = uniswapV3pool_contract.functions.liquidity().call()

I get the result 10608850786221311055 for liquidity. Do I need to process it to get the USD value or something else?

Finally this is just current liquidity, I need total locked value, which includes both active and inactive liquidity in the pool.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

末蓝 2025-01-27 06:57:39

锁定在UNISWAP的V3池中的总价值并不总是很简单。流动性本身并不是池中实际令牌数量的良好衡量。 UNISWAP V3流动性描述了虚拟令牌量的集中流动性价值,而不是实际金额。

作为最简单的选项,您可以通过在令牌合同上调用Balanceof函数来获取链上的金额:

balance0 = token0_contract.functions.balanceOf(pool_address).call()

此值还将包括无人认领的费用。在UNISWAP V3中,这些费用不是流动性的一部分。如果您想获得有助于流动性的令牌金额,则Balanceof呼叫不够。它为您提供了两种不同的链计算选项:

a)在所有流动性的所有tick范围内迭代。

b)在所有开放位置上迭代。

接下来的是一些实现方法(a)的快速且不优化的Python代码。它需要min_tickmax_ticktick_spacing,以及urlpool> pool_addressV3_ABI要定义。

from collections import namedtuple
from web3 import Web3

web3 = Web3(Web3.HTTPProvider(URL))
pool = Web3.toChecksumAddress(POOL_ADDRESS)
contract = web3.eth.contract(address=POOL_ADDRESS, abi=V3_ABI)

Tick = namedtuple("Tick", "liquidityGross liquidityNet feeGrowthOutside0X128 feeGrowthOutside1X128 tickCumulativeOutside secondsPerLiquidityOutsideX128 secondsOutside initialized")

amounts0 = 0
amounts1 = 0
liquidity = 0
slot0 = contract.functions.slot0().call()
sqrtPriceCurrent = slot0[0] / (1 << 96)

def calculate_token0_amount(liquidity, sp, sa, sb):
    sp = max(min(sp, sb), sa)
    return liquidity * (sb - sp) / (sp * sb)

def calculate_token1_amount(liquidity, sp, sa, sb):
    sp = max(min(sp, sb), sa)
    return liquidity * (sp - sa)

for tick in range(MIN_TICK, MAX_TICK, TICK_SPACING):
  tickRange = Tick(*contract.functions.ticks(tick).call())
  liquidity += tickRange.liquidityNet
  sqrtPriceLow = 1.0001 ** (tick // 2)
  sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
  amounts0 += calculate_token0_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)
  amounts1 += calculate_token1_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)

print(amounts0, amounts1) # for better output, should correct for the amount of decimals before printing

tick_spacing的值可以从池合同的tickspacing()函数中读取。一定地,如果您知道池的交换费水平,则可以使用一个常数:1%的游泳池始终具有200个,因为tick间距等


tickbitmap()呼叫,并分别查看最低和最高初始滴答。它非常复杂,更适合一个单独的问题。在最坏的情况下,如果您可能需要覆盖整个tick范围,范围介于-887272和+887272之间。因此,首先,您可以使用这些值舍入 /到刻度间距值。

编辑: 1.0001 ^ tick等于1.0001 ^(tick/2)的平方根,这一事实在这些行中使用来制作计算样品:

sqrtPriceLow = 1.0001 ** (tick // 2)
sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)

The total value locked in Uniswap's v3 pool is not always straightforward to get. The liquidity itself not a good measure of the real token amounts in the pool. Uniswap v3 liquidity describes the concentrated liquidity value of the virtual token amounts, not the real amounts.

As the simplest option, you can get the on-chain amounts by calling the balanceOf function on the token's contract:

balance0 = token0_contract.functions.balanceOf(pool_address).call()

This value is going to also include unclaimed fees. In Uniswap v3, these fees are not part of the liquidity. If you want to get the token amounts that contribute to liquidity, then the balanceOf call is not sufficient. It leaves you with two different options for on-chain calculations:

a) Iterate over all tick ranges with non-zero liquidity.

b) Iterate over all open positions.

What follows is some quick and unoptimized Python code that implements the approach (a). It needs MIN_TICK, MAX_TICK, TICK_SPACING, as well as URL, POOL_ADDRESS and V3_ABI to be defined.

from collections import namedtuple
from web3 import Web3

web3 = Web3(Web3.HTTPProvider(URL))
pool = Web3.toChecksumAddress(POOL_ADDRESS)
contract = web3.eth.contract(address=POOL_ADDRESS, abi=V3_ABI)

Tick = namedtuple("Tick", "liquidityGross liquidityNet feeGrowthOutside0X128 feeGrowthOutside1X128 tickCumulativeOutside secondsPerLiquidityOutsideX128 secondsOutside initialized")

amounts0 = 0
amounts1 = 0
liquidity = 0
slot0 = contract.functions.slot0().call()
sqrtPriceCurrent = slot0[0] / (1 << 96)

def calculate_token0_amount(liquidity, sp, sa, sb):
    sp = max(min(sp, sb), sa)
    return liquidity * (sb - sp) / (sp * sb)

def calculate_token1_amount(liquidity, sp, sa, sb):
    sp = max(min(sp, sb), sa)
    return liquidity * (sp - sa)

for tick in range(MIN_TICK, MAX_TICK, TICK_SPACING):
  tickRange = Tick(*contract.functions.ticks(tick).call())
  liquidity += tickRange.liquidityNet
  sqrtPriceLow = 1.0001 ** (tick // 2)
  sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
  amounts0 += calculate_token0_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)
  amounts1 += calculate_token1_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)

print(amounts0, amounts1) # for better output, should correct for the amount of decimals before printing

The value of TICK_SPACING can be read from the tickSpacing() function of the pool's contract. Alteratively, if you know swap fee levels of the pool, you can use a constant: 1% pools have always have 200 as the tick spacing, etc.

The values of MIN_TICK and MAX_TICK can be obtained from
tickBitmap() calls and looking at the lowest and the highest initialized tick respectively. It's quite complex and a better fit for a separate question. At the worst case if you may need to cover the whole tick range, which spans between -887272 and +887272. So for a start you can use these values rounded down / up to the tick spacing value.

Edit: the square root of 1.0001 ^ tick is equal to 1.0001 ^ (tick / 2), a fact that use in these lines to make the computation simples:

sqrtPriceLow = 1.0001 ** (tick // 2)
sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文