diff --git a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_ExistingId.snap b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_ExistingId.snap index 53c0ade..c63c524 100644 --- a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_ExistingId.snap +++ b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_ExistingId.snap @@ -1 +1 @@ -186974 \ No newline at end of file +185311 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_NewId.snap b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_NewId.snap index 3161941..1227dbb 100644 --- a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_NewId.snap +++ b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityOutsideActiveId_NewId.snap @@ -1 +1 @@ -656948 \ No newline at end of file +638186 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId.snap b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId.snap index 32ed4d6..dd3a178 100644 --- a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId.snap +++ b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId.snap @@ -1 +1 @@ -945285 \ No newline at end of file +906704 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId_WithHook.snap b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId_WithHook.snap index 33d7e1b..c36ffe2 100644 --- a/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId_WithHook.snap +++ b/.forge-snapshots/BinFungiblePositionManager_AddLiquidityTest#testAddLiquidityWithActiveId_WithHook.snap @@ -1 +1 @@ -1312637 \ No newline at end of file +1274539 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityOutsideActiveId_ThreeBins.snap b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityOutsideActiveId_ThreeBins.snap index 59a7363..608ae11 100644 --- a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityOutsideActiveId_ThreeBins.snap +++ b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityOutsideActiveId_ThreeBins.snap @@ -1 +1 @@ -153583 \ No newline at end of file +148991 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityWithActiveId_ThreeBins.snap b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityWithActiveId_ThreeBins.snap index 589ff60..9006ca0 100644 --- a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityWithActiveId_ThreeBins.snap +++ b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidityWithActiveId_ThreeBins.snap @@ -1 +1 @@ -224877 \ No newline at end of file +216053 \ No newline at end of file diff --git a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidity_Half.snap b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidity_Half.snap index dd3a892..4d09eda 100644 --- a/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidity_Half.snap +++ b/.forge-snapshots/BinFungiblePositionManager_RemoveLiquidityTest#testRemoveLiquidity_Half.snap @@ -1 +1 @@ -252792 \ No newline at end of file +241767 \ No newline at end of file diff --git a/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromBob.snap b/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromBob.snap index 41669ab..d99eabc 100644 --- a/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromBob.snap +++ b/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromBob.snap @@ -1 +1 @@ -54387 \ No newline at end of file +54579 \ No newline at end of file diff --git a/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromOwner.snap b/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromOwner.snap index 93ea312..506e4cc 100644 --- a/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromOwner.snap +++ b/.forge-snapshots/BinFungibleTokenTest#testBatchTransferFrom_FromOwner.snap @@ -1 +1 @@ -52359 \ No newline at end of file +52095 \ No newline at end of file diff --git a/.forge-snapshots/BinFungibleTokenTest#testBurn.snap b/.forge-snapshots/BinFungibleTokenTest#testBurn.snap index 25292f2..9ba56dd 100644 --- a/.forge-snapshots/BinFungibleTokenTest#testBurn.snap +++ b/.forge-snapshots/BinFungibleTokenTest#testBurn.snap @@ -1 +1 @@ -27300 \ No newline at end of file +26887 \ No newline at end of file diff --git a/.forge-snapshots/BinFungibleTokenTest#testMint.snap b/.forge-snapshots/BinFungibleTokenTest#testMint.snap index 5a500c1..9b41b12 100644 --- a/.forge-snapshots/BinFungibleTokenTest#testMint.snap +++ b/.forge-snapshots/BinFungibleTokenTest#testMint.snap @@ -1 +1 @@ -67877 \ No newline at end of file +67685 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_DifferentRecipient.snap b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_DifferentRecipient.snap index cf85684..30d5ec8 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_DifferentRecipient.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_DifferentRecipient.snap @@ -1 +1 @@ -162255 \ No newline at end of file +154616 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapEthForToken.snap b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapEthForToken.snap index e93ca17..c2ddc61 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapEthForToken.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapEthForToken.snap @@ -1 +1 @@ -156725 \ No newline at end of file +145793 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapTokenForEth.snap b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapTokenForEth.snap index 60f8b37..4374681 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapTokenForEth.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_EthPool_SwapTokenForEth.snap @@ -1 +1 @@ -159530 \ No newline at end of file +151891 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_1.snap b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_1.snap index 9cdcd67..fe72d2e 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_1.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_1.snap @@ -1 +1 @@ -160249 \ No newline at end of file +152610 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_2.snap b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_2.snap index 1ab00a0..9d11b91 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_2.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInputSingle_SwapForY_2.snap @@ -1 +1 @@ -160312 \ No newline at end of file +152651 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactInput_MultiHopDifferentRecipient.snap b/.forge-snapshots/BinSwapRouterTest#testExactInput_MultiHopDifferentRecipient.snap index 2814bdc..17618a0 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactInput_MultiHopDifferentRecipient.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactInput_MultiHopDifferentRecipient.snap @@ -1 +1 @@ -186338 \ No newline at end of file +179342 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_DifferentRecipient.snap b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_DifferentRecipient.snap index 44ce088..74d15c8 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_DifferentRecipient.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_DifferentRecipient.snap @@ -1 +1 @@ -172624 \ No newline at end of file +164893 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_1.snap b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_1.snap index afdd9de..f61cf35 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_1.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_1.snap @@ -1 +1 @@ -170630 \ No newline at end of file +162899 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_2.snap b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_2.snap index 6efd550..1ed48c6 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_2.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactOutputSingle_SwapForY_2.snap @@ -1 +1 @@ -170705 \ No newline at end of file +162936 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactOutput_MultiHopDifferentRecipient.snap b/.forge-snapshots/BinSwapRouterTest#testExactOutput_MultiHopDifferentRecipient.snap index 994afae..510b4ae 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactOutput_MultiHopDifferentRecipient.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactOutput_MultiHopDifferentRecipient.snap @@ -1 +1 @@ -200509 \ No newline at end of file +193297 \ No newline at end of file diff --git a/.forge-snapshots/BinSwapRouterTest#testExactOutput_SingleHop.snap b/.forge-snapshots/BinSwapRouterTest#testExactOutput_SingleHop.snap index cbcce68..d45294d 100644 --- a/.forge-snapshots/BinSwapRouterTest#testExactOutput_SingleHop.snap +++ b/.forge-snapshots/BinSwapRouterTest#testExactOutput_SingleHop.snap @@ -1 +1 @@ -162954 \ No newline at end of file +155207 \ No newline at end of file diff --git a/.forge-snapshots/CLSwapRouterTest#ExactInput.snap b/.forge-snapshots/CLSwapRouterTest#ExactInput.snap index 3ccc503..bf91f5f 100644 --- a/.forge-snapshots/CLSwapRouterTest#ExactInput.snap +++ b/.forge-snapshots/CLSwapRouterTest#ExactInput.snap @@ -1 +1 @@ -266645 \ No newline at end of file +255442 \ No newline at end of file diff --git a/.forge-snapshots/CLSwapRouterTest#ExactInputSingle.snap b/.forge-snapshots/CLSwapRouterTest#ExactInputSingle.snap index d551c2f..1a36d18 100644 --- a/.forge-snapshots/CLSwapRouterTest#ExactInputSingle.snap +++ b/.forge-snapshots/CLSwapRouterTest#ExactInputSingle.snap @@ -1 +1 @@ -201852 \ No newline at end of file +192524 \ No newline at end of file diff --git a/.forge-snapshots/CLSwapRouterTest#ExactOutput.snap b/.forge-snapshots/CLSwapRouterTest#ExactOutput.snap index d14a3b6..ea40a60 100644 --- a/.forge-snapshots/CLSwapRouterTest#ExactOutput.snap +++ b/.forge-snapshots/CLSwapRouterTest#ExactOutput.snap @@ -1 +1 @@ -272728 \ No newline at end of file +260676 \ No newline at end of file diff --git a/.forge-snapshots/CLSwapRouterTest#ExactOutputSingle.snap b/.forge-snapshots/CLSwapRouterTest#ExactOutputSingle.snap index 6c3d0c4..8626acc 100644 --- a/.forge-snapshots/CLSwapRouterTest#ExactOutputSingle.snap +++ b/.forge-snapshots/CLSwapRouterTest#ExactOutputSingle.snap @@ -1 +1 @@ -201502 \ No newline at end of file +191719 \ No newline at end of file diff --git a/.forge-snapshots/NonfungiblePositionManager#collect.snap b/.forge-snapshots/NonfungiblePositionManager#collect.snap index ee2fa4f..091b6c2 100644 --- a/.forge-snapshots/NonfungiblePositionManager#collect.snap +++ b/.forge-snapshots/NonfungiblePositionManager#collect.snap @@ -1 +1 @@ -276679 \ No newline at end of file +265629 \ No newline at end of file diff --git a/.forge-snapshots/NonfungiblePositionManager#decreaseLiquidity.snap b/.forge-snapshots/NonfungiblePositionManager#decreaseLiquidity.snap index b2fcfc4..e30fc66 100644 --- a/.forge-snapshots/NonfungiblePositionManager#decreaseLiquidity.snap +++ b/.forge-snapshots/NonfungiblePositionManager#decreaseLiquidity.snap @@ -1 +1 @@ -190144 \ No newline at end of file +176568 \ No newline at end of file diff --git a/.forge-snapshots/NonfungiblePositionManager#increaseLiquidity.snap b/.forge-snapshots/NonfungiblePositionManager#increaseLiquidity.snap index 5988a3c..036527e 100644 --- a/.forge-snapshots/NonfungiblePositionManager#increaseLiquidity.snap +++ b/.forge-snapshots/NonfungiblePositionManager#increaseLiquidity.snap @@ -1 +1 @@ -218325 \ No newline at end of file +210284 \ No newline at end of file diff --git a/.forge-snapshots/NonfungiblePositionManager#mint.snap b/.forge-snapshots/NonfungiblePositionManager#mint.snap index d407d24..8fdf5cf 100644 --- a/.forge-snapshots/NonfungiblePositionManager#mint.snap +++ b/.forge-snapshots/NonfungiblePositionManager#mint.snap @@ -1 +1 @@ -653033 \ No newline at end of file +609324 \ No newline at end of file diff --git a/lib/pancake-v4-core b/lib/pancake-v4-core index ab17fb7..3a99be9 160000 --- a/lib/pancake-v4-core +++ b/lib/pancake-v4-core @@ -1 +1 @@ -Subproject commit ab17fb74ae2021fc05b5fac2c98b391e6700c120 +Subproject commit 3a99be9fc489c6e5f7ae7365348444abe3a445ff diff --git a/src/SwapRouterBase.sol b/src/SwapRouterBase.sol index 80bc67e..c5684c9 100644 --- a/src/SwapRouterBase.sol +++ b/src/SwapRouterBase.sol @@ -39,8 +39,13 @@ abstract contract SwapRouterBase is ISwapRouterBase { } function _payAndSettle(Currency currency, address msgSender, int128 settleAmount) internal virtual { - _pay(currency, msgSender, address(vault), uint256(uint128(settleAmount))); - vault.settleAndMintRefund(currency, msgSender); + if (currency.isNative()) { + vault.settle{value: uint256(uint128(settleAmount))}(currency); + } else { + vault.sync(currency); + _pay(currency, msgSender, address(vault), uint256(uint128(settleAmount))); + vault.settle(currency); + } } function _pay(Currency currency, address payer, address recipient, uint256 amount) internal virtual; diff --git a/src/pool-bin/BinFungiblePositionManager.sol b/src/pool-bin/BinFungiblePositionManager.sol index a448ef7..d060fda 100644 --- a/src/pool-bin/BinFungiblePositionManager.sol +++ b/src/pool-bin/BinFungiblePositionManager.sol @@ -165,13 +165,13 @@ contract BinFungiblePositionManager is bytes32 amountIn = params.amount0.encode(params.amount1); (BalanceDelta delta, BinPool.MintArrays memory mintArray) = poolManager.mint( params.poolKey, - IBinPoolManager.MintParams({liquidityConfigs: liquidityConfigs, amountIn: amountIn}), + IBinPoolManager.MintParams({liquidityConfigs: liquidityConfigs, amountIn: amountIn, salt: bytes32(0)}), ZERO_BYTES ); - // delta amt0/amt1 will always be positive in mint case - if (delta.amount0() < 0 || delta.amount1() < 0) revert IncorrectOutputAmount(); - if (uint128(delta.amount0()) < params.amount0Min || uint128(delta.amount1()) < params.amount1Min) { + // delta amt0/amt1 will always be negative in mint case + if (delta.amount0() > 0 || delta.amount1() > 0) revert IncorrectOutputAmount(); + if (uint128(-delta.amount0()) < params.amount0Min || uint128(-delta.amount1()) < params.amount1Min) { revert OutputAmountSlippage(); } @@ -194,17 +194,19 @@ contract BinFungiblePositionManager is } } - return abi.encode(delta.amount0(), delta.amount1(), tokenIds, mintArray.liquidityMinted); + return abi.encode(uint128(-delta.amount0()), uint128(-delta.amount1()), tokenIds, mintArray.liquidityMinted); } else if (data.callbackDataType == CallbackDataType.RemoveLiquidity) { RemoveLiquidityParams memory params = abi.decode(data.params, (RemoveLiquidityParams)); BalanceDelta delta = poolManager.burn( - params.poolKey, IBinPoolManager.BurnParams({ids: params.ids, amountsToBurn: params.amounts}), ZERO_BYTES + params.poolKey, + IBinPoolManager.BurnParams({ids: params.ids, amountsToBurn: params.amounts, salt: bytes32(0)}), + ZERO_BYTES ); - // delta amt0/amt1 will either be 0 or negative in removing liquidity - if (delta.amount0() > 0 || delta.amount1() > 0) revert IncorrectOutputAmount(); - if (uint128(-delta.amount0()) < params.amount0Min || uint128(-delta.amount1()) < params.amount1Min) { + // delta amt0/amt1 will either be 0 or positive in removing liquidity + if (delta.amount0() < 0 || delta.amount1() < 0) revert IncorrectOutputAmount(); + if (uint128(delta.amount0()) < params.amount0Min || uint128(delta.amount1()) < params.amount1Min) { revert OutputAmountSlippage(); } @@ -223,7 +225,7 @@ contract BinFungiblePositionManager is } } - return abi.encode(uint128(-delta.amount0()), uint128(-delta.amount1()), tokenIds); + return abi.encode(delta.amount0(), delta.amount1(), tokenIds); } } @@ -231,17 +233,27 @@ contract BinFungiblePositionManager is /// @param user If delta.amt > 0, take amt from user. else if delta.amt < 0, transfer amt to user function _settleDeltas(address user, PoolKey memory poolKey, BalanceDelta delta) internal { if (delta.amount0() > 0) { - pay(poolKey.currency0, user, address(vault), uint256(int256(delta.amount0()))); - vault.settleAndMintRefund(poolKey.currency0, user); + vault.take(poolKey.currency0, user, uint128(delta.amount0())); } else if (delta.amount0() < 0) { - vault.take(poolKey.currency0, user, uint128(-delta.amount0())); + if (poolKey.currency0.isNative()) { + vault.settle{value: uint256(int256(-delta.amount0()))}(poolKey.currency0); + } else { + vault.sync(poolKey.currency0); + pay(poolKey.currency0, user, address(vault), uint256(int256(-delta.amount0()))); + vault.settle(poolKey.currency0); + } } if (delta.amount1() > 0) { - pay(poolKey.currency1, user, address(vault), uint256(int256(delta.amount1()))); - vault.settleAndMintRefund(poolKey.currency1, user); + vault.take(poolKey.currency1, user, uint128(delta.amount1())); } else if (delta.amount1() < 0) { - vault.take(poolKey.currency1, user, uint128(-delta.amount1())); + if (poolKey.currency1.isNative()) { + vault.settle{value: uint256(int256(-delta.amount1()))}(poolKey.currency1); + } else { + vault.sync(poolKey.currency1); + pay(poolKey.currency1, user, address(vault), uint256(int256(-delta.amount1()))); + vault.settle(poolKey.currency1); + } } } } diff --git a/src/pool-bin/BinSwapRouterBase.sol b/src/pool-bin/BinSwapRouterBase.sol index 0fe81ef..066c892 100644 --- a/src/pool-bin/BinSwapRouterBase.sol +++ b/src/pool-bin/BinSwapRouterBase.sol @@ -170,13 +170,13 @@ abstract contract BinSwapRouterBase is SwapRouterBase, IBinSwapRouterBase { BalanceDelta delta = binPoolManager.swap(poolKey, swapForY, amountIn, hookData); if (swapForY) { - if (settle) _payAndSettle(poolKey.currency0, payer, delta.amount0()); - if (take) vault.take(poolKey.currency1, recipient, uint128(-delta.amount1())); + if (settle) _payAndSettle(poolKey.currency0, payer, -delta.amount0()); + if (take) vault.take(poolKey.currency1, recipient, uint128(delta.amount1())); } else { - if (settle) _payAndSettle(poolKey.currency1, payer, delta.amount1()); - if (take) vault.take(poolKey.currency0, recipient, uint128(-delta.amount0())); + if (settle) _payAndSettle(poolKey.currency1, payer, -delta.amount1()); + if (take) vault.take(poolKey.currency0, recipient, uint128(delta.amount0())); } - amountOut = swapForY ? uint128(-delta.amount1()) : uint128(-delta.amount0()); + amountOut = swapForY ? uint128(delta.amount1()) : uint128(delta.amount0()); } } diff --git a/src/pool-cl/CLSwapRouterBase.sol b/src/pool-cl/CLSwapRouterBase.sol index 403a3ad..9a38ab9 100644 --- a/src/pool-cl/CLSwapRouterBase.sol +++ b/src/pool-cl/CLSwapRouterBase.sol @@ -24,18 +24,16 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { V4CLExactInputSingleParams memory params, V4SettlementParams memory settlementParams ) internal returns (uint256 amountOut) { - amountOut = uint128( - -_swapExactPrivate( - params.poolKey, - params.zeroForOne, - int256(int128(params.amountIn)), - params.sqrtPriceLimitX96, - settlementParams.payer, - params.recipient, - settlementParams.settle, - settlementParams.take, - params.hookData - ) + amountOut = _swapExactPrivate( + params.poolKey, + params.zeroForOne, + -int256(int128(params.amountIn)), + params.sqrtPriceLimitX96, + settlementParams.payer, + params.recipient, + settlementParams.settle, + settlementParams.take, + params.hookData ); if (amountOut < params.amountOutMinimum) revert TooLittleReceived(); } @@ -57,18 +55,16 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { for (uint256 i = 0; i < state.pathLength; i++) { (state.poolKey, state.zeroForOne) = _getPoolAndSwapDirection(params.path[i], params.currencyIn); - state.amountOut = uint128( - -_swapExactPrivate( - state.poolKey, - state.zeroForOne, - int256(int128(params.amountIn)), - 0, - settlementParams.payer, - params.recipient, - i == 0 && settlementParams.settle, - i == state.pathLength - 1 && settlementParams.take, - params.path[i].hookData - ) + state.amountOut = _swapExactPrivate( + state.poolKey, + state.zeroForOne, + -int256(int128(params.amountIn)), + 0, + settlementParams.payer, + params.recipient, + i == 0 && settlementParams.settle, + i == state.pathLength - 1 && settlementParams.take, + params.path[i].hookData ); params.amountIn = state.amountOut; @@ -85,18 +81,16 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { V4CLExactOutputSingleParams memory params, V4SettlementParams memory settlementParams ) internal returns (uint256 amountIn) { - amountIn = uint128( - _swapExactPrivate( - params.poolKey, - params.zeroForOne, - -int256(int128(params.amountOut)), - params.sqrtPriceLimitX96, - settlementParams.payer, - params.recipient, - settlementParams.settle, - settlementParams.take, - params.hookData - ) + amountIn = _swapExactPrivate( + params.poolKey, + params.zeroForOne, + int256(int128(params.amountOut)), + params.sqrtPriceLimitX96, + settlementParams.payer, + params.recipient, + settlementParams.settle, + settlementParams.take, + params.hookData ); if (amountIn > params.amountInMaximum) revert TooMuchRequested(); } @@ -118,18 +112,16 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { for (uint256 i = state.pathLength; i > 0; i--) { (state.poolKey, state.oneForZero) = _getPoolAndSwapDirection(params.path[i - 1], params.currencyOut); - state.amountIn = uint128( - _swapExactPrivate( - state.poolKey, - !state.oneForZero, - -int256(int128(params.amountOut)), - 0, - settlementParams.payer, - params.recipient, - i == 1 && settlementParams.settle, - i == state.pathLength && settlementParams.take, - params.path[i - 1].hookData - ) + state.amountIn = _swapExactPrivate( + state.poolKey, + !state.oneForZero, + int256(int128(params.amountOut)), + 0, + settlementParams.payer, + params.recipient, + i == 1 && settlementParams.settle, + i == state.pathLength && settlementParams.take, + params.path[i - 1].hookData ); params.amountOut = state.amountIn; @@ -141,6 +133,9 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { } } + /// @return reciprocalAmount The amount of the reciprocal token + // If exactInput token0 for token1, the reciprocalAmount is the amount of token1. + // If exactOutput token0 for token1, the reciprocalAmount is the amount of token0. function _swapExactPrivate( PoolKey memory poolKey, bool zeroForOne, @@ -151,7 +146,7 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { bool settle, bool take, bytes memory hookData - ) private returns (int128 reciprocalAmount) { + ) private returns (uint128 reciprocalAmount) { BalanceDelta delta = clPoolManager.swap( poolKey, ICLPoolManager.SwapParams( @@ -165,13 +160,17 @@ abstract contract CLSwapRouterBase is SwapRouterBase, ICLSwapRouterBase { ); if (zeroForOne) { - reciprocalAmount = amountSpecified > 0 ? delta.amount1() : delta.amount0(); - if (settle) _payAndSettle(poolKey.currency0, payer, delta.amount0()); - if (take) vault.take(poolKey.currency1, recipient, uint128(-delta.amount1())); + /// @dev amountSpecified < 0 indicate exactInput, so reciprocal token is token1 and positive + /// amountSpecified > 0 indicate exactOutput, so reciprocal token is token0 but is negative + reciprocalAmount = amountSpecified < 0 ? uint128(delta.amount1()) : uint128(-delta.amount0()); + + if (settle) _payAndSettle(poolKey.currency0, payer, -delta.amount0()); + if (take) vault.take(poolKey.currency1, recipient, uint128(delta.amount1())); } else { - reciprocalAmount = amountSpecified > 0 ? delta.amount0() : delta.amount1(); - if (settle) _payAndSettle(poolKey.currency1, payer, delta.amount1()); - if (take) vault.take(poolKey.currency0, recipient, uint128(-delta.amount0())); + reciprocalAmount = amountSpecified < 0 ? uint128(delta.amount0()) : uint128(-delta.amount1()); + + if (settle) _payAndSettle(poolKey.currency1, payer, -delta.amount1()); + if (take) vault.take(poolKey.currency0, recipient, uint128(delta.amount0())); } } } diff --git a/src/pool-cl/NonfungiblePositionManager.sol b/src/pool-cl/NonfungiblePositionManager.sol index 7f40f0f..f1a5c58 100644 --- a/src/pool-cl/NonfungiblePositionManager.sol +++ b/src/pool-cl/NonfungiblePositionManager.sol @@ -234,8 +234,10 @@ contract NonfungiblePositionManager is uint256 tokenId = _nextId++; _mint(params.recipient, tokenId); - CLPosition.Info memory positionInfo = - poolManager.getPosition(params.poolKey.toId(), address(this), params.tickLower, params.tickUpper); + // todo: about the salt + CLPosition.Info memory positionInfo = poolManager.getPosition( + params.poolKey.toId(), address(this), params.tickLower, params.tickUpper, bytes32(0) + ); _positions[tokenId] = Position({ nonce: 0, operator: address(0), @@ -254,7 +256,7 @@ contract NonfungiblePositionManager is settleDeltas(data.sender, params.poolKey, delta); - return abi.encode(tokenId, liquidity, delta.amount0(), delta.amount1()); + return abi.encode(tokenId, liquidity, -delta.amount0(), -delta.amount1()); } function _handleIncreaseLiquidity(CallbackData memory data) internal returns (bytes memory) { @@ -278,8 +280,9 @@ contract NonfungiblePositionManager is }) ); + // todo: about the salt CLPosition.Info memory poolManagerPositionInfo = - poolManager.getPosition(poolId, address(this), tickLower, tickUpper); + poolManager.getPosition(poolId, address(this), tickLower, tickUpper, bytes32(0)); /// @dev This can be overflow in following cases: /// 1. feeGrowthInside0LastX128 is overflow @@ -313,7 +316,7 @@ contract NonfungiblePositionManager is settleDeltas(data.sender, poolKey, delta); - return abi.encode(liquidity, delta.amount0(), delta.amount1()); + return abi.encode(liquidity, -delta.amount0(), -delta.amount1()); } function _handleDecreaseLiquidity(CallbackData memory data) internal returns (bytes memory) { @@ -340,8 +343,9 @@ contract NonfungiblePositionManager is }) ); + // todo: about the salt CLPosition.Info memory poolManagerPositionInfo = - poolManager.getPosition(poolId, address(this), tickLower, tickUpper); + poolManager.getPosition(poolId, address(this), tickLower, tickUpper, bytes32(0)); /// @dev This can be overflow in following cases: /// 1. feeGrowthInside0LastX128 is overflow @@ -378,7 +382,7 @@ contract NonfungiblePositionManager is settleDeltas(data.sender, poolKey, delta); - return abi.encode(-delta.amount0(), -delta.amount1()); + return abi.encode(delta.amount0(), delta.amount1()); } function _handleCollect(CallbackData memory data) internal returns (bytes memory) { @@ -394,8 +398,10 @@ contract NonfungiblePositionManager is if (nftPositionCache.liquidity > 0) { resetAccumulatedFee(poolKey, nftPositionCache.tickLower, nftPositionCache.tickUpper); - CLPosition.Info memory poolManagerPositionInfo = - poolManager.getPosition(poolId, address(this), nftPositionCache.tickLower, nftPositionCache.tickUpper); + // todo: about the salt + CLPosition.Info memory poolManagerPositionInfo = poolManager.getPosition( + poolId, address(this), nftPositionCache.tickLower, nftPositionCache.tickUpper, bytes32(0) + ); /// @dev This can be overflow in following cases: /// 1. feeGrowthInside0LastX128 is overflow diff --git a/src/pool-cl/base/LiquidityManagement.sol b/src/pool-cl/base/LiquidityManagement.sol index 97c79a0..086e504 100644 --- a/src/pool-cl/base/LiquidityManagement.sol +++ b/src/pool-cl/base/LiquidityManagement.sol @@ -20,6 +20,9 @@ import {LiquidityAmounts} from "../libraries/LiquidityAmounts.sol"; abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPayments { using PoolIdLibrary for PoolKey; + // todo: think if salt require non zero byte + bytes32 constant SALT_0 = bytes32(0); + error PriceSlippageCheckFailed(); struct AddLiquidityParams { @@ -46,18 +49,20 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay // for update liquidity, we claim the fee before further action to avoid this. function resetAccumulatedFee(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) internal { CLPosition.Info memory poolManagerPositionInfo = - poolManager.getPosition(poolKey.toId(), address(this), tickLower, tickUpper); + poolManager.getPosition(poolKey.toId(), address(this), tickLower, tickUpper, SALT_0); if (poolManagerPositionInfo.liquidity > 0) { - BalanceDelta delta = - poolManager.modifyLiquidity(poolKey, ICLPoolManager.ModifyLiquidityParams(tickLower, tickUpper, 0), ""); + // todo: can we avoid this resetAccumulatedFee call? + (, BalanceDelta feeDelta) = poolManager.modifyLiquidity( + poolKey, ICLPoolManager.ModifyLiquidityParams(tickLower, tickUpper, 0, SALT_0), "" + ); - if (delta.amount0() < 0) { - vault.mint(address(this), poolKey.currency0, uint256(int256(-delta.amount0()))); + if (feeDelta.amount0() > 0) { + vault.mint(address(this), poolKey.currency0, uint256(int256(feeDelta.amount0()))); } - if (delta.amount1() < 0) { - vault.mint(address(this), poolKey.currency1, uint256(int256(-delta.amount1()))); + if (feeDelta.amount1() > 0) { + vault.mint(address(this), poolKey.currency1, uint256(int256(feeDelta.amount1()))); } } } @@ -72,16 +77,16 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, params.amount0Desired, params.amount1Desired ); - delta = poolManager.modifyLiquidity( + (delta,) = poolManager.modifyLiquidity( params.poolKey, - ICLPoolManager.ModifyLiquidityParams(params.tickLower, params.tickUpper, int256(uint256(liquidity))), + ICLPoolManager.ModifyLiquidityParams(params.tickLower, params.tickUpper, int256(uint256(liquidity)), SALT_0), "" ); - /// @dev amount0 & amount1 cant be negative here since LPing has been claimed + /// @dev amount0 & amount1 cant be positive here since LPing has been claimed if ( - uint256(uint128(delta.amount0())) < params.amount0Min - || uint256(uint128(delta.amount1())) < params.amount1Min + uint256(uint128(-delta.amount0())) < params.amount0Min + || uint256(uint128(-delta.amount1())) < params.amount1Min ) { revert PriceSlippageCheckFailed(); } @@ -90,16 +95,18 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay function removeLiquidity(RemoveLiquidityParams memory params) internal returns (BalanceDelta delta) { resetAccumulatedFee(params.poolKey, params.tickLower, params.tickUpper); - delta = poolManager.modifyLiquidity( + (delta,) = poolManager.modifyLiquidity( params.poolKey, - ICLPoolManager.ModifyLiquidityParams(params.tickLower, params.tickUpper, -int256(uint256(params.liquidity))), + ICLPoolManager.ModifyLiquidityParams( + params.tickLower, params.tickUpper, -int256(uint256(params.liquidity)), SALT_0 + ), "" ); - /// @dev amount0 & amount1 must be negative here since LPing has been claimed + /// @dev amount0 & amount1 must be positive here since LPing has been claimed if ( - uint256(uint128(-delta.amount0())) < params.amount0Min - || uint256(uint128(-delta.amount1())) < params.amount1Min + uint256(uint128(delta.amount0())) < params.amount0Min + || uint256(uint128(delta.amount1())) < params.amount1Min ) { revert PriceSlippageCheckFailed(); } @@ -112,16 +119,27 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay function settleDeltas(address sender, PoolKey memory poolKey, BalanceDelta delta) internal { if (delta.amount0() > 0) { - pay(poolKey.currency0, sender, address(vault), uint256(int256(delta.amount0()))); - vault.settleAndMintRefund(poolKey.currency0, sender); + vault.take(poolKey.currency0, sender, uint128(delta.amount0())); } else if (delta.amount0() < 0) { - vault.take(poolKey.currency0, sender, uint128(-delta.amount0())); + if (poolKey.currency0.isNative()) { + vault.settle{value: uint256(int256(-delta.amount0()))}(poolKey.currency0); + } else { + vault.sync(poolKey.currency0); + pay(poolKey.currency0, sender, address(vault), uint256(int256(-delta.amount0()))); + vault.settle(poolKey.currency0); + } } + if (delta.amount1() > 0) { - pay(poolKey.currency1, sender, address(vault), uint256(int256(delta.amount1()))); - vault.settleAndMintRefund(poolKey.currency1, sender); + vault.take(poolKey.currency1, sender, uint128(delta.amount1())); } else if (delta.amount1() < 0) { - vault.take(poolKey.currency1, sender, uint128(-delta.amount1())); + if (poolKey.currency1.isNative()) { + vault.settle{value: uint256(int256(-delta.amount1()))}(poolKey.currency1); + } else { + vault.sync(poolKey.currency1); + pay(poolKey.currency1, sender, address(vault), uint256(int256(-delta.amount1()))); + vault.settle(poolKey.currency1); + } } } } diff --git a/test/pool-bin/BinFungiblePositionManager_AddLiquidity.t.sol b/test/pool-bin/BinFungiblePositionManager_AddLiquidity.t.sol index e4003c4..f869125 100644 --- a/test/pool-bin/BinFungiblePositionManager_AddLiquidity.t.sol +++ b/test/pool-bin/BinFungiblePositionManager_AddLiquidity.t.sol @@ -59,7 +59,7 @@ contract BinFungiblePositionManager_AddLiquidityTest is Test, GasSnapshot, Liqui WETH weth = new WETH(); vault = new Vault(); poolManager = new BinPoolManager(IVault(address(vault)), 500000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); binFungiblePositionManager = new BinFungiblePositionManager(IVault(address(vault)), IBinPoolManager(address(poolManager)), address(weth)); @@ -540,41 +540,4 @@ contract BinFungiblePositionManager_AddLiquidityTest is Test, GasSnapshot, Liqui deadline: block.timestamp + 600 }); } - - function testSettleAndMintRefund() public { - // transfer excess token to vault - uint256 excessTokenAmount = 1 ether; - address hacker = address(1); - token0.mint(hacker, excessTokenAmount); - vm.startPrank(hacker); - token0.transfer(address(vault), excessTokenAmount); - vm.stopPrank(); - - // pre-test, verify alice has 1e18 token0 and token1 - token0.mint(alice, 1 ether); - token1.mint(alice, 1 ether); - assertEq(token0.balanceOf(alice), 1 ether); - assertEq(token1.balanceOf(alice), 1 ether); - - vm.startPrank(alice); - uint24[] memory binIds = getBinIds(activeId, 3); - IBinFungiblePositionManager.AddLiquidityParams memory params; - params = _getAddParams(key1, binIds, 1 ether, 1 ether, activeId, alice); - (,, uint256[] memory tokenIds,) = binFungiblePositionManager.addLiquidity(params); - - for (uint256 i; i < tokenIds.length; i++) { - (Currency curr0, Currency curr1, uint24 fee, uint24 binId) = - binFungiblePositionManager.positions(tokenIds[i]); - assertEq(Currency.unwrap(curr0), Currency.unwrap(key1.currency0)); - assertEq(Currency.unwrap(curr1), Currency.unwrap(key1.currency1)); - assertEq(fee, key1.fee); - assertEq(binId, binIds[i]); - } - - // check currency balance in vault - { - uint256 currency0Balance = vault.balanceOf(alice, currency0); - assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault"); - } - } } diff --git a/test/pool-bin/BinFungiblePositionManager_RemoveLiquidity.t.sol b/test/pool-bin/BinFungiblePositionManager_RemoveLiquidity.t.sol index 1eef06d..ae6896e 100644 --- a/test/pool-bin/BinFungiblePositionManager_RemoveLiquidity.t.sol +++ b/test/pool-bin/BinFungiblePositionManager_RemoveLiquidity.t.sol @@ -60,7 +60,7 @@ contract BinFungiblePositionManager_RemoveLiquidityTest is Test, GasSnapshot, Li WETH weth = new WETH(); vault = new Vault(); poolManager = new BinPoolManager(IVault(address(vault)), 500000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); binFungiblePositionManager = new BinFungiblePositionManager(IVault(address(vault)), IBinPoolManager(address(poolManager)), address(weth)); diff --git a/test/pool-bin/BinSwapRouter.t.sol b/test/pool-bin/BinSwapRouter.t.sol index f9a20d9..1cfd771 100644 --- a/test/pool-bin/BinSwapRouter.t.sol +++ b/test/pool-bin/BinSwapRouter.t.sol @@ -58,7 +58,7 @@ contract BinSwapRouterTest is Test, GasSnapshot, LiquidityParamsHelper { weth = new WETH(); vault = new Vault(); poolManager = new BinPoolManager(IVault(address(vault)), 500000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); router = new BinSwapRouter(vault, poolManager, address(weth)); binFungiblePositionManager = @@ -251,7 +251,7 @@ contract BinSwapRouterTest is Test, GasSnapshot, LiquidityParamsHelper { function testExactInputSingle_EthPool_InsufficientETH() public { vm.deal(alice, 1 ether); - vm.expectRevert(CurrencyLibrary.NativeTransferFailed.selector); + vm.expectRevert(); // OutOfFund router.exactInputSingle{value: 0.5 ether}( IBinSwapRouterBase.V4BinExactInputSingleParams({ poolKey: key3, @@ -765,45 +765,4 @@ contract BinSwapRouterTest is Test, GasSnapshot, LiquidityParamsHelper { assertEq(address(router).balance, 0 ether); assertEq(token0.balanceOf(alice), abi.decode(result[0], (uint256))); } - - function testSettleAndMintRefund() public { - // transfer excess token to vault - uint256 excessTokenAmount = 1 ether; - address hacker = address(1); - token0.mint(hacker, excessTokenAmount); - vm.startPrank(hacker); - token0.transfer(address(vault), excessTokenAmount); - vm.stopPrank(); - - vm.startPrank(alice); - token0.mint(alice, 1 ether); - - ISwapRouterBase.PathKey[] memory path = new ISwapRouterBase.PathKey[](1); - path[0] = ISwapRouterBase.PathKey({ - intermediateCurrency: Currency.wrap(address(token1)), - fee: key.fee, - hooks: key.hooks, - hookData: new bytes(0), - poolManager: key.poolManager, - parameters: key.parameters - }); - - uint256 amountOut = router.exactInput( - IBinSwapRouterBase.V4BinExactInputParams({ - currencyIn: Currency.wrap(address(token0)), - path: path, - recipient: alice, - amountIn: 1 ether, - amountOutMinimum: 0 - }), - block.timestamp + 60 - ); - assertEq(token1.balanceOf(alice), amountOut); - - // check currency balance in vault - { - uint256 currency0Balance = vault.balanceOf(alice, Currency.wrap(address(token0))); - assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault"); - } - } } diff --git a/test/pool-bin/BinSwapRouterInvariant.t.sol b/test/pool-bin/BinSwapRouterInvariant.t.sol index 2e2fc85..2e67531 100644 --- a/test/pool-bin/BinSwapRouterInvariant.t.sol +++ b/test/pool-bin/BinSwapRouterInvariant.t.sol @@ -53,7 +53,7 @@ contract BinSwapRouterHandler is Test, LiquidityParamsHelper { WETH weth = new WETH(); vault = new Vault(); poolManager = new BinPoolManager(IVault(address(vault)), 500000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); token0 = new MockERC20("TestA", "A", 18); token1 = new MockERC20("TestB", "B", 18); @@ -227,26 +227,6 @@ contract BinSwapRouterHandler is Test, LiquidityParamsHelper { ); } - function _mint(uint128 amt) private { - /// @dev given that amt is cap at 100 ether, we can safely mint 10x the amount to reduce slippage in trading - amt = amt * 10; - - // step 1: Mint token to alice for add liquidity - token0.mint(alice, amt); - token1.mint(alice, amt); - token0Minted += (amt); - token1Minted += amt; - - // Step 2: add liquidity around activeId - vm.startPrank(alice); - (activeId,,) = poolManager.getSlot0(poolKey.toId()); - uint24[] memory binIds = getBinIds(activeId, 3); - IBinFungiblePositionManager.AddLiquidityParams memory addParams; - addParams = _getAddParams(poolKey, binIds, amt, amt, activeId, alice); - binFungiblePositionManager.addLiquidity(addParams); - vm.stopPrank(); - } - function _mint(uint128 amt, bool isNativePool) private { /// @dev given that amt is cap at 100 ether, we can safely mint 5x the amount to reduce slippage in trading amt = amt * 10; @@ -292,21 +272,21 @@ contract BinSwapRouterInvariant is Test { } /// @dev token minted should be either in vault or with alice - function invariant_AllTokensInVaultOrUser() public { + function invariant_AllTokensInVaultOrUser() public view { IVault vault = IVault(_handler.vault()); // verify token0 - uint256 token0BalInVault = vault.reservesOfVault(_handler.currency0()); + uint256 token0BalInVault = _handler.token0().balanceOf(address(vault)); uint256 token0WithAlice = _handler.token0().balanceOf(_handler.alice()); assertEq(token0BalInVault + token0WithAlice, _handler.token0Minted()); // verify token1 - uint256 token1BalInVault = vault.reservesOfVault(_handler.currency1()); + uint256 token1BalInVault = _handler.token1().balanceOf(address(vault)); uint256 token1WithAlice = _handler.token1().balanceOf(_handler.alice()); assertEq(token1BalInVault + token1WithAlice, _handler.token1Minted()); // eth case will also need to check router balance - uint256 nativeTokenInVault = vault.reservesOfVault(CurrencyLibrary.NATIVE); + uint256 nativeTokenInVault = address(vault).balance; uint256 nativeTokenWithAlice = _handler.alice().balance; uint256 routerBalance = address(_handler.router()).balance; assertEq(nativeTokenInVault + nativeTokenWithAlice + routerBalance, _handler.nativeTokenMinted()); diff --git a/test/pool-bin/helpers/BeforeMintSwapHook.sol b/test/pool-bin/helpers/BeforeMintSwapHook.sol index 140a21e..317e635 100644 --- a/test/pool-bin/helpers/BeforeMintSwapHook.sol +++ b/test/pool-bin/helpers/BeforeMintSwapHook.sol @@ -50,7 +50,7 @@ contract BeforeMintSwapHook is BaseBinTestHook { returns (bytes4) { // Swap and verify activeId did change - if (vault.reservesOfPoolManager(binManager, key.currency1) > 1 ether) { + if (vault.reservesOfApp(address(binManager), key.currency1) > 1 ether) { (uint24 activeIdBeforeSwap,,) = binManager.getSlot0(key.toId()); // swapForY for 1 ether @@ -70,20 +70,22 @@ contract BeforeMintSwapHook is BaseBinTestHook { PoolKey memory poolKey = data.key; if (data.swapForY) { - if (delta.amount0() > 0) { - IERC20(Currency.unwrap(poolKey.currency0)).transfer(address(vault), uint256(int256(delta.amount0()))); + if (delta.amount0() < 0) { + vault.sync(poolKey.currency0); + IERC20(Currency.unwrap(poolKey.currency0)).transfer(address(vault), uint128(-delta.amount0())); vault.settle(poolKey.currency0); } - if (delta.amount1() < 0) { - vault.take(poolKey.currency1, address(this), uint128(-delta.amount1())); + if (delta.amount1() > 0) { + vault.take(poolKey.currency1, address(this), uint256(int256(delta.amount1()))); } } else { - if (delta.amount1() > 0) { - IERC20(Currency.unwrap(poolKey.currency1)).transfer(address(vault), uint256(int256(delta.amount1()))); + if (delta.amount1() < 0) { + vault.sync(poolKey.currency1); + IERC20(Currency.unwrap(poolKey.currency1)).transfer(address(vault), uint128(-delta.amount1())); vault.settle(poolKey.currency1); } - if (delta.amount0() < 0) { - vault.take(data.key.currency0, address(this), uint128(-delta.amount0())); + if (delta.amount0() > 0) { + vault.take(data.key.currency0, address(this), uint256(int256(delta.amount0()))); } } diff --git a/test/pool-cl/CLSwapRouter.t.sol b/test/pool-cl/CLSwapRouter.t.sol index cf1ce88..82e5eb2 100644 --- a/test/pool-cl/CLSwapRouter.t.sol +++ b/test/pool-cl/CLSwapRouter.t.sol @@ -42,7 +42,7 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { WETH weth = new WETH(); vault = new Vault(); poolManager = new CLPoolManager(vault, 3000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); initializeTokens(); vm.label(Currency.unwrap(currency0), "token0"); @@ -75,7 +75,12 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { positionManager.modifyPosition( poolKey0, - ICLPoolManager.ModifyLiquidityParams({tickLower: 46053, tickUpper: 46055, liquidityDelta: 1e4 ether}), + ICLPoolManager.ModifyLiquidityParams({ + tickLower: 46053, + tickUpper: 46055, + liquidityDelta: 1e4 ether, + salt: bytes32(0) + }), new bytes(0) ); @@ -95,7 +100,12 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { positionManager.modifyPosition( poolKey1, - ICLPoolManager.ModifyLiquidityParams({tickLower: -5, tickUpper: 5, liquidityDelta: 1e5 ether}), + ICLPoolManager.ModifyLiquidityParams({ + tickLower: -5, + tickUpper: 5, + liquidityDelta: 1e5 ether, + salt: bytes32(0) + }), new bytes(0) ); @@ -117,7 +127,12 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { positionManager.modifyPosition{value: 25 ether}( poolKey2, - ICLPoolManager.ModifyLiquidityParams({tickLower: -5, tickUpper: 5, liquidityDelta: 1e5 ether}), + ICLPoolManager.ModifyLiquidityParams({ + tickLower: -5, + tickUpper: 5, + liquidityDelta: 1e5 ether, + salt: bytes32(0) + }), new bytes(0) ); @@ -397,7 +412,7 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { ); } - function testExactInput_gas() external { + function testExactInput_gasX() external { ISwapRouterBase.PathKey[] memory path = new ISwapRouterBase.PathKey[](2); path[0] = ISwapRouterBase.PathKey({ intermediateCurrency: currency1, @@ -689,40 +704,6 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot { snapEnd(); } - function testSettleAndMintRefund() external { - // transfer excess token to vault - uint256 excessTokenAmount = 1 ether; - address hacker = address(1); - MockERC20(Currency.unwrap(currency0)).mint(hacker, excessTokenAmount); - vm.startPrank(hacker); - MockERC20(Currency.unwrap(currency0)).transfer(address(vault), excessTokenAmount); - vm.stopPrank(); - - uint256 amountOut = router.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ - poolKey: poolKey0, - zeroForOne: true, - recipient: makeAddr("recipient"), - amountIn: 0.01 ether, - amountOutMinimum: 0, - sqrtPriceLimitX96: 0, - hookData: new bytes(0) - }), - block.timestamp + 100 - ); - - uint256 received = IERC20(Currency.unwrap(currency1)).balanceOf(makeAddr("recipient")); - assertEq(received, amountOut); - // considering slippage and fee, tolerance is 1% - assertApproxEqAbs(amountOut, 1 ether, amountOut / 100); - - // check currency balance in vault - { - uint256 currency0Balance = vault.balanceOf(address(this), currency0); - assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault"); - } - } - // allow refund of ETH receive() external payable {} } diff --git a/test/pool-cl/CLSwapRouterInvariant.t.sol b/test/pool-cl/CLSwapRouterInvariant.t.sol index 02f6895..c5beb8b 100644 --- a/test/pool-cl/CLSwapRouterInvariant.t.sol +++ b/test/pool-cl/CLSwapRouterInvariant.t.sol @@ -54,7 +54,7 @@ contract CLSwapRouterHandler is Test { WETH weth = new WETH(); vault = new Vault(); poolManager = new CLPoolManager(vault, 3000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); token0 = new MockERC20("TestA", "A", 18); token1 = new MockERC20("TestB", "B", 18); @@ -298,9 +298,11 @@ contract CLSwapRouterHandler is Test { abi.decode(entries[0].data, (int128, int128, uint160, uint128, int24, uint24, uint256)); if (amount0 < 0) { - token1FeeAccrued += uint128(amount1) * 3000 / 1e6; + // amt0 < 0 means token0 is swapped in, so fee taken from token0 + token0FeeAccrued += uint128(-amount0) * 3000 / 1e6; } else { - token0FeeAccrued += uint128(amount0) * 3000 / 1e6; + // else fee taken from token1 + token1FeeAccrued += uint128(-amount1) * 3000 / 1e6; } } } @@ -324,22 +326,21 @@ contract CLSwapRouterInvariant is Test { } /// @dev token minted should be either in vault or with alice - function invariant_AllTokensInVaultOrUser() public { + function invariant_AllTokensInVaultOrUser() public view { IVault vault = IVault(_handler.vault()); // token0 - uint256 token0BalInVault = vault.reservesOfVault(_handler.currency0()); + uint256 token0BalInVault = _handler.token0().balanceOf(address(vault)); uint256 token0WithAlice = _handler.token0().balanceOf(_handler.alice()); - uint256 token0Reserve = vault.reservesOfPoolManager(_handler.poolManager(), _handler.currency0()); assertEq(token0BalInVault + token0WithAlice, _handler.token0Minted()); // token1 - uint256 token1BalInVault = vault.reservesOfVault(_handler.currency1()); + uint256 token1BalInVault = _handler.token1().balanceOf(address(vault)); uint256 token1WithAlice = _handler.token1().balanceOf(_handler.alice()); assertEq(token1BalInVault + token1WithAlice, _handler.token1Minted()); // Native ETH case will have spare ETH in router - uint256 nativeTokenInVault = vault.reservesOfVault(CurrencyLibrary.NATIVE); + uint256 nativeTokenInVault = address(vault).balance; uint256 nativeTokenWithAlice = _handler.alice().balance; uint256 routerBalance = address(_handler.router()).balance; assertEq(nativeTokenInVault + nativeTokenWithAlice + routerBalance, _handler.nativeTokenMinted()); diff --git a/test/pool-cl/NonFungiblePositionManager.t.sol b/test/pool-cl/NonFungiblePositionManager.t.sol index 238e551..b673341 100644 --- a/test/pool-cl/NonFungiblePositionManager.t.sol +++ b/test/pool-cl/NonFungiblePositionManager.t.sol @@ -30,7 +30,6 @@ import {NonfungiblePositionManager} from "../../src/pool-cl/NonfungiblePositionM import {INonfungiblePositionManager} from "../../src/pool-cl/interfaces/INonfungiblePositionManager.sol"; import {LiquidityAmounts} from "../../src/pool-cl/libraries/LiquidityAmounts.sol"; import {LiquidityManagement} from "../../src/pool-cl/base/LiquidityManagement.sol"; -// import {console2} from "forge-std/console2.sol"; contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { using PoolIdLibrary for PoolKey; @@ -49,7 +48,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { function setUp() public { vault = new Vault(); poolManager = new CLPoolManager(vault, 3000); - vault.registerPoolManager(address(poolManager)); + vault.registerApp(address(poolManager)); initializeTokens(); @@ -321,7 +320,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(liquidity, 3982750054135827175977, "Liquidity from mint and liquidity from raw calculation mismatch"); assertEq(poolManager.getLiquidity(key.toId()), 3982750054135827175977, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 3982750054135827175977, "Unexpected liquidity for current position" ); @@ -428,7 +427,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(liquidity, 1991375027067913587988, "Liquidity from mint and liquidity from raw calculation mismatch"); assertEq(poolManager.getLiquidity(key.toId()), 2 * 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988 * 2, "Unexpected liquidity for current position" ); @@ -528,7 +527,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(liquidity, 1991375027067913587988, "Liquidity from mint and liquidity from raw calculation mismatch"); assertEq(poolManager.getLiquidity(key.toId()), 2 * 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988 * 2, "Unexpected liquidity for current position" ); @@ -659,7 +658,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(poolManager.getLiquidity(key.toId()), 2 * 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988 * 2, "Unexpected liquidity for current position" ); @@ -826,7 +825,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(poolManager.getLiquidity(key.toId()), 2 * 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988 * 2, "Unexpected liquidity for current position" ); @@ -1028,7 +1027,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(poolManager.getLiquidity(key.toId()), 0, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 0, "Unexpected liquidity for current position" ); @@ -1266,6 +1265,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { uint256 token0Before = IERC20(Currency.unwrap(currency0)).balanceOf(address(this)); uint256 token1Before = IERC20(Currency.unwrap(currency1)).balanceOf(address(this)); + console2.log("about to decrease liquidity"); (uint256 amount0, uint256 amount1) = nonfungiblePoolManager.decreaseLiquidity( INonfungiblePositionManager.DecreaseLiquidityParams({ tokenId: 1, @@ -1286,9 +1286,10 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(token1After - token1Before, 999999999999999999, "Unexpected currency1 consumed"); assertEq(amount1, 999999999999999999, "Actual consumed currency1 mismatch"); } + assertEq(poolManager.getLiquidity(key.toId()), 0, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 0, "Unexpected liquidity for current position" ); @@ -1635,6 +1636,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { poolManager.initialize(key, sqrtPriceX96, new bytes(0)); nonfungiblePoolManager.mint(mintParams); + // make the LPing balance of the position non-zero router.donate(key, 1 ether, 1 ether, ""); @@ -1685,7 +1687,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { } assertEq(poolManager.getLiquidity(key.toId()), 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988, "Unexpected liquidity for current position" ); @@ -1995,7 +1997,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { } assertEq(poolManager.getLiquidity(key.toId()), 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988, "Unexpected liquidity for current position" ); @@ -2090,7 +2092,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(poolManager.getLiquidity(key.toId()), 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988, "Unexpected liquidity for current position" ); @@ -2197,7 +2199,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { } assertEq(poolManager.getLiquidity(key.toId()), 1991375027067913587988, "Unexpected liquidity for the pool"); assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), + poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)), 1991375027067913587988, "Unexpected liquidity for current position" ); @@ -2338,7 +2340,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(tick, 46054, "Unexpected tick"); CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)); assertEq(info.liquidity, 1991375027067913587988, "Unexpected liquidity"); assertEq(info.feeGrowthInside0LastX128, 0, "Unexpected feeGrowthInside0LastX128"); assertEq(info.feeGrowthInside1LastX128, 0, "Unexpected feeGrowthInside1LastX128"); @@ -2362,7 +2364,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { { // non zero feeGrowthInside0LastX128 and feeGrowthInside1LastX128 CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)); assertEq(info.liquidity, 0, "Unexpected liquidity"); assertEq( info.feeGrowthInside0LastX128, @@ -2411,7 +2413,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { { // non zero feeGrowthInside0LastX128 and feeGrowthInside1LastX128 CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)); assertEq(info.liquidity, 1991375027067913587988, "Unexpected liquidity"); assertEq(info.feeGrowthInside0LastX128, 0, "Unexpected feeGrowthInside0LastX128"); assertEq(info.feeGrowthInside1LastX128, 0, "Unexpected feeGrowthInside1LastX128"); @@ -2481,7 +2483,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { ); CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)); assertEq(info.liquidity, 1, "Unexpected liquidity"); } @@ -2492,7 +2494,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(tick, 46054, "Unexpected tick"); CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46053, 46055, bytes32(0)); assertEq(info.liquidity, 1, "Unexpected liquidity"); assertEq(info.feeGrowthInside0LastX128, 0, "Unexpected feeGrowthInside0LastX128"); assertEq(info.feeGrowthInside1LastX128, 0, "Unexpected feeGrowthInside1LastX128"); @@ -2541,7 +2543,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { // decrease liquidity to 1 to better manipulate feeGrowthGlobal for position2 { CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058, bytes32(0)); nonfungiblePoolManager.decreaseLiquidity( INonfungiblePositionManager.DecreaseLiquidityParams({ @@ -2553,7 +2555,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { }) ); - info = poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058); + info = poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058, bytes32(0)); assertEq(info.liquidity, 1, "Unexpected liquidity"); } @@ -2602,7 +2604,7 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { // tokenOwed are calculated correctly even when overflow happens CLPosition.Info memory info = - poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058); + poolManager.getPosition(poolKey.toId(), address(nonfungiblePoolManager), 46055, 46058, bytes32(0)); // positionInfo from nonfungiblePoolManager has been synced ( , @@ -2625,98 +2627,4 @@ contract NonFungiblePositionManagerTest is TokenFixture, Test, GasSnapshot { assertEq(tokenOwed1, 1000000000000000000, "Unexpected tokenOwed1"); } } - - function testSettleAndMintRefund() external { - PoolKey memory key = PoolKey({ - currency0: currency0, - currency1: currency1, - hooks: IHooks(address(0)), - poolManager: poolManager, - fee: uint24(3000), - // 0 ~ 15 hookRegistrationMap = nil - // 16 ~ 24 tickSpacing = 1 - parameters: bytes32(uint256(0x10000)) - }); - - int24 tickLower = 46053; - int24 tickUpper = 46055; - uint256 amount0Desired = 1 ether; - uint256 amount1Desired = 2 ether; - - // transfer excess token to vault - uint256 excessTokenAmount = 1 ether; - IERC20(Currency.unwrap(currency0)).transfer(address(vault), excessTokenAmount); - - { - uint160 sqrtPriceX96 = uint160(10 * FixedPoint96.Q96); - poolManager.initialize(key, sqrtPriceX96, new bytes(0)); - - uint128 liquidityExpected = LiquidityAmounts.getLiquidityForAmounts( - sqrtPriceX96, - TickMath.getSqrtRatioAtTick(tickLower), - TickMath.getSqrtRatioAtTick(tickUpper), - amount0Desired, - amount1Desired - ); - - vm.expectEmit(true, true, true, false); - emit IncreaseLiquidity(1, liquidityExpected, 0, 0); - } - - (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) = nonfungiblePoolManager.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: tickLower, - tickUpper: tickUpper, - amount0Desired: amount0Desired, - amount1Desired: amount1Desired, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: type(uint256).max - }) - ); - - // token consumed - { - uint256 token0Left = IERC20(Currency.unwrap(currency0)).balanceOf(address(this)); - uint256 token1Left = IERC20(Currency.unwrap(currency1)).balanceOf(address(this)); - // 1.982e16 roughly 0.02 ether, need to add 1 ether which is unexpected currency0 amount - assertEq(1000 ether - token0Left - excessTokenAmount, 19824513708386292, "Unexpected currency0 consumed"); - assertEq(amount0, 19824513708386292, "Actual consumed currency0 mismatch"); - // 1e18 i.e. 2 ether, make sense because price is 100 - assertEq(1000 ether - token1Left, 2000000000000000000, "Unexpected currency1 consumed"); - assertEq(amount1, 2000000000000000000, "Actual consumed currency1 mismatch"); - } - - // check currency balance in vault - { - uint256 currency0Balance = vault.balanceOf(address(this), currency0); - assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault"); - } - - // tick lower and tick upper - { - (,,,,, int24 _tickLower, int24 _tickUpper,,,,,) = nonfungiblePoolManager.positions(1); - assertEq(_tickLower, tickLower, "Unexpected tickLower"); - assertEq(_tickUpper, tickUpper, "Unexpected tickUpper"); - } - - // token id starts from 1 - assertEq(tokenId, 1, "Unexpected tokenId"); - - assertEq(liquidity, 3982750054135827175977, "Liquidity from mint and liquidity from raw calculation mismatch"); - assertEq(poolManager.getLiquidity(key.toId()), 3982750054135827175977, "Unexpected liquidity for the pool"); - assertEq( - poolManager.getLiquidity(key.toId(), address(nonfungiblePoolManager), 46053, 46055), - 3982750054135827175977, - "Unexpected liquidity for current position" - ); - - assertEq( - nonfungiblePoolManager.balanceOf(address(this)), 1, "Unexpected balance of the position owner after mint" - ); - - assertEq(nonfungiblePoolManager.ownerOf(tokenId), address(this), "Unexpected owner of the position"); - } }