Created
December 18, 2025 13:51
-
-
Save Philogy/cfe8245b5abd6de3c830d2770999c1a9 to your computer and use it in GitHub Desktop.
Hook to let you insert swaps into position manager modify liquidities batch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity =0.8.30; | |
| import {IHooks, PoolKey, ModifyLiquidityParams, BalanceDelta} from "v4-core/interfaces/IHooks.sol"; | |
| import {Hooks} from "v4-core/libraries/Hooks.sol"; | |
| import {IPoolManager, SwapParams} from "v4-core/interfaces/IPoolManager.sol"; | |
| import {toBalanceDelta} from "v4-core/types/BalanceDelta.sol"; | |
| /// @author philogy <https://github.com/philogy> | |
| contract SwapBackdoorHook { | |
| using Hooks for IHooks; | |
| error NotValidHookAddress(); | |
| error InvalidHookCall(); | |
| IPoolManager internal immutable UNI_V4; | |
| uint256 internal constant POOL_KEY_CALLDATA_SIZE = 0xa0; | |
| uint256 internal constant SWAP_PARAMS_CALLDATA_SIZE = 0x60; | |
| constructor(IPoolManager uniV4) { | |
| require( | |
| IHooks(address(this)).hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG), | |
| NotValidHookAddress() | |
| ); | |
| require( | |
| IHooks(address(this)).hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG), | |
| NotValidHookAddress() | |
| ); | |
| require( | |
| IHooks(address(this)).hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG), | |
| NotValidHookAddress() | |
| ); | |
| require( | |
| IHooks(address(this)).hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG), | |
| NotValidHookAddress() | |
| ); | |
| UNI_V4 = uniV4; | |
| } | |
| function afterAddLiquidity( | |
| address, | |
| PoolKey calldata, | |
| ModifyLiquidityParams calldata, | |
| BalanceDelta, | |
| BalanceDelta, | |
| bytes calldata hookData | |
| ) external returns (bytes4, BalanceDelta) { | |
| require(msg.sender == address(UNI_V4), InvalidHookCall()); | |
| BalanceDelta delta = _swap(hookData); | |
| return (this.afterAddLiquidity.selector, delta); | |
| } | |
| function afterRemoveLiquidity( | |
| address, | |
| PoolKey calldata, | |
| ModifyLiquidityParams calldata, | |
| BalanceDelta, | |
| BalanceDelta, | |
| bytes calldata hookData | |
| ) external returns (bytes4, BalanceDelta) { | |
| require(msg.sender == address(UNI_V4), InvalidHookCall()); | |
| BalanceDelta delta = _swap(hookData); | |
| return (this.afterRemoveLiquidity.selector, delta); | |
| } | |
| function _swap(bytes calldata input) internal returns (BalanceDelta inverseSwapDelta) { | |
| require( | |
| input.length >= POOL_KEY_CALLDATA_SIZE + SWAP_PARAMS_CALLDATA_SIZE, InvalidHookCall() | |
| ); | |
| PoolKey calldata key; | |
| SwapParams calldata params; | |
| assembly { | |
| key := input.offset | |
| params := add(input.offset, POOL_KEY_CALLDATA_SIZE) | |
| input.offset := add( | |
| input.offset, | |
| add(POOL_KEY_CALLDATA_SIZE, SWAP_PARAMS_CALLDATA_SIZE) | |
| ) | |
| input.length := sub( | |
| input.length, | |
| add(POOL_KEY_CALLDATA_SIZE, SWAP_PARAMS_CALLDATA_SIZE) | |
| ) | |
| } | |
| BalanceDelta delta = UNI_V4.swap(key, params, input); | |
| inverseSwapDelta = toBalanceDelta(-delta.amount0(), -delta.amount1()); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment