// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {BeforeSwapDelta} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol"; import {ImmutableState} from "../base/ImmutableState.sol"; import {ModifyLiquidityParams, SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol"; /// @title Base Hook /// @notice abstract contract for hook implementations abstract contract BaseHook is IHooks, ImmutableState { error HookNotImplemented(); constructor(IPoolManager _manager) ImmutableState(_manager) { validateHookAddress(this); } /// @notice Returns a struct of permissions to signal which hook functions are to be implemented /// @dev Used at deployment to validate the address correctly represents the expected permissions /// @return Permissions struct function getHookPermissions() public pure virtual returns (Hooks.Permissions memory); /// @notice Validates the deployed hook address agrees with the expected permissions of the hook /// @dev this function is virtual so that we can override it during testing, /// which allows us to deploy an implementation to any address /// and then etch the bytecode into the correct address function validateHookAddress(BaseHook _this) internal pure virtual { Hooks.validateHookPermissions(_this, getHookPermissions()); } /// @inheritdoc IHooks function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external onlyPoolManager returns (bytes4) { return _beforeInitialize(sender, key, sqrtPriceX96); } function _beforeInitialize(address, PoolKey calldata, uint160) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) external onlyPoolManager returns (bytes4) { return _afterInitialize(sender, key, sqrtPriceX96, tick); } function _afterInitialize(address, PoolKey calldata, uint160, int24) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeAddLiquidity( address sender, PoolKey calldata key, ModifyLiquidityParams calldata params, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeAddLiquidity(sender, key, params, hookData); } function _beforeAddLiquidity(address, PoolKey calldata, ModifyLiquidityParams calldata, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeRemoveLiquidity( address sender, PoolKey calldata key, ModifyLiquidityParams calldata params, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeRemoveLiquidity(sender, key, params, hookData); } function _beforeRemoveLiquidity(address, PoolKey calldata, ModifyLiquidityParams calldata, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterAddLiquidity( address sender, PoolKey calldata key, ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external onlyPoolManager returns (bytes4, BalanceDelta) { return _afterAddLiquidity(sender, key, params, delta, feesAccrued, hookData); } function _afterAddLiquidity( address, PoolKey calldata, ModifyLiquidityParams calldata, BalanceDelta, BalanceDelta, bytes calldata ) internal virtual returns (bytes4, BalanceDelta) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterRemoveLiquidity( address sender, PoolKey calldata key, ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external onlyPoolManager returns (bytes4, BalanceDelta) { return _afterRemoveLiquidity(sender, key, params, delta, feesAccrued, hookData); } function _afterRemoveLiquidity( address, PoolKey calldata, ModifyLiquidityParams calldata, BalanceDelta, BalanceDelta, bytes calldata ) internal virtual returns (bytes4, BalanceDelta) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata hookData) external onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) { return _beforeSwap(sender, key, params, hookData); } function _beforeSwap(address, PoolKey calldata, SwapParams calldata, bytes calldata) internal virtual returns (bytes4, BeforeSwapDelta, uint24) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterSwap( address sender, PoolKey calldata key, SwapParams calldata params, BalanceDelta delta, bytes calldata hookData ) external onlyPoolManager returns (bytes4, int128) { return _afterSwap(sender, key, params, delta, hookData); } function _afterSwap(address, PoolKey calldata, SwapParams calldata, BalanceDelta, bytes calldata) internal virtual returns (bytes4, int128) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeDonate(sender, key, amount0, amount1, hookData); } function _beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _afterDonate(sender, key, amount0, amount1, hookData); } function _afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } }