github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/liquidity-scrapers/contract.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.0;
     3  
     4  import {PoolId} from "../types/PoolId.sol";
     5  import {IPoolManager} from "../interfaces/IPoolManager.sol";
     6  import {Position} from "./Position.sol";
     7  
     8  /// @notice A helper library to provide state getters that use extsload
     9  library StateLibrary {
    10      /// @notice index of pools mapping in the PoolManager
    11      bytes32 public constant POOLS_SLOT = bytes32(uint256(6));
    12  
    13      /// @notice index of feeGrowthGlobal0X128 in Pool.State
    14      uint256 public constant FEE_GROWTH_GLOBAL0_OFFSET = 1;
    15  
    16      // feeGrowthGlobal1X128 offset in Pool.State = 2
    17  
    18      /// @notice index of liquidity in Pool.State
    19      uint256 public constant LIQUIDITY_OFFSET = 3;
    20  
    21      /// @notice index of TicksInfo mapping in Pool.State: mapping(int24 => TickInfo) ticks;
    22      uint256 public constant TICKS_OFFSET = 4;
    23  
    24      /// @notice index of tickBitmap mapping in Pool.State
    25      uint256 public constant TICK_BITMAP_OFFSET = 5;
    26  
    27      /// @notice index of Position.State mapping in Pool.State: mapping(bytes32 => Position.State) positions;
    28      uint256 public constant POSITIONS_OFFSET = 6;
    29  
    30      /**
    31       * @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee
    32       * @dev Corresponds to pools[poolId].slot0
    33       * @param manager The pool manager contract.
    34       * @param poolId The ID of the pool.
    35       * @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision.
    36       * @return tick The current tick of the pool.
    37       * @return protocolFee The protocol fee of the pool.
    38       * @return lpFee The swap fee of the pool.
    39       */
    40      function getSlot0(IPoolManager manager, PoolId poolId)
    41          internal
    42          view
    43          returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)
    44      {
    45          // slot key of Pool.State value: `pools[poolId]`
    46          bytes32 stateSlot = _getPoolStateSlot(poolId);
    47  
    48          bytes32 data = manager.extsload(stateSlot);
    49  
    50          //   24 bits  |24bits|24bits      |24 bits|160 bits
    51          // 0x000000   |000bb8|000000      |ffff75 |0000000000000000fe3aa841ba359daa0ea9eff7
    52          // ---------- | fee  |protocolfee | tick  | sqrtPriceX96
    53          assembly ("memory-safe") {
    54              // bottom 160 bits of data
    55              sqrtPriceX96 := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
    56              // next 24 bits of data
    57              tick := signextend(2, shr(160, data))
    58              // next 24 bits of data
    59              protocolFee := and(shr(184, data), 0xFFFFFF)
    60              // last 24 bits of data
    61              lpFee := and(shr(208, data), 0xFFFFFF)
    62          }
    63      }
    64  
    65      /**
    66       * @notice Retrieves the tick information of a pool at a specific tick.
    67       * @dev Corresponds to pools[poolId].ticks[tick]
    68       * @param manager The pool manager contract.
    69       * @param poolId The ID of the pool.
    70       * @param tick The tick to retrieve information for.
    71       * @return liquidityGross The total position liquidity that references this tick
    72       * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left)
    73       * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
    74       * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
    75       */
    76      function getTickInfo(IPoolManager manager, PoolId poolId, int24 tick)
    77          internal
    78          view
    79          returns (
    80              uint128 liquidityGross,
    81              int128 liquidityNet,
    82              uint256 feeGrowthOutside0X128,
    83              uint256 feeGrowthOutside1X128
    84          )
    85      {
    86          bytes32 slot = _getTickInfoSlot(poolId, tick);
    87  
    88          // read all 3 words of the TickInfo struct
    89          bytes32[] memory data = manager.extsload(slot, 3);
    90          assembly ("memory-safe") {
    91              let firstWord := mload(add(data, 32))
    92              liquidityNet := sar(128, firstWord)
    93              liquidityGross := and(firstWord, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
    94              feeGrowthOutside0X128 := mload(add(data, 64))
    95              feeGrowthOutside1X128 := mload(add(data, 96))
    96          }
    97      }
    98  
    99      /**
   100       * @notice Retrieves the liquidity information of a pool at a specific tick.
   101       * @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo
   102       * @param manager The pool manager contract.
   103       * @param poolId The ID of the pool.
   104       * @param tick The tick to retrieve liquidity for.
   105       * @return liquidityGross The total position liquidity that references this tick
   106       * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left)
   107       */
   108      function getTickLiquidity(IPoolManager manager, PoolId poolId, int24 tick)
   109          internal
   110          view
   111          returns (uint128 liquidityGross, int128 liquidityNet)
   112      {
   113          bytes32 slot = _getTickInfoSlot(poolId, tick);
   114  
   115          bytes32 value = manager.extsload(slot);
   116          assembly ("memory-safe") {
   117              liquidityNet := sar(128, value)
   118              liquidityGross := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
   119          }
   120      }
   121  
   122      /**
   123       * @notice Retrieves total the liquidity of a pool.
   124       * @dev Corresponds to pools[poolId].liquidity
   125       * @param manager The pool manager contract.
   126       * @param poolId The ID of the pool.
   127       * @return liquidity The liquidity of the pool.
   128       */
   129      function getLiquidity(IPoolManager manager, PoolId poolId) internal view returns (uint128 liquidity) {
   130          // slot key of Pool.State value: `pools[poolId]`
   131          bytes32 stateSlot = _getPoolStateSlot(poolId);
   132  
   133          // Pool.State: `uint128 liquidity`
   134          bytes32 slot = bytes32(uint256(stateSlot) + LIQUIDITY_OFFSET);
   135  
   136          liquidity = uint128(uint256(manager.extsload(slot)));
   137      }
   138  
   139      /**
   140       * @notice Retrieves the tick bitmap of a pool at a specific tick.
   141       * @dev Corresponds to pools[poolId].tickBitmap[tick]
   142       * @param manager The pool manager contract.
   143       * @param poolId The ID of the pool.
   144       * @param tick The tick to retrieve the bitmap for.
   145       * @return tickBitmap The bitmap of the tick.
   146       */
   147      function getTickBitmap(IPoolManager manager, PoolId poolId, int16 tick)
   148          internal
   149          view
   150          returns (uint256 tickBitmap)
   151      {
   152          // slot key of Pool.State value: `pools[poolId]`
   153          bytes32 stateSlot = _getPoolStateSlot(poolId);
   154  
   155          // Pool.State: `mapping(int16 => uint256) tickBitmap;`
   156          bytes32 tickBitmapMapping = bytes32(uint256(stateSlot) + TICK_BITMAP_OFFSET);
   157  
   158          // slot id of the mapping key: `pools[poolId].tickBitmap[tick]
   159          bytes32 slot = keccak256(abi.encodePacked(int256(tick), tickBitmapMapping));
   160  
   161          tickBitmap = uint256(manager.extsload(slot));
   162      }
   163  
   164  
   165      function _getPoolStateSlot(PoolId poolId) internal pure returns (bytes32) {
   166          return keccak256(abi.encodePacked(PoolId.unwrap(poolId), POOLS_SLOT));
   167      }
   168  
   169      function _getTickInfoSlot(PoolId poolId, int24 tick) internal pure returns (bytes32) {
   170          // slot key of Pool.State value: `pools[poolId]`
   171          bytes32 stateSlot = _getPoolStateSlot(poolId);
   172  
   173          // Pool.State: `mapping(int24 => TickInfo) ticks`
   174          bytes32 ticksMappingSlot = bytes32(uint256(stateSlot) + TICKS_OFFSET);
   175  
   176          // slot key of the tick key: `pools[poolId].ticks[tick]
   177          return keccak256(abi.encodePacked(int256(tick), ticksMappingSlot));
   178      }
   179