diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2IncludingInit.snap b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2IncludingInit.snap index 3bf6306..03d2863 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2IncludingInit.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2IncludingInit.snap @@ -1 +1 @@ -1133418 \ No newline at end of file +1135806 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutInit.snap b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutInit.snap index 3135411..4788208 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutInit.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutInit.snap @@ -1 +1 @@ -1020942 \ No newline at end of file +1023176 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutNativeToken.snap b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutNativeToken.snap index 258abae..3676977 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutNativeToken.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV2Test#testMigrateFromV2WithoutNativeToken.snap @@ -1 +1 @@ -1090293 \ No newline at end of file +1092527 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3IncludingInit.snap b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3IncludingInit.snap index 90f8ca4..e68d309 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3IncludingInit.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3IncludingInit.snap @@ -1 +1 @@ -1205745 \ No newline at end of file +1208127 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutInit.snap b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutInit.snap index e55bcf9..a2f5912 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutInit.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutInit.snap @@ -1 +1 @@ -1093364 \ No newline at end of file +1095592 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutNativeToken.snap b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutNativeToken.snap index 92b2ee3..5bfd18c 100644 --- a/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutNativeToken.snap +++ b/.forge-snapshots/BinMigratorFromPancakeswapV3Test#testMigrateFromV3WithoutNativeToken.snap @@ -1 +1 @@ -1156698 \ No newline at end of file +1158926 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2IncludingInit.snap b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2IncludingInit.snap index 80ebe20..61a5554 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2IncludingInit.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2IncludingInit.snap @@ -1 +1 @@ -1133430 \ No newline at end of file +1135818 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutInit.snap b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutInit.snap index dd90eb4..6e878c0 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutInit.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutInit.snap @@ -1 +1 @@ -1020954 \ No newline at end of file +1023188 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutNativeToken.snap b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutNativeToken.snap index 6eb7395..f50838c 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutNativeToken.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV2Test#testMigrateFromV2WithoutNativeToken.snap @@ -1 +1 @@ -1090290 \ No newline at end of file +1092524 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3IncludingInit.snap b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3IncludingInit.snap index a312a40..71e4e77 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3IncludingInit.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3IncludingInit.snap @@ -1 +1 @@ -1203727 \ No newline at end of file +1206109 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutInit.snap b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutInit.snap index c381d97..59549b1 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutInit.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutInit.snap @@ -1 +1 @@ -1091346 \ No newline at end of file +1093574 \ No newline at end of file diff --git a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutNativeToken.snap b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutNativeToken.snap index 6fbca27..46c70c5 100644 --- a/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutNativeToken.snap +++ b/.forge-snapshots/BinMigratorFromUniswapV3Test#testMigrateFromV3WithoutNativeToken.snap @@ -1 +1 @@ -1154676 \ No newline at end of file +1156904 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2IncludingInit.snap b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2IncludingInit.snap index 771c774..f562048 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2IncludingInit.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2IncludingInit.snap @@ -1 +1 @@ -743226 \ No newline at end of file +745598 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutInit.snap b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutInit.snap index f88dc65..4924966 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutInit.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutInit.snap @@ -1 +1 @@ -628769 \ No newline at end of file +631031 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap index 36ede60..7e97c6e 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap @@ -1 +1 @@ -700382 \ No newline at end of file +702632 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3IncludingInit.snap b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3IncludingInit.snap index 759440f..c01d494 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3IncludingInit.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3IncludingInit.snap @@ -1 +1 @@ -793085 \ No newline at end of file +795335 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutInit.snap b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutInit.snap index eefb18c..340733e 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutInit.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutInit.snap @@ -1 +1 @@ -681183 \ No newline at end of file +683323 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap index 7c3231b..a757762 100644 --- a/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap +++ b/.forge-snapshots/CLMigratorFromPancakeswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap @@ -1 +1 @@ -750284 \ No newline at end of file +752424 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2IncludingInit.snap b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2IncludingInit.snap index 53d2934..f562048 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2IncludingInit.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2IncludingInit.snap @@ -1 +1 @@ -743238 \ No newline at end of file +745598 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutInit.snap b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutInit.snap index a8fda99..4924966 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutInit.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutInit.snap @@ -1 +1 @@ -628781 \ No newline at end of file +631031 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap index 36ede60..7e97c6e 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV2Test#testCLMigrateFromV2WithoutNativeToken.snap @@ -1 +1 @@ -700382 \ No newline at end of file +702632 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3IncludingInit.snap b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3IncludingInit.snap index 3944497..e424839 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3IncludingInit.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3IncludingInit.snap @@ -1 +1 @@ -791067 \ No newline at end of file +793317 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutInit.snap b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutInit.snap index 231c2b1..b254df0 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutInit.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutInit.snap @@ -1 +1 @@ -679165 \ No newline at end of file +681305 \ No newline at end of file diff --git a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap index 84fb437..30d33a9 100644 --- a/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap +++ b/.forge-snapshots/CLMigratorFromUniswapV3Test#testCLMigrateFromV3WithoutNativeToken.snap @@ -1 +1 @@ -748266 \ No newline at end of file +750406 \ No newline at end of file diff --git a/src/base/BaseMigrator.sol b/src/base/BaseMigrator.sol index 8f6ff53..b5644ef 100644 --- a/src/base/BaseMigrator.sol +++ b/src/base/BaseMigrator.sol @@ -9,13 +9,14 @@ import {IV3NonfungiblePositionManager} from "../interfaces/external/IV3Nonfungib import {IWETH9} from "../interfaces/external/IWETH9.sol"; import {Multicall_v4} from "./Multicall_v4.sol"; import {Currency, CurrencyLibrary} from "pancake-v4-core/src/types/Currency.sol"; +import {Owner} from "pancake-v4-core/src/Owner.sol"; import {SelfPermitERC721} from "./SelfPermitERC721.sol"; import {IBaseMigrator} from "../interfaces/IBaseMigrator.sol"; import {IPositionManagerPermit2} from "../interfaces/IPositionManagerPermit2.sol"; import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; import {Permit2Forwarder} from "./Permit2Forwarder.sol"; -contract BaseMigrator is IBaseMigrator, Permit2Forwarder, Multicall_v4, SelfPermitERC721 { +contract BaseMigrator is IBaseMigrator, Permit2Forwarder, Multicall_v4, SelfPermitERC721, Owner { using SafeCast for uint256; using SafeTransferLib for ERC20; diff --git a/src/pool-bin/BinMigrator.sol b/src/pool-bin/BinMigrator.sol index a99411a..6f4a5ca 100644 --- a/src/pool-bin/BinMigrator.sol +++ b/src/pool-bin/BinMigrator.sol @@ -31,7 +31,7 @@ contract BinMigrator is IBinMigrator, BaseMigrator, ReentrancyLock { V4BinPoolParams calldata v4PoolParams, uint256 extraAmount0, uint256 extraAmount1 - ) external payable override isNotLocked { + ) external payable override isNotLocked whenNotPaused { bool shouldReversePair = checkTokensOrderAndMatchFromV2( v2PoolParams.pair, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1 ); @@ -79,7 +79,7 @@ contract BinMigrator is IBinMigrator, BaseMigrator, ReentrancyLock { V4BinPoolParams calldata v4PoolParams, uint256 extraAmount0, uint256 extraAmount1 - ) external payable override isNotLocked { + ) external payable override isNotLocked whenNotPaused { bool shouldReversePair = checkTokensOrderAndMatchFromV3( v3PoolParams.nfp, v3PoolParams.tokenId, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1 ); diff --git a/src/pool-cl/CLMigrator.sol b/src/pool-cl/CLMigrator.sol index eda3ffc..08f0614 100644 --- a/src/pool-cl/CLMigrator.sol +++ b/src/pool-cl/CLMigrator.sol @@ -34,7 +34,7 @@ contract CLMigrator is ICLMigrator, BaseMigrator, ReentrancyLock { V4CLPoolParams calldata v4PoolParams, uint256 extraAmount0, uint256 extraAmount1 - ) external payable override isNotLocked { + ) external payable override isNotLocked whenNotPaused { bool shouldReversePair = checkTokensOrderAndMatchFromV2( v2PoolParams.pair, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1 ); @@ -77,7 +77,7 @@ contract CLMigrator is ICLMigrator, BaseMigrator, ReentrancyLock { V4CLPoolParams calldata v4PoolParams, uint256 extraAmount0, uint256 extraAmount1 - ) external payable override isNotLocked { + ) external payable override isNotLocked whenNotPaused { bool shouldReversePair = checkTokensOrderAndMatchFromV3( v3PoolParams.nfp, v3PoolParams.tokenId, v4PoolParams.poolKey.currency0, v4PoolParams.poolKey.currency1 ); diff --git a/src/pool-cl/interfaces/ICLMigrator.sol b/src/pool-cl/interfaces/ICLMigrator.sol index 8d8d0ff..19ce86c 100644 --- a/src/pool-cl/interfaces/ICLMigrator.sol +++ b/src/pool-cl/interfaces/ICLMigrator.sol @@ -5,7 +5,6 @@ pragma solidity ^0.8.24; import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; import {IBaseMigrator} from "../../interfaces/IBaseMigrator.sol"; import {IV3NonfungiblePositionManager} from "../../interfaces/external/IV3NonfungiblePositionManager.sol"; -// import {INonfungiblePositionManager} from "./INonfungiblePositionManager.sol"; interface ICLMigrator is IBaseMigrator { error INSUFFICIENT_LIQUIDITY(); diff --git a/test/pool-bin/migrator/BinMigratorFromV2.sol b/test/pool-bin/migrator/BinMigratorFromV2.sol index 91e6d1e..c1f194b 100644 --- a/test/pool-bin/migrator/BinMigratorFromV2.sol +++ b/test/pool-bin/migrator/BinMigratorFromV2.sol @@ -35,6 +35,7 @@ import {Permit2ApproveHelper} from "../../helpers/Permit2ApproveHelper.sol"; import {Permit2SignatureHelpers} from "../../shared/Permit2SignatureHelpers.sol"; import {Permit2Forwarder} from "../../../src/base/Permit2Forwarder.sol"; import {IPositionManager} from "../../../src/interfaces/IPositionManager.sol"; +import {Pausable} from "pancake-v4-core/src/base/Pausable.sol"; interface IPancakeV2LikePairFactory { function createPair(address tokenA, address tokenB) external returns (address pair); @@ -119,6 +120,63 @@ abstract contract BinMigratorFromV2 is v2PairWithoutNativeToken = IPancakePair(v2Factory.createPair(address(token0), address(token1))); } + function testMigrateFromV2_Owner() public { + // casted as owner/transferOwnership not in IBinMigrator interface + BinMigrator _migrator = BinMigrator(payable(address(migrator))); + assertEq(_migrator.owner(), address(this)); + + address alice = makeAddr("alice"); + _migrator.transferOwnership(alice); + + assertEq(_migrator.owner(), alice); + } + + function testMigrateFromV2_WhenPaused() public { + // 1. mint some liquidity to the v2 pair + _mintV2Liquidity(v2Pair); + uint256 lpTokenBefore = v2Pair.balanceOf(address(this)); + + // 2. make sure migrator can transfer user's v2 lp token + permit2ApproveWithSpecificAllowance( + address(this), permit2, address(v2Pair), address(migrator), lpTokenBefore, uint160(lpTokenBefore) + ); + + // 3. initialize the pool + migrator.initializePool(poolKey, ACTIVE_BIN_ID); + + IBaseMigrator.V2PoolParams memory v2PoolParams = IBaseMigrator.V2PoolParams({ + pair: address(v2Pair), + migrateAmount: lpTokenBefore, + // minor precision loss is acceptable + amount0Min: 9.999 ether, + amount1Min: 9.999 ether + }); + + IBinPositionManager.BinAddLiquidityParams memory params = + _getAddParams(poolKey, getBinIds(ACTIVE_BIN_ID, 3), 10 ether, 10 ether, ACTIVE_BIN_ID, address(this)); + + IBinMigrator.V4BinPoolParams memory v4BinPoolParams = IBinMigrator.V4BinPoolParams({ + poolKey: params.poolKey, + amount0Max: params.amount0Max, + amount1Max: params.amount1Max, + activeIdDesired: params.activeIdDesired, + idSlippage: params.idSlippage, + deltaIds: params.deltaIds, + distributionX: params.distributionX, + distributionY: params.distributionY, + to: params.to, + deadline: block.timestamp + 1 + }); + + // pre-req: pause + BinMigrator _migrator = BinMigrator(payable(address(migrator))); + _migrator.pause(); + + // 4. migrateFromV2 + vm.expectRevert(Pausable.EnforcedPause.selector); + migrator.migrateFromV2(v2PoolParams, v4BinPoolParams, 0, 0); + } + function testMigrateFromV2ReentrancyLockRevert() public { MockReentrantPositionManager reentrantPM = new MockReentrantPositionManager(permit2); migrator = new BinMigrator(address(weth), address(reentrantPM), permit2); diff --git a/test/pool-bin/migrator/BinMigratorFromV3.sol b/test/pool-bin/migrator/BinMigratorFromV3.sol index cbd23e0..014f4a2 100644 --- a/test/pool-bin/migrator/BinMigratorFromV3.sol +++ b/test/pool-bin/migrator/BinMigratorFromV3.sol @@ -36,6 +36,7 @@ import {MockReentrantPositionManager} from "../../mocks/MockReentrantPositionMan import {ReentrancyLock} from "../../../src/base/ReentrancyLock.sol"; import {Permit2ApproveHelper} from "../../helpers/Permit2ApproveHelper.sol"; import {IPositionManager} from "../../../src/interfaces/IPositionManager.sol"; +import {Pausable} from "pancake-v4-core/src/base/Pausable.sol"; interface IPancakeV3LikePairFactory { function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); @@ -147,6 +148,52 @@ abstract contract BinMigratorFromV3 is token1.approve(address(v3Nfpm), type(uint256).max); } + function testMigrateFromV3_WhenPaused() public { + // 1. mint some liquidity to the v3 pool + _mintV3Liquidity(address(weth), address(token0)); + (,,,,,,, uint128 liquidityFromV3Before,,,,) = v3Nfpm.positions(1); + + // 2. make sure migrator can transfer user's v3 lp token + v3Nfpm.approve(address(migrator), 1); + + // 3. initialize the pool + migrator.initializePool(poolKey, ACTIVE_BIN_ID); + + IBaseMigrator.V3PoolParams memory v3PoolParams = IBaseMigrator.V3PoolParams({ + nfp: address(v3Nfpm), + tokenId: 1, + liquidity: liquidityFromV3Before, + amount0Min: 9.9 ether, + amount1Min: 9.9 ether, + collectFee: false, + deadline: block.timestamp + 100 + }); + + IBinPositionManager.BinAddLiquidityParams memory params = + _getAddParams(poolKey, getBinIds(ACTIVE_BIN_ID, 3), 10 ether, 10 ether, ACTIVE_BIN_ID, address(this)); + + IBinMigrator.V4BinPoolParams memory v4BinPoolParams = IBinMigrator.V4BinPoolParams({ + poolKey: params.poolKey, + amount0Max: params.amount0Max, + amount1Max: params.amount1Max, + activeIdDesired: params.activeIdDesired, + idSlippage: params.idSlippage, + deltaIds: params.deltaIds, + distributionX: params.distributionX, + distributionY: params.distributionY, + to: params.to, + deadline: block.timestamp + 1 + }); + + // pre-req: pause + BinMigrator _migrator = BinMigrator(payable(address(migrator))); + _migrator.pause(); + + // 4. migrateFromV3 directly given pool has been initialized + vm.expectRevert(Pausable.EnforcedPause.selector); + migrator.migrateFromV3(v3PoolParams, v4BinPoolParams, 0, 0); + } + function testMigrateFromV3ReentrancyLockRevert() public { MockReentrantPositionManager reentrantPM = new MockReentrantPositionManager(permit2); migrator = new BinMigrator(address(weth), address(reentrantPM), permit2); diff --git a/test/pool-cl/migrator/CLMigratorFromV2.sol b/test/pool-cl/migrator/CLMigratorFromV2.sol index 1b66f38..f598ab6 100644 --- a/test/pool-cl/migrator/CLMigratorFromV2.sol +++ b/test/pool-cl/migrator/CLMigratorFromV2.sol @@ -26,6 +26,7 @@ import {Permit2ApproveHelper} from "../../helpers/Permit2ApproveHelper.sol"; import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; import {Permit2SignatureHelpers} from "../../shared/Permit2SignatureHelpers.sol"; import {Permit2Forwarder} from "../../../src/base/Permit2Forwarder.sol"; +import {Pausable} from "pancake-v4-core/src/base/Pausable.sol"; interface IPancakeV2LikePairFactory { function getPair(address tokenA, address tokenB) external view returns (address pair); @@ -105,6 +106,57 @@ abstract contract CLMigratorFromV2 is tickUpper = 100; } + function test_Owner() public { + // casted as owner/transferOwnership not in ICLMigrator interface + CLMigrator _migrator = CLMigrator(payable(address(migrator))); + assertEq(_migrator.owner(), address(this)); + + address alice = makeAddr("alice"); + _migrator.transferOwnership(alice); + + assertEq(_migrator.owner(), alice); + } + + function testCLMigrateFromV2_WhenPaused() public { + // 1. mint some liquidity to the v2 pair + _mintV2Liquidity(v2Pair); + uint256 lpTokenBefore = v2Pair.balanceOf(address(this)); + + // 2. make sure migrator can transfer user's v2 lp token + permit2ApproveWithSpecificAllowance( + address(this), permit2, address(v2Pair), address(migrator), lpTokenBefore, uint160(lpTokenBefore) + ); + + // 3. initialize the pool + uint160 initSqrtPrice = 79228162514264337593543950336; + migrator.initializePool(poolKey, initSqrtPrice); + + IBaseMigrator.V2PoolParams memory v2PoolParams = IBaseMigrator.V2PoolParams({ + pair: address(v2Pair), + migrateAmount: lpTokenBefore, + // minor precision loss is acceptable + amount0Min: 9.999 ether, + amount1Min: 9.999 ether + }); + + ICLMigrator.V4CLPoolParams memory v4MintParams = ICLMigrator.V4CLPoolParams({ + poolKey: poolKey, + tickLower: -100, + tickUpper: 100, + liquidityMin: 0, + recipient: address(this), + deadline: block.timestamp + 100 + }); + + // pre-req: pause + CLMigrator _migrator = CLMigrator(payable(address(migrator))); + _migrator.pause(); + + // 4. migrate from v2 to v4 + vm.expectRevert(Pausable.EnforcedPause.selector); + migrator.migrateFromV2(v2PoolParams, v4MintParams, 0, 0); + } + function testCLMigrateFromV2ReentrancyLockRevert() public { MockReentrantPositionManager reentrantPM = new MockReentrantPositionManager(permit2); reentrantPM.setCLPoolMnager(poolManager); diff --git a/test/pool-cl/migrator/CLMigratorFromV3.sol b/test/pool-cl/migrator/CLMigratorFromV3.sol index 2494337..367bf56 100644 --- a/test/pool-cl/migrator/CLMigratorFromV3.sol +++ b/test/pool-cl/migrator/CLMigratorFromV3.sol @@ -31,6 +31,7 @@ import {SqrtPriceMath} from "pancake-v4-core/src/pool-cl/libraries/SqrtPriceMath import {LiquidityAmounts} from "../../../src/pool-cl/libraries/LiquidityAmounts.sol"; import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {Pausable} from "pancake-v4-core/src/base/Pausable.sol"; interface IPancakeV3LikePairFactory { function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); @@ -127,6 +128,47 @@ abstract contract CLMigratorFromV3 is OldVersionHelper, PosmTestSetup, Permit2Ap token1.approve(address(v3Nfpm), type(uint256).max); } + function testCLMigrateFromV3_WhenPaused() public { + // 1. mint some liquidity to the v3 pool + _mintV3Liquidity(address(weth), address(token0)); + assertEq(v3Nfpm.ownerOf(1), address(this)); + (,,,,,,, uint128 liquidityFromV3Before,,,,) = v3Nfpm.positions(1); + assertGt(liquidityFromV3Before, 0); + + // 2. make sure migrator can transfer user's v3 lp token + v3Nfpm.approve(address(migrator), 1); + + // 3. init the pool + lpm.initializePool(poolKey, INIT_SQRT_PRICE); + + IBaseMigrator.V3PoolParams memory v3PoolParams = IBaseMigrator.V3PoolParams({ + nfp: address(v3Nfpm), + tokenId: 1, + liquidity: liquidityFromV3Before, + amount0Min: 9.9 ether, + amount1Min: 9.9 ether, + collectFee: false, + deadline: block.timestamp + 100 + }); + + ICLMigrator.V4CLPoolParams memory v4MintParams = ICLMigrator.V4CLPoolParams({ + poolKey: poolKey, + tickLower: -100, + tickUpper: 100, + liquidityMin: 0, + recipient: address(this), + deadline: block.timestamp + 100 + }); + + // pre-req: pause + CLMigrator _migrator = CLMigrator(payable(address(migrator))); + _migrator.pause(); + + // 4. migrateFromV3 directly given pool has been initialized + vm.expectRevert(Pausable.EnforcedPause.selector); + migrator.migrateFromV3(v3PoolParams, v4MintParams, 0, 0); + } + function testCLMigrateFromV3ReentrancyLockRevert() public { MockReentrantPositionManager reentrantPM = new MockReentrantPositionManager(permit2); reentrantPM.setCLPoolMnager(poolManager);