// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.7.6; library Tick { struct GrowthInfo { uint256 feeX128; int256 twPremiumX96; int256 twPremiumDivBySqrtPriceX96; } struct FundingGrowthRangeInfo { int256 twPremiumGrowthInsideX96; int256 twPremiumGrowthBelowX96; int256 twPremiumDivBySqrtPriceGrowthInsideX96; } /// @dev call this function only if (liquidityGrossBefore == 0 && liquidityDelta != 0) /// @dev per Uniswap: we assume that all growths before a tick is initialized happen "below" the tick function initialize( mapping(int24 => GrowthInfo) storage self, int24 tick, int24 currentTick, GrowthInfo memory globalGrowthInfo ) internal { if (tick <= currentTick) { GrowthInfo storage growthInfo = self[tick]; growthInfo.feeX128 = globalGrowthInfo.feeX128; growthInfo.twPremiumX96 = globalGrowthInfo.twPremiumX96; growthInfo.twPremiumDivBySqrtPriceX96 = globalGrowthInfo.twPremiumDivBySqrtPriceX96; } } function cross( mapping(int24 => GrowthInfo) storage self, int24 tick, GrowthInfo memory globalGrowthInfo ) internal { GrowthInfo storage growthInfo = self[tick]; growthInfo.feeX128 = globalGrowthInfo.feeX128 - growthInfo.feeX128; growthInfo.twPremiumX96 = globalGrowthInfo.twPremiumX96 - growthInfo.twPremiumX96; growthInfo.twPremiumDivBySqrtPriceX96 = globalGrowthInfo.twPremiumDivBySqrtPriceX96 - growthInfo.twPremiumDivBySqrtPriceX96; } function clear(mapping(int24 => GrowthInfo) storage self, int24 tick) internal { delete self[tick]; } /// @dev all values in this function are scaled by 2^128 (X128), thus adding the suffix to external params /// @return feeGrowthInsideX128 this value can underflow per Tick.feeGrowthOutside specs function getFeeGrowthInsideX128( mapping(int24 => GrowthInfo) storage self, int24 lowerTick, int24 upperTick, int24 currentTick, uint256 feeGrowthGlobalX128 ) internal view returns (uint256 feeGrowthInsideX128) { uint256 lowerFeeGrowthOutside = self[lowerTick].feeX128; uint256 upperFeeGrowthOutside = self[upperTick].feeX128; uint256 feeGrowthBelow = currentTick >= lowerTick ? lowerFeeGrowthOutside : feeGrowthGlobalX128 - lowerFeeGrowthOutside; uint256 feeGrowthAbove = currentTick < upperTick ? upperFeeGrowthOutside : feeGrowthGlobalX128 - upperFeeGrowthOutside; return feeGrowthGlobalX128 - feeGrowthBelow - feeGrowthAbove; } /// @return all values returned can underflow per feeGrowthOutside specs; /// see https://www.notion.so/32990980ba8b43859f6d2541722a739b function getAllFundingGrowth( mapping(int24 => GrowthInfo) storage self, int24 lowerTick, int24 upperTick, int24 currentTick, int256 twPremiumGrowthGlobalX96, int256 twPremiumDivBySqrtPriceGrowthGlobalX96 ) internal view returns (FundingGrowthRangeInfo memory) { GrowthInfo storage lowerTickGrowthInfo = self[lowerTick]; GrowthInfo storage upperTickGrowthInfo = self[upperTick]; int256 lowerTwPremiumGrowthOutsideX96 = lowerTickGrowthInfo.twPremiumX96; int256 upperTwPremiumGrowthOutsideX96 = upperTickGrowthInfo.twPremiumX96; FundingGrowthRangeInfo memory fundingGrowthRangeInfo; fundingGrowthRangeInfo.twPremiumGrowthBelowX96 = currentTick >= lowerTick ? lowerTwPremiumGrowthOutsideX96 : twPremiumGrowthGlobalX96 - lowerTwPremiumGrowthOutsideX96; int256 twPremiumGrowthAboveX96 = currentTick < upperTick ? upperTwPremiumGrowthOutsideX96 : twPremiumGrowthGlobalX96 - upperTwPremiumGrowthOutsideX96; int256 lowerTwPremiumDivBySqrtPriceGrowthOutsideX96 = lowerTickGrowthInfo.twPremiumDivBySqrtPriceX96; int256 upperTwPremiumDivBySqrtPriceGrowthOutsideX96 = upperTickGrowthInfo.twPremiumDivBySqrtPriceX96; int256 twPremiumDivBySqrtPriceGrowthBelowX96 = currentTick >= lowerTick ? lowerTwPremiumDivBySqrtPriceGrowthOutsideX96 : twPremiumDivBySqrtPriceGrowthGlobalX96 - lowerTwPremiumDivBySqrtPriceGrowthOutsideX96; int256 twPremiumDivBySqrtPriceGrowthAboveX96 = currentTick < upperTick ? upperTwPremiumDivBySqrtPriceGrowthOutsideX96 : twPremiumDivBySqrtPriceGrowthGlobalX96 - upperTwPremiumDivBySqrtPriceGrowthOutsideX96; fundingGrowthRangeInfo.twPremiumGrowthInsideX96 = twPremiumGrowthGlobalX96 - fundingGrowthRangeInfo.twPremiumGrowthBelowX96 - twPremiumGrowthAboveX96; fundingGrowthRangeInfo.twPremiumDivBySqrtPriceGrowthInsideX96 = twPremiumDivBySqrtPriceGrowthGlobalX96 - twPremiumDivBySqrtPriceGrowthBelowX96 - twPremiumDivBySqrtPriceGrowthAboveX96; return fundingGrowthRangeInfo; } }