//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface SlipStreamPool {
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function tickSpacing() external view returns (int24);
function liquidity() external view returns (uint128);
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
bool unlocked
);
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
int128 stakedLiquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
uint256 rewardGrowethOutsideX128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
}
interface IERC20 {
function decimals() external view returns (uint8);
}
contract SlipStreamDataSync {
struct PoolData {
address poolAddr;
address tokenA;
uint8 tokenADecimals;
address tokenB;
uint8 tokenBDecimals;
uint128 liquidity;
uint160 sqrtPrice;
int24 tick;
int24 tickSpacing;
uint24 fee;
int128 liquidityNet;
}
constructor(address[] memory pools) {
PoolData[] memory allPoolData = new PoolData[](pools.length);
for (uint256 i = 0; i < pools.length; ++i) {
address poolAddress = pools[i];
if (codeSizeIsZero(poolAddress)) continue;
PoolData memory poolData;
poolData.poolAddr = poolAddress;
SlipStreamPool pool = SlipStreamPool(poolAddress);
poolData.tokenA = pool.token0();
poolData.tokenB = pool.token1();
//Check that tokenA and tokenB do not have codesize of 0
if (codeSizeIsZero(poolData.tokenA)) continue;
if (codeSizeIsZero(poolData.tokenB)) continue;
//Get tokenA decimals
(
bool tokenADecimalsSuccess,
bytes memory tokenADecimalsData
) = poolData.tokenA.call{gas: 20000}(
abi.encodeWithSignature("decimals()")
);
if (tokenADecimalsSuccess) {
uint256 tokenADecimals;
if (tokenADecimalsData.length == 32) {
(tokenADecimals) = abi.decode(
tokenADecimalsData,
(uint256)
);
if (tokenADecimals == 0 || tokenADecimals > 255) {
continue;
} else {
poolData.tokenADecimals = uint8(tokenADecimals);
}
} else {
continue;
}
} else {
continue;
}
(
bool tokenBDecimalsSuccess,
bytes memory tokenBDecimalsData
) = poolData.tokenB.call{gas: 20000}(
abi.encodeWithSignature("decimals()")
);
if (tokenBDecimalsSuccess) {
uint256 tokenBDecimals;
if (tokenBDecimalsData.length == 32) {
(tokenBDecimals) = abi.decode(
tokenBDecimalsData,
(uint256)
);
if (tokenBDecimals == 0 || tokenBDecimals > 255) {
continue;
} else {
poolData.tokenBDecimals = uint8(tokenBDecimals);
}
} else {
continue;
}
} else {
continue;
}
(uint160 sqrtPriceX96, int24 tick , , , , ) = pool.slot0();
(, int128 liquidityNet, , , , , , , , ) = pool.ticks(tick);
poolData.liquidity = pool.liquidity();
poolData.tickSpacing = pool.tickSpacing();
poolData.fee = pool.fee();
poolData.sqrtPrice = sqrtPriceX96;
poolData.tick = tick;
poolData.liquidityNet = liquidityNet;
allPoolData[i] = poolData;
}
bytes memory _abiEncodedData = abi.encode(allPoolData);
assembly {
// Return from the start of the data (discarding the original data address)
// up to the end of the memory used
let dataStart := add(_abiEncodedData, 0x20)
return(dataStart, sub(msize(), dataStart))
}
}
function codeSizeIsZero(address target) internal view returns (bool) {
if (target.code.length == 0) {
return true;
} else {
return false;
}
}
}