library Tick {
function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128) {
int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1;
return type(uint128).max / numTicks;
}
}
我们来看为何 uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1;
中要加1。
计算在最小和最大价格点之间有多少个价格点(numTicks),包括两端的价格点。
使用种树的例子来解释为什么在计算价格点(ticks)时需要加1,可以这样理解:
想象你有一个长直线的道路,你想要在路上种一排树。每棵树代表一个价格点,道路的两端也都要种上树。
-
确定范围:首先,确定你想种树的起点(
minTick
)和终点(maxTick
)。比如,起点是道路的一端,终点是另一端。 -
确定间隔:然后,决定两棵树之间间隔多远种一棵树,这个间隔就是
tickSpacing
。 -
计算间隔数:如果你想计算在起点和终点之间可以种多少个间隔,你会用总长度(
maxTick - minTick
)除以单个间隔的长度(tickSpacing
)。这就像计算道路可以容纳多少个树之间的空隙。 -
加1:但是,如果你只计算间隔数,你会漏掉终点的那棵树。因此,你需要加1,以确保包括起点和终点的树。这就是为什么计算价格点时需要加1的原因。
-
种树:当你种下第一棵树后,按照间隔距离种下第二棵,依此类推,直到你种下了最后一棵树在终点。
-
包括两端:加1确保了起点和终点的位置都被计算在内,就像种树时你希望道路的两端都有一棵树一样。
-
流动性比喻:在 Uniswap V3 的情况下,每棵树可以被看作是一个价格点,可以提供一定量的流动性。通过计算包括两端在内的总价格点数,你可以知道在给定的价格范围内可以分配多少个独立的流动性段。
-
均匀分配:最后,将一个非常大的流动性值(
type(uint128).max
)均匀分配到每个价格点上,这就像将一大片土地的水资源均匀分配给每棵树,确保它们都能获得所需的养分。
通过这个种树的例子,可以理解在计算价格区间内的数量时加1的重要性,这确保了区间的起点和终点都被包括在内,并且可以进行正确的资源分配。