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