diff --git a/.gitmodules b/.gitmodules index 8bf9a45..80d4583 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,9 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "lib/pancake-v4-core"] - path = lib/pancake-v4-core - url = https://github.com/pancakeswap/pancake-v4-core -[submodule "lib/pancake-v4-periphery"] - path = lib/pancake-v4-periphery - url = https://github.com/pancakeswap/pancake-v4-periphery +[submodule "lib/forge-gas-snapshot"] + path = lib/forge-gas-snapshot + url = https://github.com/marktoda/forge-gas-snapshot +[submodule "lib/pancake-v4-universal-router"] + path = lib/pancake-v4-universal-router + url = https://github.com/pancakeswap/pancake-v4-universal-router diff --git a/foundry.toml b/foundry.toml index 3f17701..28dc252 100644 --- a/foundry.toml +++ b/foundry.toml @@ -11,12 +11,7 @@ optimizer_runs = 1000 via_ir = true evm_version = 'cancun' ffi = true -fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}] -remappings = [ - "@pancakeswap/v4-core/=lib/pancake-v4-core/", - "@pancakeswap/v4-periphery/=lib/pancake-v4-periphery/", - "@openzeppelin/=lib/pancake-v4-periphery/lib/openzeppelin-contracts/" -] +fs_permissions = [{ access = "read-write", path = ".forge-snapshots/" }] [profile.default.fuzz] runs = 1000 diff --git a/lib/forge-gas-snapshot b/lib/forge-gas-snapshot new file mode 160000 index 0000000..9fc447c --- /dev/null +++ b/lib/forge-gas-snapshot @@ -0,0 +1 @@ +Subproject commit 9fc447c732c89b6dd6352c096042d8d82b44faed diff --git a/lib/forge-std b/lib/forge-std index 19891e6..1714bee 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 19891e6a0b5474b9ea6827ddb90bb9388f7acfc0 +Subproject commit 1714bee72e286e73f76e320d110e0eaf5c4e649d diff --git a/lib/pancake-v4-core b/lib/pancake-v4-core deleted file mode 160000 index 52b2168..0000000 --- a/lib/pancake-v4-core +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52b2168f24d2a2fab9a905f5aacf0889b9521fe4 diff --git a/lib/pancake-v4-periphery b/lib/pancake-v4-periphery deleted file mode 160000 index 0355708..0000000 --- a/lib/pancake-v4-periphery +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 03557080be1ab31022664a980f859f4f5e89157b diff --git a/lib/pancake-v4-universal-router b/lib/pancake-v4-universal-router new file mode 160000 index 0000000..8cefacb --- /dev/null +++ b/lib/pancake-v4-universal-router @@ -0,0 +1 @@ +Subproject commit 8cefacb472e8fdecdb7b0391527d42b6310b817d diff --git a/remappings.txt b/remappings.txt index f251d9b..4b73269 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,3 +1,8 @@ -@pancakeswap/v4-core/=lib/pancake-v4-core/ -@pancakeswap/v4-periphery/=lib/pancake-v4-periphery/ -@openzeppelin/=lib/pancake-v4-periphery/lib/openzeppelin-contracts/ +forge-std/=lib/forge-std/src/ +ds-test/=lib/forge-std/lib/ds-test/src/ +openzeppelin-contracts/=lib/pancake-v4-universal-router/lib/pancake-v4-periphery/lib/pancake-v4-core/lib/openzeppelin-contracts/ +solmate/=lib/pancake-v4-universal-router/lib/pancake-v4-periphery/lib/pancake-v4-core/lib/solmate/ +pancake-v4-core/=lib/pancake-v4-universal-router/lib/pancake-v4-periphery/lib/pancake-v4-core/ +pancake-v4-periphery/=lib/pancake-v4-universal-router/lib/pancake-v4-periphery/ +pancake-v4-universal-router/=lib/pancake-v4-universal-router/ +permit2/=lib/pancake-v4-universal-router/lib/pancake-v4-periphery/lib/permit2/ diff --git a/src/pool-bin/BinBaseHook.sol b/src/pool-bin/BinBaseHook.sol index bc88044..ee611dc 100644 --- a/src/pool-bin/BinBaseHook.sol +++ b/src/pool-bin/BinBaseHook.sol @@ -16,15 +16,15 @@ import { HOOKS_AFTER_SWAP_RETURNS_DELTA_OFFSET, HOOKS_AFTER_MINT_RETURNS_DELTA_OFFSET, HOOKS_AFTER_BURN_RETURNS_DELTA_OFFSET -} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinHooks.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {BalanceDelta} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {BeforeSwapDelta} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {IHooks} from "@pancakeswap/v4-core/src/interfaces/IHooks.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {IBinHooks} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinHooks.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; +} from "pancake-v4-core/src/pool-bin/interfaces/IBinHooks.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {BalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {BeforeSwapDelta} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {IHooks} from "pancake-v4-core/src/interfaces/IHooks.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {IBinHooks} from "pancake-v4-core/src/pool-bin/interfaces/IBinHooks.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol"; /// @notice BaseHook abstract contract for Bin pool hooks to inherit abstract contract BinBaseHook is IBinHooks { @@ -124,7 +124,7 @@ abstract contract BinBaseHook is IBinHooks { function beforeMint(address, PoolKey calldata, IBinPoolManager.MintParams calldata, bytes calldata) external virtual - returns (bytes4) + returns (bytes4, uint24) { revert HookNotImplemented(); } diff --git a/src/pool-bin/geomean-oracle/BinGeomeanOracle.sol b/src/pool-bin/geomean-oracle/BinGeomeanOracle.sol index 3c5973c..35d6b61 100644 --- a/src/pool-bin/geomean-oracle/BinGeomeanOracle.sol +++ b/src/pool-bin/geomean-oracle/BinGeomeanOracle.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; import { HOOKS_BEFORE_INITIALIZE_OFFSET, HOOKS_AFTER_INITIALIZE_OFFSET, @@ -14,13 +14,13 @@ import { HOOKS_AFTER_SWAP_OFFSET, HOOKS_BEFORE_DONATE_OFFSET, HOOKS_AFTER_DONATE_OFFSET -} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinHooks.sol"; -import {IPoolManager} from "@pancakeswap/v4-core/src/interfaces/IPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {BalanceDelta, BalanceDeltaLibrary} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; +} from "pancake-v4-core/src/pool-bin/interfaces/IBinHooks.sol"; +import {IPoolManager} from "pancake-v4-core/src/interfaces/IPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {BalanceDelta, BalanceDeltaLibrary} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; import {BinBaseHook} from "../BinBaseHook.sol"; import {OracleHelper} from "./libraries/OracleHelper.sol"; @@ -92,9 +92,9 @@ contract BinGeomeanOracle is BinBaseHook { PoolKey calldata key, IBinPoolManager.MintParams calldata params, bytes calldata hookData - ) external override poolManagerOnly returns (bytes4) { + ) external override poolManagerOnly returns (bytes4, uint24) { _updatePool(key); - return this.beforeMint.selector; + return (this.beforeMint.selector, 0); } function beforeBurn( diff --git a/src/pool-bin/limit-order/BinLimitOrder.sol b/src/pool-bin/limit-order/BinLimitOrder.sol index 0018e6a..9114121 100644 --- a/src/pool-bin/limit-order/BinLimitOrder.sol +++ b/src/pool-bin/limit-order/BinLimitOrder.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; import { HOOKS_BEFORE_INITIALIZE_OFFSET, HOOKS_AFTER_INITIALIZE_OFFSET, @@ -14,23 +14,23 @@ import { HOOKS_AFTER_SWAP_OFFSET, HOOKS_BEFORE_DONATE_OFFSET, HOOKS_AFTER_DONATE_OFFSET -} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinHooks.sol"; -import {FullMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/FullMath.sol"; -import {SafeCast} from "@pancakeswap/v4-core/src/libraries/SafeCast.sol"; -import {BinPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; -import {IPoolManager} from "@pancakeswap/v4-core/src/interfaces/IPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {Currency, CurrencyLibrary} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {BalanceDelta} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; -import {LiquidityConfigurations} from "@pancakeswap/v4-core/src/pool-bin/libraries/math/LiquidityConfigurations.sol"; -import {PackedUint128Math} from "@pancakeswap/v4-core/src/pool-bin/libraries/math/PackedUint128Math.sol"; -import {BinPool} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPool.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +} from "pancake-v4-core/src/pool-bin/interfaces/IBinHooks.sol"; +import {FullMath} from "pancake-v4-core/src/pool-cl/libraries/FullMath.sol"; +import {SafeCast} from "pancake-v4-core/src/libraries/SafeCast.sol"; +import {BinPoolParametersHelper} from "pancake-v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; +import {IPoolManager} from "pancake-v4-core/src/interfaces/IPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {Currency, CurrencyLibrary} from "pancake-v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol"; +import {LiquidityConfigurations} from "pancake-v4-core/src/pool-bin/libraries/math/LiquidityConfigurations.sol"; +import {PackedUint128Math} from "pancake-v4-core/src/pool-bin/libraries/math/PackedUint128Math.sol"; +import {BinPool} from "pancake-v4-core/src/pool-bin/libraries/BinPool.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {BinBaseHook} from "../BinBaseHook.sol"; @@ -315,13 +315,13 @@ contract BinLimitOrder is BinBaseHook { IERC20(Currency.unwrap(key.currency0)).safeTransferFrom( owner, address(vault), uint256(uint128(-delta.amount0())) ); - vault.settle(key.currency0); + vault.settle(); } else { vault.sync(key.currency1); IERC20(Currency.unwrap(key.currency1)).safeTransferFrom( owner, address(vault), uint256(uint128(-delta.amount1())) ); - vault.settle(key.currency1); + vault.settle(); } } diff --git a/src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol b/src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol index 6126d02..fc022c7 100644 --- a/src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol +++ b/src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.24; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; import {BinBaseHook} from "../BinBaseHook.sol"; diff --git a/src/pool-cl/CLBaseHook.sol b/src/pool-cl/CLBaseHook.sol index 46bec23..348f263 100644 --- a/src/pool-cl/CLBaseHook.sol +++ b/src/pool-cl/CLBaseHook.sol @@ -16,15 +16,15 @@ import { HOOKS_AFTER_SWAP_RETURNS_DELTA_OFFSET, HOOKS_AFTER_ADD_LIQUIDIY_RETURNS_DELTA_OFFSET, HOOKS_AFTER_REMOVE_LIQUIDIY_RETURNS_DELTA_OFFSET -} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLHooks.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {BalanceDelta} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {BeforeSwapDelta} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {IHooks} from "@pancakeswap/v4-core/src/interfaces/IHooks.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {ICLHooks} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLHooks.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; +} from "pancake-v4-core/src/pool-cl/interfaces/ICLHooks.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {BalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {BeforeSwapDelta} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {IHooks} from "pancake-v4-core/src/interfaces/IHooks.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {ICLHooks} from "pancake-v4-core/src/pool-cl/interfaces/ICLHooks.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; /// @notice BaseHook abstract contract for CL pool hooks to inherit abstract contract CLBaseHook is ICLHooks { diff --git a/src/pool-cl/full-range/CLFullRange.sol b/src/pool-cl/full-range/CLFullRange.sol index c8f848d..74a09dd 100644 --- a/src/pool-cl/full-range/CLFullRange.sol +++ b/src/pool-cl/full-range/CLFullRange.sol @@ -2,28 +2,28 @@ pragma solidity ^0.8.19; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {TickMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickMath.sol"; -import {TickBitmap} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickBitmap.sol"; -import {SqrtPriceMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/SqrtPriceMath.sol"; -import {FixedPoint96} from "@pancakeswap/v4-core/src/pool-cl/libraries/FixedPoint96.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {IPoolManager} from "@pancakeswap/v4-core/src/interfaces/IPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {Currency, CurrencyLibrary} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {BalanceDelta} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; -import {SafeCast} from "@pancakeswap/v4-core/src/libraries/SafeCast.sol"; -import {FullMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/FullMath.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; -import {IERC20Metadata} from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {TickBitmap} from "pancake-v4-core/src/pool-cl/libraries/TickBitmap.sol"; +import {SqrtPriceMath} from "pancake-v4-core/src/pool-cl/libraries/SqrtPriceMath.sol"; +import {FixedPoint96} from "pancake-v4-core/src/pool-cl/libraries/FixedPoint96.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {IPoolManager} from "pancake-v4-core/src/interfaces/IPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {Currency, CurrencyLibrary} from "pancake-v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {SafeCast} from "pancake-v4-core/src/libraries/SafeCast.sol"; +import {FullMath} from "pancake-v4-core/src/pool-cl/libraries/FullMath.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol"; +import {IERC20Metadata} from "openzeppelin-contracts/contracts/interfaces/IERC20Metadata.sol"; +import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {CLBaseHook} from "../CLBaseHook.sol"; import {LiquidityAmounts} from "./libraries/LiquidityAmounts.sol"; @@ -331,7 +331,7 @@ contract CLFullRange is CLBaseHook { function _settleDelta(address sender, Currency currency, uint128 amount) internal { if (currency.isNative()) { - vault.settle{value: amount}(currency); + vault.settle{value: amount}(); } else { vault.sync(currency); if (sender == address(this)) { @@ -339,7 +339,7 @@ contract CLFullRange is CLBaseHook { } else { IERC20(Currency.unwrap(currency)).safeTransferFrom(sender, address(vault), amount); } - vault.settle(currency); + vault.settle(); } } diff --git a/src/pool-cl/full-range/libraries/LiquidityAmounts.sol b/src/pool-cl/full-range/libraries/LiquidityAmounts.sol index 851de11..65aa7af 100644 --- a/src/pool-cl/full-range/libraries/LiquidityAmounts.sol +++ b/src/pool-cl/full-range/libraries/LiquidityAmounts.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.19; -import "@pancakeswap/v4-core/src/pool-cl/libraries/FullMath.sol"; -import "@pancakeswap/v4-core/src/pool-cl/libraries/FixedPoint96.sol"; +import "pancake-v4-core/src/pool-cl/libraries/FullMath.sol"; +import "pancake-v4-core/src/pool-cl/libraries/FixedPoint96.sol"; /// @title Liquidity amount functions /// @notice Provides functions for computing liquidity amounts from token amounts and prices diff --git a/src/pool-cl/full-range/libraries/PancakeV4ERC20.sol b/src/pool-cl/full-range/libraries/PancakeV4ERC20.sol index 0e922b1..98662fc 100644 --- a/src/pool-cl/full-range/libraries/PancakeV4ERC20.sol +++ b/src/pool-cl/full-range/libraries/PancakeV4ERC20.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.19; -import {ERC20} from "solmate/tokens/ERC20.sol"; -import {Owned} from "solmate/auth/Owned.sol"; +import {ERC20} from "solmate/src/tokens/ERC20.sol"; +import {Owned} from "solmate/src/auth/Owned.sol"; contract PancakeV4ERC20 is ERC20, Owned { constructor(string memory name, string memory symbol) ERC20(name, symbol, 18) Owned(msg.sender) {} diff --git a/src/pool-cl/geomean-oracle/CLGeomeanOracle.sol b/src/pool-cl/geomean-oracle/CLGeomeanOracle.sol index cde671e..1499dc5 100644 --- a/src/pool-cl/geomean-oracle/CLGeomeanOracle.sol +++ b/src/pool-cl/geomean-oracle/CLGeomeanOracle.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.19; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {TickMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickMath.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {IPoolManager} from "@pancakeswap/v4-core/src/interfaces/IPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {IPoolManager} from "pancake-v4-core/src/interfaces/IPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; import {CLBaseHook} from "../CLBaseHook.sol"; import {Oracle} from "./libraries/Oracle.sol"; @@ -98,7 +98,7 @@ contract CLGeomeanOracle is CLBaseHook { // In other words, there may only be one pool per pair of tokens that use // this hook. The tick spacing is set to the maximum because we only allow // full range liquidity in this pool. - if (key.fee != 0 || key.parameters.getTickSpacing() != poolManager.MAX_TICK_SPACING()) { + if (key.fee != 0 || key.parameters.getTickSpacing() != TickMath.MAX_TICK_SPACING) { revert OnlyOneOraclePoolAllowed(); } return this.beforeInitialize.selector; @@ -133,7 +133,7 @@ contract CLGeomeanOracle is CLBaseHook { ICLPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external override returns (bytes4) { - int24 maxTickSpacing = poolManager.MAX_TICK_SPACING(); + int24 maxTickSpacing = TickMath.MAX_TICK_SPACING; if ( params.tickLower != TickMath.minUsableTick(maxTickSpacing) || params.tickUpper != TickMath.maxUsableTick(maxTickSpacing) diff --git a/src/pool-cl/limit-order/CLLimitOrder.sol b/src/pool-cl/limit-order/CLLimitOrder.sol index 8909bc1..4149712 100644 --- a/src/pool-cl/limit-order/CLLimitOrder.sol +++ b/src/pool-cl/limit-order/CLLimitOrder.sol @@ -2,21 +2,21 @@ pragma solidity ^0.8.19; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {FullMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/FullMath.sol"; -import {SafeCast} from "@pancakeswap/v4-core/src/libraries/SafeCast.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {IPoolManager} from "@pancakeswap/v4-core/src/interfaces/IPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {Currency, CurrencyLibrary} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {BalanceDelta} from "@pancakeswap/v4-core/src/types/BalanceDelta.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {FullMath} from "pancake-v4-core/src/pool-cl/libraries/FullMath.sol"; +import {SafeCast} from "pancake-v4-core/src/libraries/SafeCast.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {IPoolManager} from "pancake-v4-core/src/interfaces/IPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {Currency, CurrencyLibrary} from "pancake-v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "pancake-v4-core/src/types/BalanceDelta.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {IERC1155Receiver} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {CLBaseHook} from "../CLBaseHook.sol"; @@ -304,7 +304,7 @@ contract CLLimitOrder is CLBaseHook { IERC20(Currency.unwrap(key.currency0)).safeTransferFrom( owner, address(vault), uint256(uint128(-delta.amount0())) ); - vault.settle(key.currency0); + vault.settle(); } else { if (delta.amount0() != 0) revert InRange(); if (zeroForOne) revert CrossedRange(); @@ -312,7 +312,7 @@ contract CLLimitOrder is CLBaseHook { IERC20(Currency.unwrap(key.currency1)).safeTransferFrom( owner, address(vault), uint256(uint128(-delta.amount1())) ); - vault.settle(key.currency1); + vault.settle(); } } diff --git a/src/pool-cl/vecake-exclusive/CLVeCakeExclusiveHook.sol b/src/pool-cl/vecake-exclusive/CLVeCakeExclusiveHook.sol index 2c7bd3a..45f832f 100644 --- a/src/pool-cl/vecake-exclusive/CLVeCakeExclusiveHook.sol +++ b/src/pool-cl/vecake-exclusive/CLVeCakeExclusiveHook.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.19; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@pancakeswap/v4-core/src/types/BeforeSwapDelta.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "pancake-v4-core/src/types/BeforeSwapDelta.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; import {CLBaseHook} from "../CLBaseHook.sol"; diff --git a/test/pool-bin/BinGeomeanOracle.t.sol b/test/pool-bin/BinGeomeanOracle.t.sol index 3ab1011..98839cd 100644 --- a/test/pool-bin/BinGeomeanOracle.t.sol +++ b/test/pool-bin/BinGeomeanOracle.t.sol @@ -3,27 +3,29 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {BinPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; -import {Constants} from "@pancakeswap/v4-core/src/pool-bin/libraries/Constants.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {IBinSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinSwapRouterBase.sol"; -import {BinSwapRouter} from "@pancakeswap/v4-periphery/src/pool-bin/BinSwapRouter.sol"; -import {BinFungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-bin/BinFungiblePositionManager.sol"; -import {IBinFungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinFungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; - +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {BinPoolParametersHelper} from "pancake-v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; +import {Constants} from "pancake-v4-core/src/pool-bin/libraries/Constants.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; +import {IBinRouterBase} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinRouterBase.sol"; +import {IBinPositionManager} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinPositionManager.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; + +import {MockBinPositionManager} from "./helpers/MockBinPositionManager.sol"; +import {MockBinSwapRouter} from "./helpers/MockBinSwapRouter.sol"; import {BinGeomeanOracle} from "../../src/pool-bin/geomean-oracle/BinGeomeanOracle.sol"; import {Deployers} from "./helpers/Deployers.sol"; -contract BinGeomeanOracleHookTest is Test, Deployers { +contract BinGeomeanOracleHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using BinPoolParametersHelper for bytes32; @@ -31,8 +33,9 @@ contract BinGeomeanOracleHookTest is Test, Deployers { IVault vault; IBinPoolManager poolManager; - BinFungiblePositionManager bfp; - BinSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockBinPositionManager bpm; + MockBinSwapRouter swapRouter; BinGeomeanOracle geomeanOracle; @@ -49,14 +52,17 @@ contract BinGeomeanOracleHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); geomeanOracle = new BinGeomeanOracle(poolManager); - bfp = new BinFungiblePositionManager(vault, poolManager, address(0)); - swapRouter = new BinSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + bpm = new MockBinPositionManager(vault, poolManager, permit2); + swapRouter = new MockBinSwapRouter(vault, poolManager); - address[2] memory approvalAddress = [address(bfp), address(swapRouter)]; + address[3] memory approvalAddress = [address(bpm), address(swapRouter), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(bpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(bpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -78,7 +84,13 @@ contract BinGeomeanOracleHookTest is Test, Deployers { fee: 1, parameters: bytes32(uint256(geomeanOracle.getHooksRegistrationBitmap())).setBinStep(60) }); - vm.expectRevert(BinGeomeanOracle.OnlyOneOraclePoolAllowed.selector); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(geomeanOracle), + abi.encodeWithSelector(BinGeomeanOracle.OnlyOneOraclePoolAllowed.selector) + ) + ); poolManager.initialize(k, BIN_ID_1_1, ZERO_BYTES); } @@ -112,8 +124,8 @@ contract BinGeomeanOracleHookTest is Test, Deployers { distributionX[0] = Constants.PRECISION; uint256[] memory distributionY = new uint256[](numBins); distributionY[0] = Constants.PRECISION; - (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bfp.addLiquidity( - IBinFungiblePositionManager.AddLiquidityParams({ + (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bpm.addLiquidity( + IBinPositionManager.BinAddLiquidityParams({ poolKey: key, amount0: 1e18, amount1: 1e18, @@ -124,8 +136,7 @@ contract BinGeomeanOracleHookTest is Test, Deployers { deltaIds: deltaIds, distributionX: distributionX, distributionY: distributionY, - to: address(this), - deadline: block.timestamp + to: address(this) }) ); @@ -153,8 +164,8 @@ contract BinGeomeanOracleHookTest is Test, Deployers { distributionX[0] = Constants.PRECISION; uint256[] memory distributionY = new uint256[](numBins); distributionY[0] = Constants.PRECISION; - (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bfp.addLiquidity( - IBinFungiblePositionManager.AddLiquidityParams({ + (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bpm.addLiquidity( + IBinPositionManager.BinAddLiquidityParams({ poolKey: key, amount0: 1e18, amount1: 1e18, @@ -165,8 +176,7 @@ contract BinGeomeanOracleHookTest is Test, Deployers { deltaIds: deltaIds, distributionX: distributionX, distributionY: distributionY, - to: address(this), - deadline: block.timestamp + to: address(this) }) ); @@ -195,8 +205,8 @@ contract BinGeomeanOracleHookTest is Test, Deployers { distributionX[0] = Constants.PRECISION; uint256[] memory distributionY = new uint256[](numBins); distributionY[0] = Constants.PRECISION; - (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bfp.addLiquidity( - IBinFungiblePositionManager.AddLiquidityParams({ + (,, uint256[] memory tokenIds, uint256[] memory liquidityMinted) = bpm.addLiquidity( + IBinPositionManager.BinAddLiquidityParams({ poolKey: key, amount0: 1e18, amount1: 1e18, @@ -207,22 +217,26 @@ contract BinGeomeanOracleHookTest is Test, Deployers { deltaIds: deltaIds, distributionX: distributionX, distributionY: distributionY, - to: address(this), - deadline: block.timestamp + to: address(this) }) ); - vm.expectRevert(BinGeomeanOracle.OraclePoolMustLockLiquidity.selector); - bfp.removeLiquidity( - IBinFungiblePositionManager.RemoveLiquidityParams({ + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(geomeanOracle), + abi.encodeWithSelector(BinGeomeanOracle.OraclePoolMustLockLiquidity.selector) + ) + ); + + bpm.removeLiquidity( + IBinPositionManager.BinRemoveLiquidityParams({ poolKey: key, amount0Min: 0, amount1Min: 0, ids: tokenIds, amounts: liquidityMinted, - from: address(this), - to: address(this), - deadline: block.timestamp + from: address(this) }) ); } diff --git a/test/pool-bin/BinLimitOrder.t.sol b/test/pool-bin/BinLimitOrder.t.sol index 553ca2c..bdd2200 100644 --- a/test/pool-bin/BinLimitOrder.t.sol +++ b/test/pool-bin/BinLimitOrder.t.sol @@ -3,28 +3,29 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {BinPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; -import {BinPosition} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPosition.sol"; -import {Constants} from "@pancakeswap/v4-core/src/pool-bin/libraries/Constants.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {IBinSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinSwapRouterBase.sol"; -import {BinSwapRouter} from "@pancakeswap/v4-periphery/src/pool-bin/BinSwapRouter.sol"; -import {BinFungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-bin/BinFungiblePositionManager.sol"; -import {IBinFungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinFungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {BinPoolParametersHelper} from "pancake-v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; +import {BinPosition} from "pancake-v4-core/src/pool-bin/libraries/BinPosition.sol"; +import {Constants} from "pancake-v4-core/src/pool-bin/libraries/Constants.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; +import {IBinPositionManager} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinPositionManager.sol"; +import {IBinRouterBase} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinRouterBase.sol"; import {BinLimitOrder, Epoch, EpochLibrary} from "../../src/pool-bin/limit-order/BinLimitOrder.sol"; +import {MockBinPositionManager} from "./helpers/MockBinPositionManager.sol"; +import {MockBinSwapRouter} from "./helpers/MockBinSwapRouter.sol"; import {Deployers} from "./helpers/Deployers.sol"; -contract BinLimitOrderHookTest is Test, Deployers { +contract BinLimitOrderHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using BinPoolParametersHelper for bytes32; @@ -32,8 +33,9 @@ contract BinLimitOrderHookTest is Test, Deployers { IVault vault; IBinPoolManager poolManager; - BinFungiblePositionManager bfp; - BinSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockBinPositionManager bpm; + MockBinSwapRouter swapRouter; BinLimitOrder limitOrder; @@ -50,14 +52,17 @@ contract BinLimitOrderHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); limitOrder = new BinLimitOrder(poolManager); - bfp = new BinFungiblePositionManager(vault, poolManager, address(0)); - swapRouter = new BinSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + bpm = new MockBinPositionManager(vault, poolManager, permit2); + swapRouter = new MockBinSwapRouter(vault, poolManager); - address[3] memory approvalAddress = [address(bfp), address(swapRouter), address(limitOrder)]; + address[4] memory approvalAddress = [address(bpm), address(swapRouter), address(limitOrder), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(bpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(bpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -90,8 +95,8 @@ contract BinLimitOrderHookTest is Test, Deployers { distributionY[2] = Constants.PRECISION / 3; distributionY[3] = 0; distributionY[4] = 0; - bfp.addLiquidity( - IBinFungiblePositionManager.AddLiquidityParams({ + bpm.addLiquidity( + IBinPositionManager.BinAddLiquidityParams({ poolKey: key, amount0: 3 * 1e18, amount1: 3 * 1e18, @@ -102,8 +107,7 @@ contract BinLimitOrderHookTest is Test, Deployers { deltaIds: deltaIds, distributionX: distributionX, distributionY: distributionY, - to: address(this), - deadline: block.timestamp + to: address(this) }) ); } @@ -200,10 +204,9 @@ contract BinLimitOrderHookTest is Test, Deployers { limitOrder.place(key, BIN_ID_1_1 + 1, true, 1e18); swapRouter.exactInputSingle( - IBinSwapRouterBase.V4BinExactInputSingleParams({ + IBinRouterBase.BinSwapExactInputSingleParams({ poolKey: key, swapForY: false, - recipient: address(this), amountIn: 4 * 1e18, amountOutMinimum: 0, hookData: ZERO_BYTES diff --git a/test/pool-bin/BinVeCakeExclusiveHook.t.sol b/test/pool-bin/BinVeCakeExclusiveHook.t.sol index 953f97d..dd719fc 100644 --- a/test/pool-bin/BinVeCakeExclusiveHook.t.sol +++ b/test/pool-bin/BinVeCakeExclusiveHook.t.sol @@ -3,27 +3,28 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {BinPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; -import {Constants} from "@pancakeswap/v4-core/src/pool-bin/libraries/Constants.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {IBinSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinSwapRouterBase.sol"; -import {BinSwapRouter} from "@pancakeswap/v4-periphery/src/pool-bin/BinSwapRouter.sol"; -import {BinFungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-bin/BinFungiblePositionManager.sol"; -import {IBinFungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-bin/interfaces/IBinFungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {BinPoolParametersHelper} from "pancake-v4-core/src/pool-bin/libraries/BinPoolParametersHelper.sol"; +import {Constants} from "pancake-v4-core/src/pool-bin/libraries/Constants.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {IBinPositionManager} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinPositionManager.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; +import {IBinRouterBase} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinRouterBase.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; -import {BinVeCakeExclusiveHook} from "../../src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol"; import {Deployers} from "./helpers/Deployers.sol"; +import {MockBinPositionManager} from "./helpers/MockBinPositionManager.sol"; +import {MockBinSwapRouter} from "./helpers/MockBinSwapRouter.sol"; +import {BinVeCakeExclusiveHook} from "../../src/pool-bin/vecake-exclusive/BinVeCakeExclusiveHook.sol"; -contract BinVeCakeExclusiveHookTest is Test, Deployers { +contract BinVeCakeExclusiveHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using BinPoolParametersHelper for bytes32; @@ -31,8 +32,9 @@ contract BinVeCakeExclusiveHookTest is Test, Deployers { IVault vault; IBinPoolManager poolManager; - BinFungiblePositionManager bfp; - BinSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockBinPositionManager bpm; + MockBinSwapRouter swapRouter; BinVeCakeExclusiveHook veCakeExclusiveHook; @@ -55,14 +57,17 @@ contract BinVeCakeExclusiveHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); veCakeExclusiveHook = new BinVeCakeExclusiveHook(poolManager, address(veCake)); - bfp = new BinFungiblePositionManager(vault, poolManager, address(0)); - swapRouter = new BinSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + bpm = new MockBinPositionManager(vault, poolManager, permit2); + swapRouter = new MockBinSwapRouter(vault, poolManager); - address[2] memory approvalAddress = [address(bfp), address(swapRouter)]; + address[3] memory approvalAddress = [address(bpm), address(swapRouter), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(bpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(bpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -83,8 +88,8 @@ contract BinVeCakeExclusiveHookTest is Test, Deployers { distributionX[0] = Constants.PRECISION; uint256[] memory distributionY = new uint256[](numBins); distributionY[0] = Constants.PRECISION; - bfp.addLiquidity( - IBinFungiblePositionManager.AddLiquidityParams({ + bpm.addLiquidity( + IBinPositionManager.BinAddLiquidityParams({ poolKey: key, amount0: 1e18, amount1: 1e18, @@ -95,42 +100,43 @@ contract BinVeCakeExclusiveHookTest is Test, Deployers { deltaIds: deltaIds, distributionX: distributionX, distributionY: distributionY, - to: address(this), - deadline: block.timestamp + to: address(this) }) ); } function test_SwapRevertIfNotHolder() public { - vm.startPrank(nonHolder, nonHolder); - vm.expectRevert(BinVeCakeExclusiveHook.NotVeCakeHolder.selector); + vm.prank(nonHolder, nonHolder); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(veCakeExclusiveHook), + abi.encodeWithSelector(BinVeCakeExclusiveHook.NotVeCakeHolder.selector) + ) + ); swapRouter.exactInputSingle( - IBinSwapRouterBase.V4BinExactInputSingleParams({ + IBinRouterBase.BinSwapExactInputSingleParams({ poolKey: key, swapForY: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, hookData: ZERO_BYTES }), block.timestamp ); - vm.stopPrank(); } function test_Swap() public { - vm.startPrank(address(this), address(this)); + vm.prank(address(this), address(this)); swapRouter.exactInputSingle( - IBinSwapRouterBase.V4BinExactInputSingleParams({ + IBinRouterBase.BinSwapExactInputSingleParams({ poolKey: key, swapForY: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, hookData: ZERO_BYTES }), block.timestamp ); - vm.stopPrank(); } } diff --git a/test/pool-bin/helpers/Deployers.sol b/test/pool-bin/helpers/Deployers.sol index 90711bf..8de2813 100644 --- a/test/pool-bin/helpers/Deployers.sol +++ b/test/pool-bin/helpers/Deployers.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.24; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; -import {Hooks} from "@pancakeswap/v4-core/src/libraries/Hooks.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {IHooks} from "@pancakeswap/v4-core/src/interfaces/IHooks.sol"; -import {IBinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; -import {BinPoolManager} from "@pancakeswap/v4-core/src/pool-bin/BinPoolManager.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {LPFeeLibrary} from "@pancakeswap/v4-core/src/libraries/LPFeeLibrary.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {IHooks} from "pancake-v4-core/src/interfaces/IHooks.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {BinPoolManager} from "pancake-v4-core/src/pool-bin/BinPoolManager.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {LPFeeLibrary} from "pancake-v4-core/src/libraries/LPFeeLibrary.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; contract Deployers { using LPFeeLibrary for uint24; diff --git a/test/pool-bin/helpers/MockBinPositionManager.sol b/test/pool-bin/helpers/MockBinPositionManager.sol new file mode 100644 index 0000000..33715ab --- /dev/null +++ b/test/pool-bin/helpers/MockBinPositionManager.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2024 PancakeSwap +pragma solidity ^0.8.19; + +import {CommonBase} from "forge-std/Base.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {IBinPositionManager} from "pancake-v4-periphery/src/pool-bin/interfaces/IBinPositionManager.sol"; +import {BinPositionManager} from "pancake-v4-periphery/src/pool-bin/BinPositionManager.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; +import {Planner, Plan} from "pancake-v4-periphery/src/libraries/Planner.sol"; +import {Actions} from "pancake-v4-periphery/src/libraries/Actions.sol"; + +contract MockBinPositionManager is BinPositionManager, CommonBase { + using Planner for Plan; + + constructor(IVault _vault, IBinPoolManager _binPoolManager, IAllowanceTransfer _permit2) + BinPositionManager(_vault, _binPoolManager, _permit2) + {} + + function addLiquidity(IBinPositionManager.BinAddLiquidityParams calldata params) + external + payable + returns (uint128, uint128, uint256[] memory tokenIds, uint256[] memory liquidityMinted) + { + Plan memory planner = Planner.init().add(Actions.BIN_ADD_LIQUIDITY, abi.encode(params)); + bytes memory data = planner.finalizeModifyLiquidityWithClose(params.poolKey); + + vm.recordLogs(); + + vm.prank(msg.sender); + this.modifyLiquidities(data, block.timestamp); + + Vm.Log[] memory entries = vm.getRecordedLogs(); + // find IBinFungibleToken.TransferBatch + for (uint256 i = 0; i < entries.length; i++) { + if (entries[i].topics[0] == keccak256("TransferBatch(address,address,address,uint256[],uint256[])")) { + (tokenIds, liquidityMinted) = abi.decode(entries[i].data, (uint256[], uint256[])); + } + } + } + + function removeLiquidity(IBinPositionManager.BinRemoveLiquidityParams calldata params) external payable { + Plan memory planner = Planner.init().add(Actions.BIN_REMOVE_LIQUIDITY, abi.encode(params)); + bytes memory data = planner.finalizeModifyLiquidityWithClose(params.poolKey); + + vm.prank(msg.sender); + this.modifyLiquidities(data, block.timestamp); + } +} diff --git a/test/pool-bin/helpers/MockBinSwapRouter.sol b/test/pool-bin/helpers/MockBinSwapRouter.sol new file mode 100644 index 0000000..4df7752 --- /dev/null +++ b/test/pool-bin/helpers/MockBinSwapRouter.sol @@ -0,0 +1,80 @@ +pragma solidity ^0.8.19; + +import {CommonBase} from "forge-std/Base.sol"; +import {MockV4Router} from "pancake-v4-periphery/test/mocks/MockV4Router.sol"; +import {IV4Router} from "pancake-v4-periphery/src/interfaces/IV4Router.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {Planner, Plan} from "pancake-v4-periphery/src/libraries/Planner.sol"; +import {Actions} from "pancake-v4-periphery/src/libraries/Actions.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; + +contract MockBinSwapRouter is MockV4Router, CommonBase { + using Planner for Plan; + + constructor(IVault _vault, IBinPoolManager _binPoolManager) + MockV4Router(_vault, ICLPoolManager(address(0)), _binPoolManager) + {} + + modifier checkDeadline(uint256 deadline) { + if (block.timestamp > deadline) revert(); + _; + } + + function exactInputSingle(IV4Router.BinSwapExactInputSingleParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.BIN_SWAP_EXACT_IN_SINGLE, abi.encode(params)); + Currency inputCurrency = params.swapForY ? params.poolKey.currency0 : params.poolKey.currency1; + Currency outputCurrency = params.swapForY ? params.poolKey.currency1 : params.poolKey.currency0; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactInput(IV4Router.BinSwapExactInputParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.BIN_SWAP_EXACT_IN, abi.encode(params)); + Currency inputCurrency = params.currencyIn; + Currency outputCurrency = params.path[params.path.length - 1].intermediateCurrency; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactOutputSingle(IV4Router.BinSwapExactOutputSingleParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.BIN_SWAP_EXACT_OUT_SINGLE, abi.encode(params)); + Currency inputCurrency = params.swapForY ? params.poolKey.currency0 : params.poolKey.currency1; + Currency outputCurrency = params.swapForY ? params.poolKey.currency1 : params.poolKey.currency0; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactOutput(IV4Router.BinSwapExactOutputParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.BIN_SWAP_EXACT_OUT, abi.encode(params)); + Currency inputCurrency = params.path[params.path.length - 1].intermediateCurrency; + Currency outputCurrency = params.currencyOut; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } +} diff --git a/test/pool-cl/CLFullRangeHook.t.sol b/test/pool-cl/CLFullRangeHook.t.sol index a534995..9856d06 100644 --- a/test/pool-cl/CLFullRangeHook.t.sol +++ b/test/pool-cl/CLFullRangeHook.t.sol @@ -3,28 +3,32 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency, CurrencyLibrary} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {TickMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickMath.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {Deployers} from "@pancakeswap/v4-core/test/pool-cl/helpers/Deployers.sol"; -import {ICLSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-cl/interfaces/ICLSwapRouterBase.sol"; -import {CLSwapRouter} from "@pancakeswap/v4-periphery/src/pool-cl/CLSwapRouter.sol"; -import {NonfungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-cl/NonfungiblePositionManager.sol"; -import {INonfungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-cl/interfaces/INonfungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency, CurrencyLibrary} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {Deployers} from "pancake-v4-core/test/pool-cl/helpers/Deployers.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; + +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {ICLRouterBase} from "pancake-v4-periphery/src/pool-cl/interfaces/ICLRouterBase.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; + +import {MockCLSwapRouter} from "./helpers/MockCLSwapRouter.sol"; +import {MockCLPositionManager} from "./helpers/MockCLPositionManager.sol"; +import {PositionConfig} from "pancake-v4-periphery/src/pool-cl/libraries/PositionConfig.sol"; import {CLFullRange} from "../../src/pool-cl/full-range/CLFullRange.sol"; import {PancakeV4ERC20} from "../../src/pool-cl/full-range/libraries/PancakeV4ERC20.sol"; -contract CLFullRangeHookTest is Test, Deployers { +contract CLFullRangeHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using CLPoolParametersHelper for bytes32; using CurrencyLibrary for Currency; @@ -39,8 +43,9 @@ contract CLFullRangeHookTest is Test, Deployers { IVault vault; ICLPoolManager poolManager; - NonfungiblePositionManager nfp; - CLSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockCLPositionManager cpm; + MockCLSwapRouter swapRouter; CLFullRange fullRange; @@ -61,8 +66,9 @@ contract CLFullRangeHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); fullRange = new CLFullRange(poolManager); - nfp = new NonfungiblePositionManager(vault, poolManager, address(0), address(0)); - swapRouter = new CLSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + cpm = new MockCLPositionManager(vault, poolManager, permit2); + swapRouter = new MockCLSwapRouter(vault, poolManager); MockERC20[] memory tokens = deployTokens(3, 2 ** 128); token0 = tokens[0]; @@ -114,6 +120,13 @@ contract CLFullRangeHookTest is Test, Deployers { token0.approve(address(swapRouter), type(uint256).max); token1.approve(address(swapRouter), type(uint256).max); token2.approve(address(swapRouter), type(uint256).max); + token0.approve(address(permit2), type(uint256).max); + token1.approve(address(permit2), type(uint256).max); + token2.approve(address(permit2), type(uint256).max); + + permit2.approve(address(token0), address(cpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(cpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token2), address(cpm), type(uint160).max, type(uint48).max); poolManager.initialize(keyWithLiq, SQRT_RATIO_1_1, ZERO_BYTES); @@ -143,7 +156,13 @@ contract CLFullRangeHookTest is Test, Deployers { parameters: bytes32(uint256(fullRange.getHooksRegistrationBitmap())).setTickSpacing(61) }); - vm.expectRevert(CLFullRange.TickSpacingNotDefault.selector); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(fullRange), + abi.encodeWithSelector(CLFullRange.TickSpacingNotDefault.selector) + ) + ); poolManager.initialize(wrongKey, SQRT_RATIO_1_1, ZERO_BYTES); } @@ -196,10 +215,9 @@ contract CLFullRangeHookTest is Test, Deployers { ); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: 0, @@ -258,10 +276,9 @@ contract CLFullRangeHookTest is Test, Deployers { assertEq(hasAccruedFees, false); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: 0, @@ -289,10 +306,9 @@ contract CLFullRangeHookTest is Test, Deployers { ); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: 0, diff --git a/test/pool-cl/CLGeomeanOracle.t.sol b/test/pool-cl/CLGeomeanOracle.t.sol index 8ade606..ac26441 100644 --- a/test/pool-cl/CLGeomeanOracle.t.sol +++ b/test/pool-cl/CLGeomeanOracle.t.sol @@ -3,29 +3,33 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {TickMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickMath.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {Deployers} from "@pancakeswap/v4-core/test/pool-cl/helpers/Deployers.sol"; -import {Constants} from "@pancakeswap/v4-core/test/pool-cl/helpers/Constants.sol"; -import {ICLSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-cl/interfaces/ICLSwapRouterBase.sol"; -import {CLSwapRouter} from "@pancakeswap/v4-periphery/src/pool-cl/CLSwapRouter.sol"; -import {NonfungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-cl/NonfungiblePositionManager.sol"; -import {INonfungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-cl/interfaces/INonfungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {Deployers} from "pancake-v4-core/test/pool-cl/helpers/Deployers.sol"; +import {Constants} from "pancake-v4-core/test/pool-cl/helpers/Constants.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; + +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {ICLRouterBase} from "pancake-v4-periphery/src/pool-cl/interfaces/ICLRouterBase.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; + +import {MockCLSwapRouter} from "./helpers/MockCLSwapRouter.sol"; +import {MockCLPositionManager} from "./helpers/MockCLPositionManager.sol"; +import {PositionConfig} from "pancake-v4-periphery/src/pool-cl/libraries/PositionConfig.sol"; import {CLGeomeanOracle} from "../../src/pool-cl/geomean-oracle/CLGeomeanOracle.sol"; import {Oracle} from "../../src/pool-cl/geomean-oracle/libraries/Oracle.sol"; -contract CLGeomeanOracleHookTest is Test, Deployers { +contract CLGeomeanOracleHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using CLPoolParametersHelper for bytes32; @@ -33,8 +37,9 @@ contract CLGeomeanOracleHookTest is Test, Deployers { IVault vault; ICLPoolManager poolManager; - NonfungiblePositionManager nfp; - CLSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockCLPositionManager cpm; + MockCLSwapRouter swapRouter; CLGeomeanOracle geomeanOracle; @@ -47,19 +52,22 @@ contract CLGeomeanOracleHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); geomeanOracle = new CLGeomeanOracle(poolManager); - nfp = new NonfungiblePositionManager(vault, poolManager, address(0), address(0)); - swapRouter = new CLSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + cpm = new MockCLPositionManager(vault, poolManager, permit2); + swapRouter = new MockCLSwapRouter(vault, poolManager); MockERC20[] memory tokens = deployTokens(2, type(uint256).max); token0 = tokens[0]; token1 = tokens[1]; (Currency currency0, Currency currency1) = SortTokens.sort(token0, token1); - address[2] memory approvalAddress = [address(nfp), address(swapRouter)]; + address[3] memory approvalAddress = [address(cpm), address(swapRouter), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(cpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(cpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -87,7 +95,13 @@ contract CLGeomeanOracleHookTest is Test, Deployers { fee: 1, parameters: bytes32(uint256(geomeanOracle.getHooksRegistrationBitmap())).setTickSpacing(MAX_TICK_SPACING) }); - vm.expectRevert(CLGeomeanOracle.OnlyOneOraclePoolAllowed.selector); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(geomeanOracle), + abi.encodeWithSelector(CLGeomeanOracle.OnlyOneOraclePoolAllowed.selector) + ) + ); poolManager.initialize(k, SQRT_RATIO_1_1, ZERO_BYTES); } @@ -100,7 +114,14 @@ contract CLGeomeanOracleHookTest is Test, Deployers { fee: 0, parameters: bytes32(uint256(geomeanOracle.getHooksRegistrationBitmap())).setTickSpacing(60) }); - vm.expectRevert(CLGeomeanOracle.OnlyOneOraclePoolAllowed.selector); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(geomeanOracle), + abi.encodeWithSelector(CLGeomeanOracle.OnlyOneOraclePoolAllowed.selector) + ) + ); + poolManager.initialize(k, SQRT_RATIO_1_1, ZERO_BYTES); } @@ -136,19 +157,24 @@ contract CLGeomeanOracleHookTest is Test, Deployers { function testBeforeModifyPositionNoObservations() public { poolManager.initialize(key, Constants.SQRT_RATIO_2_1, ZERO_BYTES); - nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), - tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING), - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + PositionConfig memory config = PositionConfig({ + poolKey: key, + tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), + tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING) + }); + + cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 100e18, + // amount1Max: + 100e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); CLGeomeanOracle.ObservationState memory observationState = geomeanOracle.getState(key); @@ -166,19 +192,25 @@ contract CLGeomeanOracleHookTest is Test, Deployers { function testBeforeModifyPositionObservation() public { poolManager.initialize(key, Constants.SQRT_RATIO_2_1, ZERO_BYTES); vm.warp(3); // advance 2 seconds - nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), - tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING), - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + + PositionConfig memory config = PositionConfig({ + poolKey: key, + tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), + tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING) + }); + + cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 100e18, + // amount1Max: + 100e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); CLGeomeanOracle.ObservationState memory observationState = geomeanOracle.getState(key); @@ -202,19 +234,24 @@ contract CLGeomeanOracleHookTest is Test, Deployers { assertEq(observationState.cardinality, 1); assertEq(observationState.cardinalityNext, 2); - nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), - tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING), - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + PositionConfig memory config = PositionConfig({ + poolKey: key, + tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), + tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING) + }); + + cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 100e18, + // amount1Max: + 100e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); // cardinality is updated @@ -241,30 +278,47 @@ contract CLGeomeanOracleHookTest is Test, Deployers { function testPermanentLiquidity() public { poolManager.initialize(key, Constants.SQRT_RATIO_2_1, ZERO_BYTES); vm.warp(3); // advance 2 seconds - (uint256 tokenId, uint128 liquidity,,) = nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), - tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING), - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + + PositionConfig memory config = PositionConfig({ + poolKey: key, + tickLower: TickMath.minUsableTick(MAX_TICK_SPACING), + tickUpper: TickMath.maxUsableTick(MAX_TICK_SPACING) + }); + + (uint256 tokenId, uint128 liquidity) = cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 100e18, + // amount1Max: + 100e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); - vm.expectRevert(CLGeomeanOracle.OraclePoolMustLockLiquidity.selector); - nfp.decreaseLiquidity( - INonfungiblePositionManager.DecreaseLiquidityParams({ - tokenId: tokenId, - liquidity: liquidity, - amount0Min: 0, - amount1Min: 0, - deadline: block.timestamp - }) + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(geomeanOracle), + abi.encodeWithSelector(CLGeomeanOracle.OraclePoolMustLockLiquidity.selector) + ) + ); + cpm.decreaseLiquidity( + // tokenId: + tokenId, + // config: + config, + // liquidity: + liquidity, + // amount0Min: + 0, + // amount1Min: + 0, + // hookData: + ZERO_BYTES ); } } diff --git a/test/pool-cl/CLLimitOrder.t.sol b/test/pool-cl/CLLimitOrder.t.sol index 970d0ff..07e3f3f 100644 --- a/test/pool-cl/CLLimitOrder.t.sol +++ b/test/pool-cl/CLLimitOrder.t.sol @@ -3,27 +3,31 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {TickMath} from "@pancakeswap/v4-core/src/pool-cl/libraries/TickMath.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {Deployers} from "@pancakeswap/v4-core/test/pool-cl/helpers/Deployers.sol"; -import {ICLSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-cl/interfaces/ICLSwapRouterBase.sol"; -import {CLSwapRouter} from "@pancakeswap/v4-periphery/src/pool-cl/CLSwapRouter.sol"; -import {NonfungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-cl/NonfungiblePositionManager.sol"; -import {INonfungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-cl/interfaces/INonfungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {TickMath} from "pancake-v4-core/src/pool-cl/libraries/TickMath.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {Deployers} from "pancake-v4-core/test/pool-cl/helpers/Deployers.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; + +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {ICLRouterBase} from "pancake-v4-periphery/src/pool-cl/interfaces/ICLRouterBase.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; + +import {MockCLSwapRouter} from "./helpers/MockCLSwapRouter.sol"; +import {MockCLPositionManager} from "./helpers/MockCLPositionManager.sol"; +import {PositionConfig} from "pancake-v4-periphery/src/pool-cl/libraries/PositionConfig.sol"; import {CLLimitOrder, Epoch, EpochLibrary} from "../../src/pool-cl/limit-order/CLLimitOrder.sol"; -contract CLLimitOrderHookTest is Test, Deployers { +contract CLLimitOrderHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using CLPoolParametersHelper for bytes32; @@ -31,8 +35,9 @@ contract CLLimitOrderHookTest is Test, Deployers { IVault vault; ICLPoolManager poolManager; - NonfungiblePositionManager nfp; - CLSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockCLPositionManager cpm; + MockCLSwapRouter swapRouter; CLLimitOrder limitOrder; @@ -47,19 +52,22 @@ contract CLLimitOrderHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); limitOrder = new CLLimitOrder(poolManager); - nfp = new NonfungiblePositionManager(vault, poolManager, address(0), address(0)); - swapRouter = new CLSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + cpm = new MockCLPositionManager(vault, poolManager, permit2); + swapRouter = new MockCLSwapRouter(vault, poolManager); MockERC20[] memory tokens = deployTokens(2, type(uint256).max); token0 = tokens[0]; token1 = tokens[1]; (currency0, currency1) = SortTokens.sort(token0, token1); - address[3] memory approvalAddress = [address(nfp), address(swapRouter), address(limitOrder)]; + address[4] memory approvalAddress = [address(cpm), address(swapRouter), address(limitOrder), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(cpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(cpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -73,19 +81,20 @@ contract CLLimitOrderHookTest is Test, Deployers { poolManager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); - nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: -120, - tickUpper: 120, - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + PositionConfig memory config = PositionConfig({poolKey: key, tickLower: -120, tickUpper: 120}); + + cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 100e18, + // amount1Max: + 100e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); } @@ -142,10 +151,9 @@ contract CLLimitOrderHookTest is Test, Deployers { function testZeroForOneInRangeRevert() public { // swapping is free, there's no liquidity in the pool, so we only need to specify 1 wei swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: false, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: SQRT_RATIO_1_1 + 1, @@ -175,10 +183,9 @@ contract CLLimitOrderHookTest is Test, Deployers { function testNotZeroForOneInRangeRevert() public { // swapping is free, there's no liquidity in the pool, so we only need to specify 1 wei swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: SQRT_RATIO_1_1 - 1, @@ -244,10 +251,9 @@ contract CLLimitOrderHookTest is Test, Deployers { limitOrder.place(key, tickLower, zeroForOne, liquidity); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: false, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: TickMath.getSqrtRatioAtTick(60), diff --git a/test/pool-cl/CLVeCakeExclusiveHook.t.sol b/test/pool-cl/CLVeCakeExclusiveHook.t.sol index 72771bd..1eccacd 100644 --- a/test/pool-cl/CLVeCakeExclusiveHook.t.sol +++ b/test/pool-cl/CLVeCakeExclusiveHook.t.sol @@ -3,26 +3,29 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {ICLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; -import {IVault} from "@pancakeswap/v4-core/src/interfaces/IVault.sol"; -import {CLPoolManager} from "@pancakeswap/v4-core/src/pool-cl/CLPoolManager.sol"; -import {Vault} from "@pancakeswap/v4-core/src/Vault.sol"; -import {Currency} from "@pancakeswap/v4-core/src/types/Currency.sol"; -import {PoolKey} from "@pancakeswap/v4-core/src/types/PoolKey.sol"; -import {PoolId, PoolIdLibrary} from "@pancakeswap/v4-core/src/types/PoolId.sol"; -import {CLPoolParametersHelper} from "@pancakeswap/v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; -import {SortTokens} from "@pancakeswap/v4-core/test/helpers/SortTokens.sol"; -import {Deployers} from "@pancakeswap/v4-core/test/pool-cl/helpers/Deployers.sol"; -import {ICLSwapRouterBase} from "@pancakeswap/v4-periphery/src/pool-cl/interfaces/ICLSwapRouterBase.sol"; -import {CLSwapRouter} from "@pancakeswap/v4-periphery/src/pool-cl/CLSwapRouter.sol"; -import {NonfungiblePositionManager} from "@pancakeswap/v4-periphery/src/pool-cl/NonfungiblePositionManager.sol"; -import {INonfungiblePositionManager} from - "@pancakeswap/v4-periphery/src/pool-cl/interfaces/INonfungiblePositionManager.sol"; -import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol"; - +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {CLPoolManager} from "pancake-v4-core/src/pool-cl/CLPoolManager.sol"; +import {Vault} from "pancake-v4-core/src/Vault.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; +import {PoolKey} from "pancake-v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "pancake-v4-core/src/types/PoolId.sol"; +import {CLPoolParametersHelper} from "pancake-v4-core/src/pool-cl/libraries/CLPoolParametersHelper.sol"; +import {SortTokens} from "pancake-v4-core/test/helpers/SortTokens.sol"; +import {Deployers} from "pancake-v4-core/test/pool-cl/helpers/Deployers.sol"; +import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; + +import {Hooks} from "pancake-v4-core/src/libraries/Hooks.sol"; +import {ICLRouterBase} from "pancake-v4-periphery/src/pool-cl/interfaces/ICLRouterBase.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; + +import {MockCLSwapRouter} from "./helpers/MockCLSwapRouter.sol"; +import {MockCLPositionManager} from "./helpers/MockCLPositionManager.sol"; +import {PositionConfig} from "pancake-v4-periphery/src/pool-cl/libraries/PositionConfig.sol"; import {CLVeCakeExclusiveHook} from "../../src/pool-cl/vecake-exclusive/CLVeCakeExclusiveHook.sol"; -contract CLVeCakeExclusiveHookTest is Test, Deployers { +contract CLVeCakeExclusiveHookTest is Test, Deployers, DeployPermit2 { using PoolIdLibrary for PoolKey; using CLPoolParametersHelper for bytes32; @@ -30,8 +33,9 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { IVault vault; ICLPoolManager poolManager; - NonfungiblePositionManager nfp; - CLSwapRouter swapRouter; + IAllowanceTransfer permit2; + MockCLPositionManager cpm; + MockCLSwapRouter swapRouter; CLVeCakeExclusiveHook veCakeExclusiveHook; @@ -41,6 +45,7 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { Currency currency1; PoolKey key; PoolId id; + PositionConfig config; MockERC20 veCake; address nonHolder = address(0x1); @@ -55,14 +60,17 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { (vault, poolManager) = createFreshManager(); veCakeExclusiveHook = new CLVeCakeExclusiveHook(poolManager, address(veCake)); - nfp = new NonfungiblePositionManager(vault, poolManager, address(0), address(0)); - swapRouter = new CLSwapRouter(vault, poolManager, address(0)); + permit2 = IAllowanceTransfer(deployPermit2()); + cpm = new MockCLPositionManager(vault, poolManager, permit2); + swapRouter = new MockCLSwapRouter(vault, poolManager); - address[2] memory approvalAddress = [address(nfp), address(swapRouter)]; + address[3] memory approvalAddress = [address(cpm), address(swapRouter), address(permit2)]; for (uint256 i; i < approvalAddress.length; i++) { token0.approve(approvalAddress[i], type(uint256).max); token1.approve(approvalAddress[i], type(uint256).max); } + permit2.approve(address(token0), address(cpm), type(uint160).max, type(uint48).max); + permit2.approve(address(token1), address(cpm), type(uint160).max, type(uint48).max); key = PoolKey({ currency0: currency0, @@ -72,34 +80,39 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { fee: 3000, parameters: bytes32(uint256(veCakeExclusiveHook.getHooksRegistrationBitmap())).setTickSpacing(60) }); + config = PositionConfig({poolKey: key, tickLower: -120, tickUpper: 120}); id = key.toId(); poolManager.initialize(key, SQRT_RATIO_1_1, ZERO_BYTES); - nfp.mint( - INonfungiblePositionManager.MintParams({ - poolKey: key, - tickLower: -120, - tickUpper: 120, - salt: bytes32(0), - amount0Desired: 1e18, - amount1Desired: 1e18, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }) + cpm.mint( + config, + // liquidity: + 10e18, + // amount0Max: + 1e18, + // amount1Max: + 1e18, + // owner: + address(this), + // hookData: + ZERO_BYTES ); } function test_SwapRevertIfNotHolder() public { - vm.startPrank(nonHolder, nonHolder); - vm.expectRevert(CLVeCakeExclusiveHook.NotVeCakeHolder.selector); + vm.prank(nonHolder, nonHolder); + vm.expectRevert( + abi.encodeWithSelector( + Hooks.Wrap__FailedHookCall.selector, + address(veCakeExclusiveHook), + abi.encodeWithSelector(CLVeCakeExclusiveHook.NotVeCakeHolder.selector) + ) + ); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: 0, @@ -107,16 +120,14 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { }), block.timestamp ); - vm.stopPrank(); } function test_Swap() public { - vm.startPrank(address(this), address(this)); + vm.prank(address(this), address(this)); swapRouter.exactInputSingle( - ICLSwapRouterBase.V4CLExactInputSingleParams({ + ICLRouterBase.CLSwapExactInputSingleParams({ poolKey: key, zeroForOne: true, - recipient: address(this), amountIn: 1e18, amountOutMinimum: 0, sqrtPriceLimitX96: 0, @@ -124,6 +135,5 @@ contract CLVeCakeExclusiveHookTest is Test, Deployers { }), block.timestamp ); - vm.stopPrank(); } } diff --git a/test/pool-cl/helpers/MockCLPositionManager.sol b/test/pool-cl/helpers/MockCLPositionManager.sol new file mode 100644 index 0000000..65bc4e9 --- /dev/null +++ b/test/pool-cl/helpers/MockCLPositionManager.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2024 PancakeSwap +pragma solidity ^0.8.19; + +import {CommonBase} from "forge-std/Base.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {ICLPositionManager} from "pancake-v4-periphery/src/pool-cl/interfaces/ICLPositionManager.sol"; +import {CLPositionManager} from "pancake-v4-periphery/src/pool-cl/CLPositionManager.sol"; +import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; +import {Planner, Plan} from "pancake-v4-periphery/src/libraries/Planner.sol"; +import {Actions} from "pancake-v4-periphery/src/libraries/Actions.sol"; +import {PositionConfig} from "pancake-v4-periphery/src/pool-cl/libraries/PositionConfig.sol"; + +contract MockCLPositionManager is CLPositionManager, CommonBase { + using Planner for Plan; + + constructor(IVault _vault, ICLPoolManager _clPoolManager, IAllowanceTransfer _permit2) + CLPositionManager(_vault, _clPoolManager, _permit2) + {} + + function mint( + PositionConfig calldata config, + uint256 liquidity, + uint128 amount0Max, + uint128 amount1Max, + address owner, + bytes calldata hookData + ) external payable returns (uint256 tokenId, uint128 liquidityMinted) { + Plan memory planner = Planner.init().add( + Actions.CL_MINT_POSITION, abi.encode(config, liquidity, amount0Max, amount1Max, owner, hookData) + ); + bytes memory data = planner.finalizeModifyLiquidityWithClose(config.poolKey); + + // vm.recordLogs(); + + tokenId = nextTokenId; + + vm.prank(msg.sender); + this.modifyLiquidities(data, block.timestamp); + + liquidityMinted = getPositionLiquidity(tokenId, config); + } + + function decreaseLiquidity( + uint256 tokenId, + PositionConfig calldata config, + uint256 liquidity, + uint128 amount0Min, + uint128 amount1Min, + bytes calldata hookData + ) external payable { + Plan memory planner = Planner.init().add( + Actions.CL_DECREASE_LIQUIDITY, abi.encode(tokenId, config, liquidity, amount0Min, amount1Min, hookData) + ); + bytes memory data = planner.finalizeModifyLiquidityWithClose(config.poolKey); + + vm.prank(msg.sender); + this.modifyLiquidities(data, block.timestamp); + } +} diff --git a/test/pool-cl/helpers/MockCLSwapRouter.sol b/test/pool-cl/helpers/MockCLSwapRouter.sol new file mode 100644 index 0000000..99fda4d --- /dev/null +++ b/test/pool-cl/helpers/MockCLSwapRouter.sol @@ -0,0 +1,80 @@ +pragma solidity ^0.8.19; + +import {CommonBase} from "forge-std/Base.sol"; +import {MockV4Router} from "pancake-v4-periphery/test/mocks/MockV4Router.sol"; +import {IV4Router} from "pancake-v4-periphery/src/interfaces/IV4Router.sol"; +import {IVault} from "pancake-v4-core/src/interfaces/IVault.sol"; +import {ICLPoolManager} from "pancake-v4-core/src/pool-cl/interfaces/ICLPoolManager.sol"; +import {IBinPoolManager} from "pancake-v4-core/src/pool-bin/interfaces/IBinPoolManager.sol"; +import {Planner, Plan} from "pancake-v4-periphery/src/libraries/Planner.sol"; +import {Actions} from "pancake-v4-periphery/src/libraries/Actions.sol"; +import {Currency} from "pancake-v4-core/src/types/Currency.sol"; + +contract MockCLSwapRouter is MockV4Router, CommonBase { + using Planner for Plan; + + constructor(IVault _vault, ICLPoolManager _clPoolManager) + MockV4Router(_vault, _clPoolManager, IBinPoolManager(address(0))) + {} + + modifier checkDeadline(uint256 deadline) { + if (block.timestamp > deadline) revert(); + _; + } + + function exactInputSingle(IV4Router.CLSwapExactInputSingleParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.CL_SWAP_EXACT_IN_SINGLE, abi.encode(params)); + Currency inputCurrency = params.zeroForOne ? params.poolKey.currency0 : params.poolKey.currency1; + Currency outputCurrency = params.zeroForOne ? params.poolKey.currency1 : params.poolKey.currency0; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactInput(IV4Router.CLSwapExactInputParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.CL_SWAP_EXACT_IN, abi.encode(params)); + Currency inputCurrency = params.currencyIn; + Currency outputCurrency = params.path[params.path.length - 1].intermediateCurrency; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactOutputSingle(IV4Router.CLSwapExactOutputSingleParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.CL_SWAP_EXACT_OUT_SINGLE, abi.encode(params)); + Currency inputCurrency = params.zeroForOne ? params.poolKey.currency0 : params.poolKey.currency1; + Currency outputCurrency = params.zeroForOne ? params.poolKey.currency1 : params.poolKey.currency0; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } + + function exactOutput(IV4Router.CLSwapExactOutputParams calldata params, uint256 deadline) + external + payable + checkDeadline(deadline) + { + Plan memory planner = Planner.init().add(Actions.CL_SWAP_EXACT_OUT, abi.encode(params)); + Currency inputCurrency = params.path[params.path.length - 1].intermediateCurrency; + Currency outputCurrency = params.currencyOut; + bytes memory data = planner.finalizeSwap(inputCurrency, outputCurrency, msg.sender); + + vm.prank(msg.sender); + this.executeActions(data); + } +}