diff --git a/contracts/hooks/examples/FullRange.sol b/contracts/hooks/examples/FullRange.sol index aa4b606d..ed080f5a 100644 --- a/contracts/hooks/examples/FullRange.sol +++ b/contracts/hooks/examples/FullRange.sol @@ -26,6 +26,25 @@ import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@uniswap/v4-core/src/type import "../../libraries/LiquidityAmounts.sol"; +function hookPermissions() pure returns (Hooks.Permissions memory) { + return Hooks.Permissions({ + beforeInitialize: true, + afterInitialize: false, + beforeAddLiquidity: true, + beforeRemoveLiquidity: false, + afterAddLiquidity: false, + afterRemoveLiquidity: false, + beforeSwap: true, + afterSwap: false, + beforeDonate: false, + afterDonate: false, + beforeSwapReturnDelta: false, + afterSwapReturnDelta: false, + afterAddLiquidityReturnDelta: false, + afterRemoveLiquidityReturnDelta: false + }); +} + contract FullRange is BaseHook, IUnlockCallback { using CurrencyLibrary for Currency; using CurrencySettleTake for Currency; @@ -93,22 +112,7 @@ contract FullRange is BaseHook, IUnlockCallback { } function getHookPermissions() public pure override returns (Hooks.Permissions memory) { - return Hooks.Permissions({ - beforeInitialize: true, - afterInitialize: false, - beforeAddLiquidity: true, - beforeRemoveLiquidity: false, - afterAddLiquidity: false, - afterRemoveLiquidity: false, - beforeSwap: true, - afterSwap: false, - beforeDonate: false, - afterDonate: false, - beforeSwapReturnDelta: false, - afterSwapReturnDelta: false, - afterAddLiquidityReturnDelta: false, - afterRemoveLiquidityReturnDelta: false - }); + return hookPermissions(); } function addLiquidity(AddLiquidityParams calldata params) diff --git a/contracts/hooks/examples/GeomeanOracle.sol b/contracts/hooks/examples/GeomeanOracle.sol index ec8301a5..6d24f2c0 100644 --- a/contracts/hooks/examples/GeomeanOracle.sol +++ b/contracts/hooks/examples/GeomeanOracle.sol @@ -11,6 +11,25 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol"; +function hookPermissions() pure returns (Hooks.Permissions memory) { + return Hooks.Permissions({ + beforeInitialize: true, + afterInitialize: true, + beforeAddLiquidity: true, + beforeRemoveLiquidity: true, + afterAddLiquidity: false, + afterRemoveLiquidity: false, + beforeSwap: true, + afterSwap: false, + beforeDonate: false, + afterDonate: false, + beforeSwapReturnDelta: false, + afterSwapReturnDelta: false, + afterAddLiquidityReturnDelta: false, + afterRemoveLiquidityReturnDelta: false + }); +} + /// @notice A hook for a pool that allows a Uniswap pool to act as an oracle. Pools that use this hook must have full range /// tick spacing and liquidity is always permanently locked in these pools. This is the suggested configuration /// for protocols that wish to use a V3 style geomean oracle. @@ -64,22 +83,7 @@ contract GeomeanOracle is BaseHook { constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} function getHookPermissions() public pure override returns (Hooks.Permissions memory) { - return Hooks.Permissions({ - beforeInitialize: true, - afterInitialize: true, - beforeAddLiquidity: true, - beforeRemoveLiquidity: true, - afterAddLiquidity: false, - afterRemoveLiquidity: false, - beforeSwap: true, - afterSwap: false, - beforeDonate: false, - afterDonate: false, - beforeSwapReturnDelta: false, - afterSwapReturnDelta: false, - afterAddLiquidityReturnDelta: false, - afterRemoveLiquidityReturnDelta: false - }); + return hookPermissions(); } function beforeInitialize(address, PoolKey calldata key, uint160, bytes calldata) diff --git a/contracts/hooks/examples/LimitOrder.sol b/contracts/hooks/examples/LimitOrder.sol index 92d6489b..1850456c 100644 --- a/contracts/hooks/examples/LimitOrder.sol +++ b/contracts/hooks/examples/LimitOrder.sol @@ -29,6 +29,25 @@ library EpochLibrary { } } +function hookPermissions() pure returns (Hooks.Permissions memory) { + return Hooks.Permissions({ + beforeInitialize: false, + afterInitialize: true, + beforeAddLiquidity: false, + beforeRemoveLiquidity: false, + afterAddLiquidity: false, + afterRemoveLiquidity: false, + beforeSwap: false, + afterSwap: true, + beforeDonate: false, + afterDonate: false, + beforeSwapReturnDelta: false, + afterSwapReturnDelta: false, + afterAddLiquidityReturnDelta: false, + afterRemoveLiquidityReturnDelta: false + }); +} + contract LimitOrder is BaseHook { using EpochLibrary for Epoch; using PoolIdLibrary for PoolKey; @@ -78,22 +97,7 @@ contract LimitOrder is BaseHook { constructor(IPoolManager _poolManager) BaseHook(_poolManager) {} function getHookPermissions() public pure override returns (Hooks.Permissions memory) { - return Hooks.Permissions({ - beforeInitialize: false, - afterInitialize: true, - beforeAddLiquidity: false, - beforeRemoveLiquidity: false, - afterAddLiquidity: false, - afterRemoveLiquidity: false, - beforeSwap: false, - afterSwap: true, - beforeDonate: false, - afterDonate: false, - beforeSwapReturnDelta: false, - afterSwapReturnDelta: false, - afterAddLiquidityReturnDelta: false, - afterRemoveLiquidityReturnDelta: false - }); + return hookPermissions(); } function getTickLowerLast(PoolId poolId) public view returns (int24) { diff --git a/contracts/hooks/examples/TWAMM.sol b/contracts/hooks/examples/TWAMM.sol index 0661dd54..be65feb1 100644 --- a/contracts/hooks/examples/TWAMM.sol +++ b/contracts/hooks/examples/TWAMM.sol @@ -23,6 +23,25 @@ import {CurrencySettleTake} from "@uniswap/v4-core/src/libraries/CurrencySettleT import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol"; +function hookPermissions() pure returns (Hooks.Permissions memory) { + return Hooks.Permissions({ + beforeInitialize: true, + afterInitialize: false, + beforeAddLiquidity: true, + beforeRemoveLiquidity: false, + afterAddLiquidity: false, + afterRemoveLiquidity: false, + beforeSwap: true, + afterSwap: false, + beforeDonate: false, + afterDonate: false, + beforeSwapReturnDelta: false, + afterSwapReturnDelta: false, + afterAddLiquidityReturnDelta: false, + afterRemoveLiquidityReturnDelta: false + }); +} + contract TWAMM is BaseHook, ITWAMM { using TransferHelper for IERC20Minimal; using CurrencyLibrary for Currency; @@ -66,22 +85,7 @@ contract TWAMM is BaseHook, ITWAMM { } function getHookPermissions() public pure override returns (Hooks.Permissions memory) { - return Hooks.Permissions({ - beforeInitialize: true, - afterInitialize: false, - beforeAddLiquidity: true, - beforeRemoveLiquidity: false, - afterAddLiquidity: false, - afterRemoveLiquidity: false, - beforeSwap: true, - afterSwap: false, - beforeDonate: false, - afterDonate: false, - beforeSwapReturnDelta: false, - afterSwapReturnDelta: false, - afterAddLiquidityReturnDelta: false, - afterRemoveLiquidityReturnDelta: false - }); + return hookPermissions(); } function beforeInitialize(address, PoolKey calldata key, uint160, bytes calldata) diff --git a/contracts/hooks/examples/VolatilityOracle.sol b/contracts/hooks/examples/VolatilityOracle.sol index ede61bf5..0f242550 100644 --- a/contracts/hooks/examples/VolatilityOracle.sol +++ b/contracts/hooks/examples/VolatilityOracle.sol @@ -7,6 +7,25 @@ import {LPFeeLibrary} from "@uniswap/v4-core/src/libraries/LPFeeLibrary.sol"; import {BaseHook} from "../../BaseHook.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +function hookPermissions() pure returns (Hooks.Permissions memory) { + return Hooks.Permissions({ + beforeInitialize: true, + afterInitialize: true, + beforeAddLiquidity: false, + beforeRemoveLiquidity: false, + afterAddLiquidity: false, + afterRemoveLiquidity: false, + beforeSwap: false, + afterSwap: false, + beforeDonate: false, + afterDonate: false, + beforeSwapReturnDelta: false, + afterSwapReturnDelta: false, + afterAddLiquidityReturnDelta: false, + afterRemoveLiquidityReturnDelta: false + }); +} + contract VolatilityOracle is BaseHook { using LPFeeLibrary for uint24; @@ -24,22 +43,7 @@ contract VolatilityOracle is BaseHook { } function getHookPermissions() public pure override returns (Hooks.Permissions memory) { - return Hooks.Permissions({ - beforeInitialize: true, - afterInitialize: true, - beforeAddLiquidity: false, - beforeRemoveLiquidity: false, - afterAddLiquidity: false, - afterRemoveLiquidity: false, - beforeSwap: false, - afterSwap: false, - beforeDonate: false, - afterDonate: false, - beforeSwapReturnDelta: false, - afterSwapReturnDelta: false, - afterAddLiquidityReturnDelta: false, - afterRemoveLiquidityReturnDelta: false - }); + return hookPermissions(); } function beforeInitialize(address, PoolKey calldata key, uint160, bytes calldata) diff --git a/contracts/libraries/HookHelpers.sol b/contracts/libraries/HookHelpers.sol new file mode 100644 index 00000000..23e49da1 --- /dev/null +++ b/contracts/libraries/HookHelpers.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; + +library HookHelpers { + /// @notice Function to calculate flags from permissions + /// @param permissions The permissions to convert to flags + /// @return out The flags that correspond to the permissions + function flags(Hooks.Permissions memory permissions) internal pure returns (uint160 out) { + if (permissions.beforeInitialize) out |= Hooks.BEFORE_INITIALIZE_FLAG; + if (permissions.afterInitialize) out |= Hooks.AFTER_INITIALIZE_FLAG; + if (permissions.beforeAddLiquidity) out |= Hooks.BEFORE_ADD_LIQUIDITY_FLAG; + if (permissions.afterAddLiquidity) out |= Hooks.AFTER_ADD_LIQUIDITY_FLAG; + if (permissions.beforeRemoveLiquidity) out |= Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG; + if (permissions.afterRemoveLiquidity) out |= Hooks.AFTER_REMOVE_LIQUIDITY_FLAG; + if (permissions.beforeSwap) out |= Hooks.BEFORE_SWAP_FLAG; + if (permissions.afterSwap) out |= Hooks.AFTER_SWAP_FLAG; + if (permissions.beforeDonate) out |= Hooks.BEFORE_DONATE_FLAG; + if (permissions.afterDonate) out |= Hooks.AFTER_DONATE_FLAG; + if (permissions.beforeSwapReturnDelta) out |= Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG; + if (permissions.afterSwapReturnDelta) out |= Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG; + if (permissions.afterAddLiquidityReturnDelta) out |= Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG; + if (permissions.afterRemoveLiquidityReturnDelta) out |= Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG; + } +} diff --git a/test/FullRange.t.sol b/test/FullRange.t.sol index 5edec106..6b9756cc 100644 --- a/test/FullRange.t.sol +++ b/test/FullRange.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; -import {FullRange} from "../contracts/hooks/examples/FullRange.sol"; +import {FullRange, hookPermissions} from "../contracts/hooks/examples/FullRange.sol"; import {FullRangeImplementation} from "./shared/implementation/FullRangeImplementation.sol"; import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; @@ -21,12 +21,14 @@ import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; import {HookEnabledSwapRouter} from "./utils/HookEnabledSwapRouter.sol"; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; +import {HookHelpers} from "../contracts/libraries/HookHelpers.sol"; contract TestFullRange is Test, Deployers, GasSnapshot { using PoolIdLibrary for PoolKey; using SafeCast for uint256; using CurrencyLibrary for Currency; using StateLibrary for IPoolManager; + using HookHelpers for Hooks.Permissions; event Initialize( PoolId poolId, @@ -66,9 +68,7 @@ contract TestFullRange is Test, Deployers, GasSnapshot { MockERC20 token1; MockERC20 token2; - FullRangeImplementation fullRange = FullRangeImplementation( - address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.BEFORE_SWAP_FLAG)) - ); + FullRangeImplementation fullRange = FullRangeImplementation(address(hookPermissions().flags())); PoolId id; diff --git a/test/GeomeanOracle.t.sol b/test/GeomeanOracle.t.sol index e6ff1695..5cab8d79 100644 --- a/test/GeomeanOracle.t.sol +++ b/test/GeomeanOracle.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GetSender} from "./shared/GetSender.sol"; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; -import {GeomeanOracle} from "../contracts/hooks/examples/GeomeanOracle.sol"; +import {GeomeanOracle, hookPermissions} from "../contracts/hooks/examples/GeomeanOracle.sol"; import {GeomeanOracleImplementation} from "./shared/implementation/GeomeanOracleImplementation.sol"; import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; @@ -16,22 +16,17 @@ import {PoolModifyLiquidityTest} from "@uniswap/v4-core/src/test/PoolModifyLiqui import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {Oracle} from "../contracts/libraries/Oracle.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {HookHelpers} from "../contracts/libraries/HookHelpers.sol"; contract TestGeomeanOracle is Test, Deployers { using PoolIdLibrary for PoolKey; + using HookHelpers for Hooks.Permissions; int24 constant MAX_TICK_SPACING = 32767; TestERC20 token0; TestERC20 token1; - GeomeanOracleImplementation geomeanOracle = GeomeanOracleImplementation( - address( - uint160( - Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG - | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.BEFORE_SWAP_FLAG - ) - ) - ); + GeomeanOracleImplementation geomeanOracle = GeomeanOracleImplementation(address(hookPermissions().flags())); PoolId id; function setUp() public { diff --git a/test/LimitOrder.t.sol b/test/LimitOrder.t.sol index 17f5aecb..1cb01ed2 100644 --- a/test/LimitOrder.t.sol +++ b/test/LimitOrder.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {GetSender} from "./shared/GetSender.sol"; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; -import {LimitOrder, Epoch, EpochLibrary} from "../contracts/hooks/examples/LimitOrder.sol"; +import {LimitOrder, Epoch, EpochLibrary, hookPermissions} from "../contracts/hooks/examples/LimitOrder.sol"; import {LimitOrderImplementation} from "./shared/implementation/LimitOrderImplementation.sol"; import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; @@ -16,17 +16,19 @@ import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {HookEnabledSwapRouter} from "./utils/HookEnabledSwapRouter.sol"; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; +import {HookHelpers} from "../contracts/libraries/HookHelpers.sol"; contract TestLimitOrder is Test, Deployers { using PoolIdLibrary for PoolKey; using StateLibrary for IPoolManager; + using HookHelpers for Hooks.Permissions; uint160 constant SQRT_RATIO_10_1 = 250541448375047931186413801569; HookEnabledSwapRouter router; TestERC20 token0; TestERC20 token1; - LimitOrder limitOrder = LimitOrder(address(uint160(Hooks.AFTER_INITIALIZE_FLAG | Hooks.AFTER_SWAP_FLAG))); + LimitOrder limitOrder = LimitOrder(address(hookPermissions().flags())); PoolId id; function setUp() public { diff --git a/test/TWAMM.t.sol b/test/TWAMM.t.sol index 0f2f82e0..e698131f 100644 --- a/test/TWAMM.t.sol +++ b/test/TWAMM.t.sol @@ -17,13 +17,15 @@ import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol"; import {PoolDonateTest} from "@uniswap/v4-core/src/test/PoolDonateTest.sol"; import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; import {CurrencyLibrary, Currency} from "@uniswap/v4-core/src/types/Currency.sol"; -import {TWAMM} from "../contracts/hooks/examples/TWAMM.sol"; +import {TWAMM, hookPermissions} from "../contracts/hooks/examples/TWAMM.sol"; import {ITWAMM} from "../contracts/interfaces/ITWAMM.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {HookHelpers} from "../contracts/libraries/HookHelpers.sol"; contract TWAMMTest is Test, Deployers, GasSnapshot { using PoolIdLibrary for PoolKey; using CurrencyLibrary for Currency; + using HookHelpers for Hooks.Permissions; event SubmitOrder( PoolId indexed poolId, @@ -43,8 +45,7 @@ contract TWAMMTest is Test, Deployers, GasSnapshot { uint256 earningsFactorLast ); - TWAMM twamm = - TWAMM(address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG))); + TWAMM twamm = TWAMM(address(hookPermissions().flags())); address hookAddress; MockERC20 token0; MockERC20 token1;