Skip to content

Commit

Permalink
refactor v4 -> infi from migrator
Browse files Browse the repository at this point in the history
  • Loading branch information
ChefMist committed Jan 28, 2025
1 parent 7e40dee commit edcf1fb
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 254 deletions.
32 changes: 16 additions & 16 deletions src/MixedQuoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,11 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {
amountIn = swapAmountOut - accAmountOut;
}
} else if (action == MixedQuoterActions.INFI_CL_EXACT_INPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory clParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactInputSingleParams));
(tokenIn, tokenOut) = convertWETHToV4NativeCurency(clParams.poolKey, tokenIn, tokenOut);
QuoteMixedInfiExactInputSingleParams memory clParams =
abi.decode(params[actionIndex], (QuoteMixedInfiExactInputSingleParams));
(tokenIn, tokenOut) = convertWETHToInfiNativeCurency(clParams.poolKey, tokenIn, tokenOut);
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(clParams.poolKey, zeroForOne, tokenIn, tokenOut);
checkInfiPoolKeyCurrency(clParams.poolKey, zeroForOne, tokenIn, tokenOut);

IQuoter.QuoteExactSingleParams memory swapParams = IQuoter.QuoteExactSingleParams({
poolKey: clParams.poolKey,
Expand All @@ -317,8 +317,8 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {
});
// will execute all swap history of same infinity pool in one transaction if withContext is true
if (withContext) {
bytes32 poolHash = MixedQuoterRecorder.getV4CLPoolHash(clParams.poolKey);
bytes memory swapListBytes = MixedQuoterRecorder.getV4PoolSwapList(poolHash);
bytes32 poolHash = MixedQuoterRecorder.getInfiCLPoolHash(clParams.poolKey);
bytes memory swapListBytes = MixedQuoterRecorder.getInfiPoolSwapList(poolHash);
IQuoter.QuoteExactSingleParams[] memory swapHistoryList;
uint256 swapHistoryListLength;
if (swapListBytes.length > 0) {
Expand All @@ -335,16 +335,16 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {

(amountIn, gasEstimateForCurAction) = clQuoter.quoteExactInputSingleList(swapList);
swapListBytes = abi.encode(swapList);
MixedQuoterRecorder.setV4PoolSwapList(poolHash, swapListBytes);
MixedQuoterRecorder.setInfiPoolSwapList(poolHash, swapListBytes);
} else {
(amountIn, gasEstimateForCurAction) = clQuoter.quoteExactInputSingle(swapParams);
}
} else if (action == MixedQuoterActions.INFI_BIN_EXACT_INPUT_SINGLE) {
QuoteMixedV4ExactInputSingleParams memory binParams =
abi.decode(params[actionIndex], (QuoteMixedV4ExactInputSingleParams));
(tokenIn, tokenOut) = convertWETHToV4NativeCurency(binParams.poolKey, tokenIn, tokenOut);
QuoteMixedInfiExactInputSingleParams memory binParams =
abi.decode(params[actionIndex], (QuoteMixedInfiExactInputSingleParams));
(tokenIn, tokenOut) = convertWETHToInfiNativeCurency(binParams.poolKey, tokenIn, tokenOut);
bool zeroForOne = tokenIn < tokenOut;
checkV4PoolKeyCurrency(binParams.poolKey, zeroForOne, tokenIn, tokenOut);
checkInfiPoolKeyCurrency(binParams.poolKey, zeroForOne, tokenIn, tokenOut);

IQuoter.QuoteExactSingleParams memory swapParams = IQuoter.QuoteExactSingleParams({
poolKey: binParams.poolKey,
Expand All @@ -354,8 +354,8 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {
});
// will execute all swap history of same infinity pool in one transaction if withContext is true
if (withContext) {
bytes32 poolHash = MixedQuoterRecorder.getV4BinPoolHash(binParams.poolKey);
bytes memory swapListBytes = MixedQuoterRecorder.getV4PoolSwapList(poolHash);
bytes32 poolHash = MixedQuoterRecorder.getInfiBinPoolHash(binParams.poolKey);
bytes memory swapListBytes = MixedQuoterRecorder.getInfiPoolSwapList(poolHash);
IQuoter.QuoteExactSingleParams[] memory swapHistoryList;
uint256 swapHistoryListLength;
if (swapListBytes.length > 0) {
Expand All @@ -372,7 +372,7 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {

(amountIn, gasEstimateForCurAction) = binQuoter.quoteExactInputSingleList(swapList);
swapListBytes = abi.encode(swapList);
MixedQuoterRecorder.setV4PoolSwapList(poolHash, swapListBytes);
MixedQuoterRecorder.setInfiPoolSwapList(poolHash, swapListBytes);
} else {
(amountIn, gasEstimateForCurAction) = binQuoter.quoteExactInputSingle(swapParams);
}
Expand Down Expand Up @@ -431,7 +431,7 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {
}

/// @dev Check if the poolKey currency matches the tokenIn and tokenOut
function checkV4PoolKeyCurrency(PoolKey memory poolKey, bool isZeroForOne, address tokenIn, address tokenOut)
function checkInfiPoolKeyCurrency(PoolKey memory poolKey, bool isZeroForOne, address tokenIn, address tokenOut)
private
pure
{
Expand All @@ -452,7 +452,7 @@ contract MixedQuoter is IMixedQuoter, IPancakeV3SwapCallback, Multicall {
/// @notice Convert WETH to native currency for infinity pools
/// @dev for example, quote route are v3 WETH pool[token0, WETH] and infinity native pool[NATIVE,token1]
/// paths is [token0, WETH, token1], we need to convert WETH to NATIVE when quote infinity pool
function convertWETHToV4NativeCurency(PoolKey memory poolKey, address tokenIn, address tokenOut)
function convertWETHToInfiNativeCurency(PoolKey memory poolKey, address tokenIn, address tokenOut)
private
view
returns (address, address)
Expand Down
18 changes: 9 additions & 9 deletions src/base/BaseMigrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,29 +186,29 @@ contract BaseMigrator is IBaseMigrator, Permit2Forwarder, Multicall, SelfPermitE
/// Return true if match but v2v3Token1 is WETH which should be ETH in infinity pair
/// @param v2v3Token0 token0 from v2/v3 pair
/// @param v2v3Token1 token1 from v2/v3 pair
/// @param v4Token0 token0 from infinity pair
/// @param v4Token1 token1 from infinity pair
/// @param infiToken0 token0 from infinity pair
/// @param infiToken1 token1 from infinity pair
/// @return shouldReversePair if the order of tokens from v2/v3 pair is different from infinity pair (only when WETH is involved)
function _checkIfTokenPairMatchAndOrder(
address v2v3Token0,
address v2v3Token1,
Currency v4Token0,
Currency v4Token1
Currency infiToken0,
Currency infiToken1
) private view returns (bool shouldReversePair) {
if (v4Token0.isNative() && v2v3Token0 == WETH9) {
if (Currency.unwrap(v4Token1) != v2v3Token1) {
if (infiToken0.isNative() && v2v3Token0 == WETH9) {
if (Currency.unwrap(infiToken1) != v2v3Token1) {
revert TOKEN_NOT_MATCH();
}
} else if (v4Token0.isNative() && v2v3Token1 == WETH9) {
if (Currency.unwrap(v4Token1) != v2v3Token0) {
} else if (infiToken0.isNative() && v2v3Token1 == WETH9) {
if (Currency.unwrap(infiToken1) != v2v3Token0) {
revert TOKEN_NOT_MATCH();
}
shouldReversePair = true;
} else {
/// @dev the order of token0 and token1 is always sorted
/// v2: https://github.com/pancakeswap/pancake-swap-core-v2/blob/38aad83854a46a82ea0e31988ff3cddb2bffb71a/contracts/PancakeFactory.sol#L27
/// v3: https://github.com/pancakeswap/pancake-v3-contracts/blob/5cc479f0c5a98966c74d94700057b8c3ca629afd/projects/v3-core/contracts/PancakeV3Factory.sol#L66
if (Currency.unwrap(v4Token0) != v2v3Token0 || Currency.unwrap(v4Token1) != v2v3Token1) {
if (Currency.unwrap(infiToken0) != v2v3Token0 || Currency.unwrap(infiToken1) != v2v3Token1) {
revert TOKEN_NOT_MATCH();
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/interfaces/IMixedQuoter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface IMixedQuoter {
error NoActions();
error UnsupportedAction(uint256 action);

struct QuoteMixedV4ExactInputSingleParams {
struct QuoteMixedInfiExactInputSingleParams {
PoolKey poolKey;
bytes hookData;
}
Expand Down Expand Up @@ -50,8 +50,8 @@ interface IMixedQuoter {
/// SS_3_EXACT_INPUT_SINGLE params are zero bytes
/// V2_EXACT_INPUT_SINGLE params are zero bytes
/// V3_EXACT_INPUT_SINGLE params are encoded as `uint24 fee`
/// INFI_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// INFI_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedInfiExactInputSingleParams`
/// INFI_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedInfiExactInputSingleParams`
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
/// @return gasEstimate The estimate of the gas that the swap consumes
Expand All @@ -71,8 +71,8 @@ interface IMixedQuoter {
/// SS_3_EXACT_INPUT_SINGLE params are zero bytes
/// V2_EXACT_INPUT_SINGLE params are zero bytes
/// V3_EXACT_INPUT_SINGLE params are encoded as `uint24 fee`
/// INFI_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// V4_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedV4ExactInputSingleParams`
/// INFI_CL_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedInfiExactInputSingleParams`
/// INFI_EXACT_INPUT_SINGLE params are encoded as `QuoteMixedInfiExactInputSingleParams`
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
/// @return gasEstimate The estimate of the gas that the swap consumes
Expand Down
8 changes: 4 additions & 4 deletions src/libraries/MixedQuoterRecorder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ library MixedQuoterRecorder {
/// @dev Record the swap history list of infinity pool.
/// @param poolHash The hash of the pool.
/// @param swapListBytes The swap history list bytes.
function setV4PoolSwapList(bytes32 poolHash, bytes memory swapListBytes) internal {
function setInfiPoolSwapList(bytes32 poolHash, bytes memory swapListBytes) internal {
uint256 swapListSlot = uint256(keccak256(abi.encode(poolHash, SWAP_V4_LIST)));
assembly ("memory-safe") {
// save the length of the bytes
Expand All @@ -142,7 +142,7 @@ library MixedQuoterRecorder {
/// @dev Get the swap history list of infinity pool.
/// @param poolHash The hash of the pool.
/// @return swapListBytes The swap history list bytes.
function getV4PoolSwapList(bytes32 poolHash) internal view returns (bytes memory swapListBytes) {
function getInfiPoolSwapList(bytes32 poolHash) internal view returns (bytes memory swapListBytes) {
uint256 swapListSlot = uint256(keccak256(abi.encode(poolHash, SWAP_V4_LIST)));
assembly ("memory-safe") {
// get the length of the bytes
Expand Down Expand Up @@ -190,14 +190,14 @@ library MixedQuoterRecorder {
/// @dev Get the infinity cl pool hash.
/// @param key The pool key.
/// @return poolHash The hash of the pool.
function getV4CLPoolHash(PoolKey memory key) internal pure returns (bytes32) {
function getInfiCLPoolHash(PoolKey memory key) internal pure returns (bytes32) {
return keccak256(abi.encode(key, SWAP_V4_CL));
}

/// @dev Get the infinity bin pool hash.
/// @param key The pool key.
/// @return poolHash The hash of the pool.
function getV4BinPoolHash(PoolKey memory key) internal pure returns (bytes32) {
function getInfiBinPoolHash(PoolKey memory key) internal pure returns (bytes32) {
return keccak256(abi.encode(key, SWAP_V4_BIN));
}
}
64 changes: 32 additions & 32 deletions src/pool-bin/BinMigrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,94 +27,94 @@ contract BinMigrator is IBinMigrator, BaseMigrator, ReentrancyLock {
/// @inheritdoc IBinMigrator
function migrateFromV2(
V2PoolParams calldata v2PoolParams,
V4BinPoolParams calldata v4PoolParams,
InfiBinPoolParams calldata infiPoolParams,
uint256 extraAmount0,
uint256 extraAmount1
) external payable override isNotLocked whenNotPaused {
bool shouldReversePair = checkTokensOrderAndMatchFromV2(
v2PoolParams.pair, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1
v2PoolParams.pair, infiPoolParams.poolKey.currency0, infiPoolParams.poolKey.currency1
);
(uint256 amount0Received, uint256 amount1Received) = withdrawLiquidityFromV2(v2PoolParams, shouldReversePair);

/// @notice if user mannually specify the price range, they might need to send extra token
batchAndNormalizeTokens(
v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1, extraAmount0, extraAmount1
infiPoolParams.poolKey.currency0, infiPoolParams.poolKey.currency1, extraAmount0, extraAmount1
);

uint256 amount0Input = amount0Received + extraAmount0;
uint256 amount1Input = amount1Received + extraAmount1;
IBinPositionManager.BinAddLiquidityParams memory addLiquidityParams = IBinPositionManager.BinAddLiquidityParams({
poolKey: v4PoolParams.poolKey,
poolKey: infiPoolParams.poolKey,
amount0: amount0Input.toUint128(),
amount1: amount1Input.toUint128(),
amount0Max: v4PoolParams.amount0Max,
amount1Max: v4PoolParams.amount1Max,
activeIdDesired: v4PoolParams.activeIdDesired,
idSlippage: v4PoolParams.idSlippage,
deltaIds: v4PoolParams.deltaIds,
distributionX: v4PoolParams.distributionX,
distributionY: v4PoolParams.distributionY,
to: v4PoolParams.to,
hookData: v4PoolParams.hookData
amount0Max: infiPoolParams.amount0Max,
amount1Max: infiPoolParams.amount1Max,
activeIdDesired: infiPoolParams.activeIdDesired,
idSlippage: infiPoolParams.idSlippage,
deltaIds: infiPoolParams.deltaIds,
distributionX: infiPoolParams.distributionX,
distributionY: infiPoolParams.distributionY,
to: infiPoolParams.to,
hookData: infiPoolParams.hookData
});

(uint256 amount0Consumed, uint256 amount1Consumed) =
_addLiquidityToTargetPool(addLiquidityParams, v4PoolParams.deadline);
_addLiquidityToTargetPool(addLiquidityParams, infiPoolParams.deadline);

// refund if necessary, ETH is supported by CurrencyLib
unchecked {
if (amount0Input > amount0Consumed) {
v4PoolParams.poolKey.currency0.transfer(v4PoolParams.to, amount0Input - amount0Consumed);
infiPoolParams.poolKey.currency0.transfer(infiPoolParams.to, amount0Input - amount0Consumed);
}
if (amount1Input > amount1Consumed) {
v4PoolParams.poolKey.currency1.transfer(v4PoolParams.to, amount1Input - amount1Consumed);
infiPoolParams.poolKey.currency1.transfer(infiPoolParams.to, amount1Input - amount1Consumed);
}
}
}

/// @inheritdoc IBinMigrator
function migrateFromV3(
V3PoolParams calldata v3PoolParams,
V4BinPoolParams calldata v4PoolParams,
InfiBinPoolParams calldata infiPoolParams,
uint256 extraAmount0,
uint256 extraAmount1
) external payable override isNotLocked whenNotPaused {
bool shouldReversePair = checkTokensOrderAndMatchFromV3(
v3PoolParams.nfp, v3PoolParams.tokenId, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1
v3PoolParams.nfp, v3PoolParams.tokenId, infiPoolParams.poolKey.currency0, infiPoolParams.poolKey.currency1
);
(uint256 amount0Received, uint256 amount1Received) = withdrawLiquidityFromV3(v3PoolParams, shouldReversePair);

/// @notice if user mannually specify the price range, they need to send extra token
batchAndNormalizeTokens(
v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1, extraAmount0, extraAmount1
infiPoolParams.poolKey.currency0, infiPoolParams.poolKey.currency1, extraAmount0, extraAmount1
);

uint256 amount0Input = amount0Received + extraAmount0;
uint256 amount1Input = amount1Received + extraAmount1;
IBinPositionManager.BinAddLiquidityParams memory addLiquidityParams = IBinPositionManager.BinAddLiquidityParams({
poolKey: v4PoolParams.poolKey,
poolKey: infiPoolParams.poolKey,
amount0: amount0Input.toUint128(),
amount1: amount1Input.toUint128(),
amount0Max: v4PoolParams.amount0Max,
amount1Max: v4PoolParams.amount1Max,
activeIdDesired: v4PoolParams.activeIdDesired,
idSlippage: v4PoolParams.idSlippage,
deltaIds: v4PoolParams.deltaIds,
distributionX: v4PoolParams.distributionX,
distributionY: v4PoolParams.distributionY,
to: v4PoolParams.to,
hookData: v4PoolParams.hookData
amount0Max: infiPoolParams.amount0Max,
amount1Max: infiPoolParams.amount1Max,
activeIdDesired: infiPoolParams.activeIdDesired,
idSlippage: infiPoolParams.idSlippage,
deltaIds: infiPoolParams.deltaIds,
distributionX: infiPoolParams.distributionX,
distributionY: infiPoolParams.distributionY,
to: infiPoolParams.to,
hookData: infiPoolParams.hookData
});
(uint256 amount0Consumed, uint256 amount1Consumed) =
_addLiquidityToTargetPool(addLiquidityParams, v4PoolParams.deadline);
_addLiquidityToTargetPool(addLiquidityParams, infiPoolParams.deadline);

// refund if necessary, ETH is supported by CurrencyLib
unchecked {
if (amount0Input > amount0Consumed) {
v4PoolParams.poolKey.currency0.transfer(v4PoolParams.to, amount0Input - amount0Consumed);
infiPoolParams.poolKey.currency0.transfer(infiPoolParams.to, amount0Input - amount0Consumed);
}
if (amount1Input > amount1Consumed) {
v4PoolParams.poolKey.currency1.transfer(v4PoolParams.to, amount1Input - amount1Consumed);
infiPoolParams.poolKey.currency1.transfer(infiPoolParams.to, amount1Input - amount1Consumed);
}
}
}
Expand Down
Loading

0 comments on commit edcf1fb

Please sign in to comment.