Skip to content

Commit 3f2ff64

Browse files
authored
Merge pull request #60 from euler-xyz/sauce/revert-add-liq
Revert on add liquidity
2 parents cfc3b95 + 4c757b0 commit 3f2ff64

File tree

4 files changed

+52
-4
lines changed

4 files changed

+52
-4
lines changed

src/UniswapHook.sol

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ contract UniswapHook is BaseHook {
2727

2828
PoolKey internal _poolKey;
2929

30+
error NativeConcentratedLiquidityUnsupported();
31+
3032
constructor(address evc_, address _poolManager) BaseHook(IPoolManager(_poolManager)) {
3133
evc = evc_;
3234
}
@@ -116,11 +118,20 @@ contract UniswapHook is BaseHook {
116118
return (BaseHook.beforeSwap.selector, returnDelta, 0);
117119
}
118120

121+
function _beforeAddLiquidity(address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, bytes calldata)
122+
internal
123+
pure
124+
override
125+
returns (bytes4)
126+
{
127+
revert NativeConcentratedLiquidityUnsupported();
128+
}
129+
119130
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
120131
return Hooks.Permissions({
121132
beforeInitialize: false,
122133
afterInitialize: false,
123-
beforeAddLiquidity: false,
134+
beforeAddLiquidity: true,
124135
afterAddLiquidity: false,
125136
beforeRemoveLiquidity: false,
126137
afterRemoveLiquidity: false,

test/EulerSwapTestBase.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ contract EulerSwapTestBase is EVaultTestBase {
4141
// use the canonical miner to find a valid 'implementation' address
4242
(, bytes32 salt) = v4HookMiner.find(
4343
address(this),
44-
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG),
44+
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG),
4545
type(EulerSwap).creationCode,
4646
abi.encode(address(evc), poolManager_)
4747
);
@@ -178,7 +178,7 @@ contract EulerSwapTestBase is EVaultTestBase {
178178
(address predictedAddr, bytes32 salt) = HookMiner.find(
179179
address(eulerSwapFactory),
180180
holder,
181-
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG),
181+
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG),
182182
creationCode
183183
);
184184

test/FactoryTest.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ contract FactoryTest is EulerSwapTestBase {
3333
}
3434

3535
function mineSalt(IEulerSwap.Params memory poolParams) internal view returns (address hookAddress, bytes32 salt) {
36-
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG);
36+
uint160 flags =
37+
uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG);
3738
bytes memory creationCode = MetaProxyDeployer.creationCodeMetaProxy(eulerSwapImpl, abi.encode(poolParams));
3839
(hookAddress, salt) = HookMiner.find(address(eulerSwapFactory), holder, flags, creationCode);
3940
}

test/HookSwaps.t.sol

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ pragma solidity ^0.8.24;
44
import {EulerSwapTestBase, EulerSwap, EulerSwapPeriphery, IEulerSwap} from "./EulerSwapTestBase.t.sol";
55
import {TestERC20} from "evk-test/unit/evault/EVaultTestBase.t.sol";
66
import {EulerSwap} from "../src/EulerSwap.sol";
7+
import {UniswapHook} from "../src/UniswapHook.sol";
78

89
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
910
import {IPoolManager, PoolManagerDeployer} from "./utils/PoolManagerDeployer.sol";
1011
import {PoolSwapTest} from "@uniswap/v4-core/src/test/PoolSwapTest.sol";
1112
import {MinimalRouter} from "./utils/MinimalRouter.sol";
13+
import {PoolModifyLiquidityTest} from "@uniswap/v4-core/src/test/PoolModifyLiquidityTest.sol";
1214
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
1315
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
1416
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
1517
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
18+
import {CustomRevert} from "@uniswap/v4-core/src/libraries/CustomRevert.sol";
19+
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
20+
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
1621

1722
contract HookSwapsTest is EulerSwapTestBase {
1823
using StateLibrary for IPoolManager;
@@ -22,6 +27,7 @@ contract HookSwapsTest is EulerSwapTestBase {
2227
IPoolManager public poolManager;
2328
PoolSwapTest public swapRouter;
2429
MinimalRouter public minimalRouter;
30+
PoolModifyLiquidityTest public liquidityManager;
2531

2632
PoolSwapTest.TestSettings public settings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
2733

@@ -31,6 +37,7 @@ contract HookSwapsTest is EulerSwapTestBase {
3137
poolManager = PoolManagerDeployer.deploy(address(this));
3238
swapRouter = new PoolSwapTest(poolManager);
3339
minimalRouter = new MinimalRouter(poolManager);
40+
liquidityManager = new PoolModifyLiquidityTest(poolManager);
3441

3542
deployEulerSwap(address(poolManager));
3643

@@ -119,6 +126,35 @@ contract HookSwapsTest is EulerSwapTestBase {
119126
vm.stopPrank();
120127
}
121128

129+
/// @dev adding liquidity as a concentrated liquidity position will revert
130+
function test_revertAddConcentratedLiquidity() public {
131+
assetTST.mint(anyone, 10000e18);
132+
assetTST2.mint(anyone, 10000e18);
133+
134+
vm.startPrank(anyone);
135+
assetTST.approve(address(liquidityManager), 1e18);
136+
assetTST2.approve(address(liquidityManager), 1e18);
137+
138+
PoolKey memory poolKey = eulerSwap.poolKey();
139+
140+
// hook intentionally reverts to prevent v3-CLAMM positions
141+
vm.expectRevert(
142+
abi.encodeWithSelector(
143+
CustomRevert.WrappedError.selector,
144+
address(eulerSwap),
145+
IHooks.beforeAddLiquidity.selector,
146+
abi.encodeWithSelector(UniswapHook.NativeConcentratedLiquidityUnsupported.selector),
147+
abi.encodeWithSelector(Hooks.HookCallFailed.selector)
148+
)
149+
);
150+
liquidityManager.modifyLiquidity(
151+
poolKey,
152+
IPoolManager.ModifyLiquidityParams({tickLower: -10, tickUpper: 10, liquidityDelta: 1000, salt: bytes32(0)}),
153+
""
154+
);
155+
vm.stopPrank();
156+
}
157+
122158
function _swap(PoolKey memory key, bool zeroForOne, bool exactInput, uint256 amount) internal {
123159
IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({
124160
zeroForOne: zeroForOne,

0 commit comments

Comments
 (0)