Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
src = "src"
out = "out"
libs = ["lib"]
test = "test"
optimizer = true
optimizer_runs = 200

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
35 changes: 27 additions & 8 deletions script/Quote.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,48 @@ contract Deploy is Test {
// base
// address stateView = 0xA3c0c9b65baD0b08107Aa264b0f3dB444b867A71;
// address positionManager = 0x7C5f5A4bBd8fD63184577525326123B519429bDc;
// address pancakeInfinityCLPoolManager = 0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b;
// address pancakeInfinityPositionManager = 0x55f4c8abA71A1e923edC303eb4fEfF14608cC226;
// eth
// address stateView = 0x7fFE42C4a5DEeA5b0feC41C94C136Cf115597227;
// address positionManager = 0xbD216513d74C8cf14cf4747E6AaA6420FF64ee9e;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// Arbitrum
// address stateView = 0x76Fd297e2D437cd7f76d50F01AfE6160f86e9990;
// address positionManager = 0xd88F38F930b7952f2DB2432Cb002E7abbF3dD869;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// Optimism
// address stateView = 0xc18a3169788F4F75A170290584ECA6395C75Ecdb;
// address positionManager = 0x3C3Ea4B57a46241e54610e5f022E5c45859A1017;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// Polygon
// address stateView = 0x5eA1bD7974c8A611cBAB0bDCAFcB1D9CC9b3BA5a;
// address positionManager = 0x1Ec2eBf4F37E7363FDfe3551602425af0B3ceef9;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// Blast
// address stateView = 0x12a88AE16F46DCe4e8B15368008Ab3380885df30;
// address positionManager = 0x4AD2F4CcA2682cBB5B950d660dD458a1D3f1bAaD;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// Avalanche
// address stateView = 0xc3c9e198C735a4b97e3e683f391cCBDD60B69286;
// address positionManager = 0xB74b1F14d2754AcfcbBe1a221023a5cf50Ab8ACD;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;
// BNB Smart Chain
// address stateView = 0xd13Dd3D6E93f276FAfc9Db9E6BB47C1180aeE0c4;
// address positionManager = 0x7A4a5c919aE2541AeD11041A1AEeE68f1287f95b;
address stateView = 0xd13Dd3D6E93f276FAfc9Db9E6BB47C1180aeE0c4;
address positionManager = 0x7A4a5c919aE2541AeD11041A1AEeE68f1287f95b;
address pancakeInfinityCLPoolManager = 0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b;
address pancakeInfinityPositionManager = 0x55f4c8abA71A1e923edC303eb4fEfF14608cC226;
// UniChain
address stateView = 0x86e8631A016F9068C3f085fAF484Ee3F5fDee8f2;
address positionManager = 0x4529A01c7A0410167c5740C487A8DE60232617bf;
// address stateView = 0x86e8631A016F9068C3f085fAF484Ee3F5fDee8f2;
// address positionManager = 0x4529A01c7A0410167c5740C487A8DE60232617bf;
// address pancakeInfinityCLPoolManager = 0x0000000000000000000000000000000000000000;
// address pancakeInfinityPositionManager = 0x0000000000000000000000000000000000000000;

function run() public {
// base
Expand All @@ -51,13 +69,14 @@ contract Deploy is Test {
// Avalanche
// vm.createSelectFork(vm.envString("AVAX_RPC_URL"));
// BNB Smart Chain
// vm.createSelectFork("https://binance.llamarpc.com");
vm.createSelectFork("https://binance.llamarpc.com");
// unichain
vm.createSelectFork("https://mainnet.unichain.org");
// vm.createSelectFork("https://mainnet.unichain.org");

vm.startBroadcast(deployer);
require(block.chainid == 130, "must be right chain");
quoter = new QueryData(stateView, positionManager);
require(block.chainid == 56, "must be right chain");
// For Unichain deployment, Pancake Infinity addresses are not needed (set to 0)
quoter = new QueryData(stateView, positionManager, pancakeInfinityCLPoolManager, pancakeInfinityPositionManager);
console2.log("query address", address(quoter));
vm.stopBroadcast();
}
Expand Down
156 changes: 155 additions & 1 deletion src/Quote.sol
Original file line number Diff line number Diff line change
Expand Up @@ -341,20 +341,63 @@ interface IPositionManager {

interface IHooks {}

interface ICLPoolManager {
type PoolId is bytes32;

/// @notice Get the tick info about a specific tick in the pool
function getPoolTickInfo(PoolId id, int24 tick) external view returns (Tick.Info memory);

/// @notice Get the tick bitmap info about a specific range (a word range) in the pool
function getPoolBitmapInfo(PoolId id, int16 word) external view returns (uint256 tickBitmap);

/// @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee
function getSlot0(PoolId id)
external
view
returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee);
}

/// @notice Tick info library for Pancake Infinity
library Tick {
struct Info {
uint128 liquidityGross;
int128 liquidityNet;
uint256 feeGrowthOutside0X128;
uint256 feeGrowthOutside1X128;
}
}

/// @notice Pool parameters helper for extracting tickSpacing
library CLPoolParametersHelper {
uint256 internal constant OFFSET_TICK_SPACING = 16;

function getTickSpacing(bytes32 params) internal pure returns (int24 tickSpacing) {
assembly {
tickSpacing := and(shr(OFFSET_TICK_SPACING, params), 0xffffff)
}
}
}

/// @title DexNativeRouter
/// @notice Entrance of trading native token in web3-dex
contract QueryData {
int24 internal constant MIN_TICK_MINUS_1 = -887_272 - 1;
int24 internal constant MAX_TICK_PLUS_1 = 887_272 + 1;
address public immutable STATE_VIEW;
address public immutable POSITION_MANAGER;
address public immutable PANCAKE_INFINITY_CLPOOLMANAGER;
address public immutable PANCAKE_INFINITY_POSITION_MANAGER;

constructor (
address stateView,
address positionManager
address positionManager,
address pancakeInfinityCLPoolManager,
address pancakeInfinityPositionManager
) {
STATE_VIEW = stateView;
POSITION_MANAGER = positionManager;
PANCAKE_INFINITY_CLPOOLMANAGER = pancakeInfinityCLPoolManager;
PANCAKE_INFINITY_POSITION_MANAGER = pancakeInfinityPositionManager;
}

type Currency is address;
Expand Down Expand Up @@ -1102,4 +1145,115 @@ contract QueryData {
}
return tickInfo;
}

function queryPancakeInfinityTicksSuperCompact(bytes32 poolId, uint256 len)
public
view
returns (bytes memory)
{
SuperVar memory tmp;

// 从 PANCAKE_INFINITY_POSITION_MANAGER 获取 poolKey 中的 parameters 来提取 tickSpacing
{
(, bytes memory result) = PANCAKE_INFINITY_POSITION_MANAGER.staticcall(
abi.encodeWithSignature("poolKeys(bytes25)", bytes25(poolId))
);
bytes32 parameters;
assembly {
// Skip currency0 (32), currency1 (32), hooks (32), poolManager (32), fee (32)
// Parameters is at offset 160 (32 * 5)
parameters := mload(add(result, 192))
}
tmp.tickSpacing = CLPoolParametersHelper.getTickSpacing(parameters);
}

ICLPoolManager.PoolId clPoolId = ICLPoolManager.PoolId.wrap(poolId);

// 读取 slot0 结构中的当前 tick
{
(, int24 tick, , ) = ICLPoolManager(PANCAKE_INFINITY_CLPOOLMANAGER).getSlot0(clPoolId);
tmp.currTick = tick;
}

tmp.right = tmp.currTick / tmp.tickSpacing / int24(256);
tmp.leftMost = -887_272 / tmp.tickSpacing / int24(256) - 2;
tmp.rightMost = 887_272 / tmp.tickSpacing / int24(256) + 1;

if (tmp.currTick < 0) {
tmp.initPoint =
uint256(
int256(tmp.currTick) /
int256(tmp.tickSpacing) -
(int256(tmp.currTick) / int256(tmp.tickSpacing) / 256 - 1) *
256
) %
256;
} else {
tmp.initPoint = (uint256(int256(tmp.currTick)) / uint256(int256(tmp.tickSpacing))) % 256;
}
tmp.initPoint2 = tmp.initPoint;

if (tmp.currTick < 0) tmp.right--;

bytes memory tickInfo;
tmp.left = tmp.right;

uint256 index = 0;

while (index < len / 2 && tmp.right < tmp.rightMost) {
uint256 res = ICLPoolManager(PANCAKE_INFINITY_CLPOOLMANAGER).getPoolBitmapInfo(clPoolId, int16(tmp.right));
if (res > 0) {
res = res >> tmp.initPoint;
for (uint256 i = tmp.initPoint; i < 256 && index < len / 2; i++) {
uint256 isInit = res & 0x01;
if (isInit > 0) {
int256 tick = int256((256 * tmp.right + int256(i)) * tmp.tickSpacing);

Tick.Info memory tickInfo_ = ICLPoolManager(PANCAKE_INFINITY_CLPOOLMANAGER).getPoolTickInfo(clPoolId, int24(int256(tick)));
int128 liquidityNet = tickInfo_.liquidityNet;

int256 data = int256(uint256(int256(tick)) << 128) +
(int256(liquidityNet) & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff);
tickInfo = bytes.concat(tickInfo, bytes32(uint256(data)));

index++;
}

res = res >> 1;
}
}
tmp.initPoint = 0;
tmp.right++;
}

bool isInitPoint = true;
while (index < len && tmp.left > tmp.leftMost) {
uint256 res = ICLPoolManager(PANCAKE_INFINITY_CLPOOLMANAGER).getPoolBitmapInfo(clPoolId, int16(tmp.left));
if (res > 0 && tmp.initPoint2 != 0) {
res = isInitPoint ? res << ((256 - tmp.initPoint2) % 256) : res;
for (uint256 i = tmp.initPoint2 - 1; i >= 0 && index < len; i--) {
uint256 isInit = res & 0x8000000000000000000000000000000000000000000000000000000000000000;
if (isInit > 0) {
int256 tick = int256((256 * tmp.left + int256(i)) * tmp.tickSpacing);

Tick.Info memory tickInfo_ = ICLPoolManager(PANCAKE_INFINITY_CLPOOLMANAGER).getPoolTickInfo(clPoolId, int24(int256(tick)));
int128 liquidityNet = tickInfo_.liquidityNet;

int256 data = int256(uint256(int256(tick)) << 128) +
(int256(liquidityNet) & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff);
tickInfo = bytes.concat(tickInfo, bytes32(uint256(data)));

index++;
}

res = res << 1;
if (i == 0) break;
}
}
isInitPoint = false;
tmp.initPoint2 = 256;
tmp.left--;
}
return tickInfo;
}
}
Loading
Loading