@bananapus/univ4-lp-split-hook-v6 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILLS.md +4 -4
- package/package.json +1 -1
- package/src/UniV4DeploymentSplitHook.sol +3 -10
- package/src/UniV4DeploymentSplitHookDeployer.sol +1 -1
- package/src/interfaces/IUniV4DeploymentSplitHook.sol +1 -2
- package/test/ConstructorTest.t.sol +6 -16
- package/test/DeployerTest.t.sol +0 -1
- package/test/NativeETHTest.t.sol +1 -2
- package/test/PriceMathTest.t.sol +1 -2
- package/test/TestBaseV4.sol +1 -1
- package/test/regression/L25_FeeProjectIdValidation.t.sol +3 -5
- package/test/regression/M32_ReinitAfterRenounce.t.sol +9 -22
package/SKILLS.md
CHANGED
|
@@ -8,7 +8,7 @@ Juicebox reserved-token split hook that accumulates project tokens, deploys a Un
|
|
|
8
8
|
|
|
9
9
|
| Contract | Role |
|
|
10
10
|
|----------|------|
|
|
11
|
-
| `UniV4DeploymentSplitHook` | Core split hook. Implements `IJBSplitHook.processSplitWith` to accumulate or burn tokens. Manages V4 pool creation, LP position minting, fee collection, and liquidity rebalancing. Inherits `JBPermissioned
|
|
11
|
+
| `UniV4DeploymentSplitHook` | Core split hook. Implements `IJBSplitHook.processSplitWith` to accumulate or burn tokens. Manages V4 pool creation, LP position minting, fee collection, and liquidity rebalancing. Inherits `JBPermissioned`. Deployed as clones via factory. |
|
|
12
12
|
| `UniV4DeploymentSplitHookDeployer` | Factory that deploys hook clones via `LibClone` (Solady). Supports CREATE2 deterministic deployment. Initializes clones with `feeProjectId` and `feePercent`. Registers each deployed clone in `JBAddressRegistry` so frontends can verify the deployer. |
|
|
13
13
|
|
|
14
14
|
## Key Functions
|
|
@@ -71,7 +71,7 @@ Juicebox reserved-token split hook that accumulates project tokens, deploys a Un
|
|
|
71
71
|
| `@bananapus/permission-ids-v6` | `JBPermissionIds` | `SET_BUYBACK_POOL` permission ID |
|
|
72
72
|
| `@uniswap/v4-core` | `IPoolManager`, `PoolKey`, `PoolId`, `Currency`, `TickMath`, `IHooks` | V4 pool creation, price math, currency handling |
|
|
73
73
|
| `@uniswap/v4-periphery` | `IPositionManager`, `Actions`, `LiquidityAmounts` | V4 position management: mint, modify, burn, collect |
|
|
74
|
-
| `@openzeppelin/contracts` | `IERC20`, `IERC20Metadata`, `SafeERC20
|
|
74
|
+
| `@openzeppelin/contracts` | `IERC20`, `IERC20Metadata`, `SafeERC20` | Token operations |
|
|
75
75
|
| `@prb/math` | `mulDiv`, `sqrt` | Overflow-safe arithmetic for sqrtPriceX96 calculations |
|
|
76
76
|
| `@bananapus/address-registry-v6` | `IJBAddressRegistry` | On-chain registry mapping deployed hooks to their deployer contract |
|
|
77
77
|
| `solady` | `LibClone` | Clone factory for deploying hook instances |
|
|
@@ -107,7 +107,7 @@ Juicebox reserved-token split hook that accumulates project tokens, deploys a Un
|
|
|
107
107
|
| `UniV4DeploymentSplitHook_InvalidFeePercent` | `feePercent > BPS` (> 100%) |
|
|
108
108
|
| `UniV4DeploymentSplitHook_InvalidTerminalToken` | No primary terminal found for project/token pair |
|
|
109
109
|
| `UniV4DeploymentSplitHook_PoolAlreadyDeployed` | `deployPool` called for a pair that already has a position |
|
|
110
|
-
| `UniV4DeploymentSplitHook_AlreadyInitialized` | `initialize` called on a clone that was already initialized
|
|
110
|
+
| `UniV4DeploymentSplitHook_AlreadyInitialized` | `initialize` called on a clone that was already initialized |
|
|
111
111
|
| `UniV4DeploymentSplitHook_FeePercentWithoutFeeProject` | `initialize` called with `feePercent > 0` but `feeProjectId == 0` (fees would get stuck since `primaryTerminalOf(0, token)` returns `address(0)`) |
|
|
112
112
|
|
|
113
113
|
## Constants
|
|
@@ -127,7 +127,7 @@ Juicebox reserved-token split hook that accumulates project tokens, deploys a Un
|
|
|
127
127
|
| `accumulatedProjectTokens` | `projectId => uint256` | Pre-deployment token accumulation |
|
|
128
128
|
| `projectDeployed` | `projectId => bool` | Switches accumulate (Stage 1) to burn (Stage 2) |
|
|
129
129
|
| `claimableFeeTokens` | `projectId => uint256` | Fee-project tokens claimable via `claimFeeTokensFor` |
|
|
130
|
-
| `initialized` | `bool` | Prevents re-initialization
|
|
130
|
+
| `initialized` | `bool` | Prevents re-initialization of clone instances |
|
|
131
131
|
|
|
132
132
|
## Gotchas
|
|
133
133
|
|
package/package.json
CHANGED
|
@@ -19,7 +19,6 @@ import {JBConstants} from "@bananapus/core/libraries/JBConstants.sol";
|
|
|
19
19
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
20
20
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
21
21
|
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
22
|
-
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
23
22
|
import {mulDiv, sqrt} from "@prb/math/src/Common.sol";
|
|
24
23
|
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
|
25
24
|
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
|
|
@@ -52,7 +51,7 @@ import {IUniV4DeploymentSplitHook} from "./interfaces/IUniV4DeploymentSplitHook.
|
|
|
52
51
|
* @dev For any given Uniswap V4 pool, the contract will control a single LP position.
|
|
53
52
|
* @dev Pool deployment requires SET_BUYBACK_POOL permission from the project owner.
|
|
54
53
|
*/
|
|
55
|
-
contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JBPermissioned
|
|
54
|
+
contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JBPermissioned {
|
|
56
55
|
using JBRulesetMetadataResolver for JBRuleset;
|
|
57
56
|
using SafeERC20 for IERC20;
|
|
58
57
|
using PoolIdLibrary for PoolKey;
|
|
@@ -129,7 +128,7 @@ contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JB
|
|
|
129
128
|
/// @notice ProjectID => Fee tokens claimable by that project
|
|
130
129
|
mapping(uint256 projectId => uint256 claimableFeeTokens) public claimableFeeTokens;
|
|
131
130
|
|
|
132
|
-
/// @notice Whether this clone instance has been initialized
|
|
131
|
+
/// @notice Whether this clone instance has been initialized.
|
|
133
132
|
bool public initialized;
|
|
134
133
|
|
|
135
134
|
//*********************************************************************//
|
|
@@ -149,7 +148,6 @@ contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JB
|
|
|
149
148
|
IPositionManager positionManager
|
|
150
149
|
)
|
|
151
150
|
JBPermissioned(permissions)
|
|
152
|
-
Ownable(msg.sender)
|
|
153
151
|
{
|
|
154
152
|
if (directory == address(0)) revert UniV4DeploymentSplitHook_ZeroAddressNotAllowed();
|
|
155
153
|
if (tokens == address(0)) revert UniV4DeploymentSplitHook_ZeroAddressNotAllowed();
|
|
@@ -163,12 +161,9 @@ contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JB
|
|
|
163
161
|
}
|
|
164
162
|
|
|
165
163
|
/// @notice Initialize per-instance config on a clone. Can only be called once.
|
|
166
|
-
/// @dev Uses an explicit `initialized` flag rather than relying on owner() == address(0),
|
|
167
|
-
/// which would allow re-initialization after renounceOwnership().
|
|
168
|
-
/// @param initialOwner The owner of this clone instance.
|
|
169
164
|
/// @param feeProjectId Project ID to receive LP fees.
|
|
170
165
|
/// @param feePercent Percentage of LP fees to route to fee project (in basis points, e.g., 3800 = 38%).
|
|
171
|
-
function initialize(
|
|
166
|
+
function initialize(uint256 feeProjectId, uint256 feePercent) external {
|
|
172
167
|
if (initialized) revert UniV4DeploymentSplitHook_AlreadyInitialized();
|
|
173
168
|
|
|
174
169
|
if (feePercent > BPS) revert UniV4DeploymentSplitHook_InvalidFeePercent();
|
|
@@ -185,8 +180,6 @@ contract UniV4DeploymentSplitHook is IUniV4DeploymentSplitHook, IJBSplitHook, JB
|
|
|
185
180
|
initialized = true;
|
|
186
181
|
FEE_PROJECT_ID = feeProjectId;
|
|
187
182
|
FEE_PERCENT = feePercent;
|
|
188
|
-
|
|
189
|
-
_transferOwnership(initialOwner);
|
|
190
183
|
}
|
|
191
184
|
|
|
192
185
|
/// @notice Accept ETH transfers (needed for cashOut with native ETH and V4 TAKE operations).
|
|
@@ -66,7 +66,7 @@ contract UniV4DeploymentSplitHookDeployer is IUniV4DeploymentSplitHookDeployer {
|
|
|
66
66
|
})
|
|
67
67
|
);
|
|
68
68
|
|
|
69
|
-
IUniV4DeploymentSplitHook(address(hook)).initialize(
|
|
69
|
+
IUniV4DeploymentSplitHook(address(hook)).initialize(feeProjectId, feePercent);
|
|
70
70
|
|
|
71
71
|
emit HookDeployed(feeProjectId, feePercent, hook, msg.sender);
|
|
72
72
|
|
|
@@ -35,11 +35,10 @@ interface IUniV4DeploymentSplitHook {
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* @notice Initialize per-instance config on a clone.
|
|
38
|
-
* @param initialOwner The owner of this clone instance.
|
|
39
38
|
* @param feeProjectId Project ID to receive LP fees.
|
|
40
39
|
* @param feePercent Percentage of LP fees to route to fee project (in basis points).
|
|
41
40
|
*/
|
|
42
|
-
function initialize(
|
|
41
|
+
function initialize(uint256 feeProjectId, uint256 feePercent) external;
|
|
43
42
|
|
|
44
43
|
/**
|
|
45
44
|
* @notice Check if a pool has been deployed for a project/terminal token pair
|
|
@@ -25,11 +25,10 @@ contract ConstructorTest is LPSplitHookV4TestBase {
|
|
|
25
25
|
assertEq(address(hook.POSITION_MANAGER()), address(positionManager), "POSITION_MANAGER mismatch");
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/// @notice Verify initialize() sets per-clone config (
|
|
28
|
+
/// @notice Verify initialize() sets per-clone config (feeProjectId, feePercent).
|
|
29
29
|
function test_Initialize_SetsCloneConfig() public view {
|
|
30
30
|
assertEq(hook.FEE_PROJECT_ID(), FEE_PROJECT_ID, "FEE_PROJECT_ID mismatch");
|
|
31
31
|
assertEq(hook.FEE_PERCENT(), FEE_PERCENT, "FEE_PERCENT mismatch");
|
|
32
|
-
assertEq(hook.owner(), owner, "owner mismatch");
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/// @notice Constructor reverts when directory is address(0).
|
|
@@ -94,11 +93,9 @@ contract ConstructorTest is LPSplitHookV4TestBase {
|
|
|
94
93
|
IPoolManager(address(1)),
|
|
95
94
|
IPositionManager(address(positionManager))
|
|
96
95
|
);
|
|
97
|
-
// Zero out slot 0 (owner) so initialize() can be called
|
|
98
|
-
vm.store(address(impl), bytes32(uint256(0)), bytes32(0));
|
|
99
96
|
|
|
100
97
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_InvalidFeePercent.selector);
|
|
101
|
-
impl.initialize(
|
|
98
|
+
impl.initialize(FEE_PROJECT_ID, 10_001);
|
|
102
99
|
}
|
|
103
100
|
|
|
104
101
|
/// @notice initialize() reverts when feeProjectId is 0 but feePercent > 0 (L-25 fix).
|
|
@@ -111,11 +108,9 @@ contract ConstructorTest is LPSplitHookV4TestBase {
|
|
|
111
108
|
IPoolManager(address(1)),
|
|
112
109
|
IPositionManager(address(positionManager))
|
|
113
110
|
);
|
|
114
|
-
// Zero out slot 0 (owner) so initialize() can be called
|
|
115
|
-
vm.store(address(impl), bytes32(uint256(0)), bytes32(0));
|
|
116
111
|
|
|
117
112
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_FeePercentWithoutFeeProject.selector);
|
|
118
|
-
impl.initialize(
|
|
113
|
+
impl.initialize(0, FEE_PERCENT);
|
|
119
114
|
}
|
|
120
115
|
|
|
121
116
|
/// @notice When both feeProjectId and feePercent are 0, initialize() succeeds (no fees configured).
|
|
@@ -128,14 +123,11 @@ contract ConstructorTest is LPSplitHookV4TestBase {
|
|
|
128
123
|
IPoolManager(address(1)),
|
|
129
124
|
IPositionManager(address(positionManager))
|
|
130
125
|
);
|
|
131
|
-
// Zero out slot 0 (owner) so initialize() can be called
|
|
132
|
-
vm.store(address(impl), bytes32(uint256(0)), bytes32(0));
|
|
133
126
|
|
|
134
|
-
impl.initialize(
|
|
127
|
+
impl.initialize(0, 0);
|
|
135
128
|
|
|
136
129
|
assertEq(impl.FEE_PROJECT_ID(), 0, "FEE_PROJECT_ID should be 0");
|
|
137
130
|
assertEq(impl.FEE_PERCENT(), 0, "FEE_PERCENT should be 0");
|
|
138
|
-
assertEq(impl.owner(), owner, "owner mismatch");
|
|
139
131
|
}
|
|
140
132
|
|
|
141
133
|
/// @notice Calling initialize() a second time reverts with AlreadyInitialized.
|
|
@@ -148,14 +140,12 @@ contract ConstructorTest is LPSplitHookV4TestBase {
|
|
|
148
140
|
IPoolManager(address(1)),
|
|
149
141
|
IPositionManager(address(positionManager))
|
|
150
142
|
);
|
|
151
|
-
// Zero out slot 0 (owner) so initialize() can be called
|
|
152
|
-
vm.store(address(impl), bytes32(uint256(0)), bytes32(0));
|
|
153
143
|
|
|
154
144
|
// First init succeeds
|
|
155
|
-
impl.initialize(
|
|
145
|
+
impl.initialize(FEE_PROJECT_ID, FEE_PERCENT);
|
|
156
146
|
|
|
157
147
|
// Second init reverts
|
|
158
148
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_AlreadyInitialized.selector);
|
|
159
|
-
impl.initialize(
|
|
149
|
+
impl.initialize(FEE_PROJECT_ID, FEE_PERCENT);
|
|
160
150
|
}
|
|
161
151
|
}
|
package/test/DeployerTest.t.sol
CHANGED
|
@@ -99,7 +99,6 @@ contract DeployerTest is Test {
|
|
|
99
99
|
IUniV4DeploymentSplitHook hook = deployer.deployHookFor(FEE_PROJECT_ID, FEE_PERCENT, bytes32(0));
|
|
100
100
|
|
|
101
101
|
UniV4DeploymentSplitHook concreteHook = UniV4DeploymentSplitHook(payable(address(hook)));
|
|
102
|
-
assertEq(concreteHook.owner(), caller, "owner not set");
|
|
103
102
|
assertEq(concreteHook.FEE_PROJECT_ID(), FEE_PROJECT_ID, "feeProjectId not set");
|
|
104
103
|
assertEq(concreteHook.FEE_PERCENT(), FEE_PERCENT, "feePercent not set");
|
|
105
104
|
}
|
package/test/NativeETHTest.t.sol
CHANGED
|
@@ -43,8 +43,7 @@ contract NativeETHTest is LPSplitHookV4TestBase {
|
|
|
43
43
|
IPoolManager(address(1)),
|
|
44
44
|
IPositionManager(address(positionManager))
|
|
45
45
|
);
|
|
46
|
-
|
|
47
|
-
testableHook.initialize(owner, FEE_PROJECT_ID, FEE_PERCENT);
|
|
46
|
+
testableHook.initialize(FEE_PROJECT_ID, FEE_PERCENT);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
// -----------------------------------------------------------------------
|
package/test/PriceMathTest.t.sol
CHANGED
|
@@ -137,8 +137,7 @@ contract PriceMathTest is LPSplitHookV4TestBase {
|
|
|
137
137
|
IPoolManager(address(1)),
|
|
138
138
|
IPositionManager(address(positionManager))
|
|
139
139
|
);
|
|
140
|
-
|
|
141
|
-
testableHook.initialize(owner, FEE_PROJECT_ID, FEE_PERCENT);
|
|
140
|
+
testableHook.initialize(FEE_PROJECT_ID, FEE_PERCENT);
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
// ─────────────────────────────────────────────────────────────────────
|
package/test/TestBaseV4.sol
CHANGED
|
@@ -142,7 +142,7 @@ contract LPSplitHookV4TestBase is Test {
|
|
|
142
142
|
IPositionManager(address(positionManager))
|
|
143
143
|
);
|
|
144
144
|
hook = UniV4DeploymentSplitHook(payable(LibClone.clone(address(hookImpl))));
|
|
145
|
-
hook.initialize(
|
|
145
|
+
hook.initialize(FEE_PROJECT_ID, FEE_PERCENT);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// ─── Directory Helpers (write to fallback-based mock) ───────────────
|
|
@@ -53,18 +53,17 @@ contract L25_FeeProjectIdValidationTest is Test {
|
|
|
53
53
|
UniV4DeploymentSplitHook clone = UniV4DeploymentSplitHook(payable(LibClone.clone(address(hookImpl))));
|
|
54
54
|
|
|
55
55
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_FeePercentWithoutFeeProject.selector);
|
|
56
|
-
clone.initialize(
|
|
56
|
+
clone.initialize(0, 3800); // feeProjectId=0, feePercent=38%
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/// @notice initialize succeeds when feePercent == 0 and feeProjectId == 0 (no fees configured).
|
|
60
60
|
function test_initialize_succeeds_zero_feePercent_zero_feeProjectId() public {
|
|
61
61
|
UniV4DeploymentSplitHook clone = UniV4DeploymentSplitHook(payable(LibClone.clone(address(hookImpl))));
|
|
62
62
|
|
|
63
|
-
clone.initialize(
|
|
63
|
+
clone.initialize(0, 0); // both zero is fine
|
|
64
64
|
|
|
65
65
|
assertEq(clone.FEE_PERCENT(), 0);
|
|
66
66
|
assertEq(clone.FEE_PROJECT_ID(), 0);
|
|
67
|
-
assertEq(clone.owner(), address(this));
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
/// @notice initialize succeeds when feePercent > 0 and feeProjectId != 0 (valid fee config).
|
|
@@ -75,10 +74,9 @@ contract L25_FeeProjectIdValidationTest is Test {
|
|
|
75
74
|
|
|
76
75
|
UniV4DeploymentSplitHook clone = UniV4DeploymentSplitHook(payable(LibClone.clone(address(hookImpl))));
|
|
77
76
|
|
|
78
|
-
clone.initialize(
|
|
77
|
+
clone.initialize(2, 3800); // feeProjectId=2, feePercent=38%
|
|
79
78
|
|
|
80
79
|
assertEq(clone.FEE_PERCENT(), 3800);
|
|
81
80
|
assertEq(clone.FEE_PROJECT_ID(), 2);
|
|
82
|
-
assertEq(clone.owner(), address(this));
|
|
83
81
|
}
|
|
84
82
|
}
|
|
@@ -21,10 +21,8 @@ import {
|
|
|
21
21
|
MockJBPermissions
|
|
22
22
|
} from "../mock/MockJBContracts.sol";
|
|
23
23
|
|
|
24
|
-
/// @notice Regression test for M-32: Re-initialization
|
|
25
|
-
/// @dev
|
|
26
|
-
/// in initialize() would pass again, allowing an attacker to re-initialize with malicious
|
|
27
|
-
/// fee parameters. The fix uses an explicit `initialized` boolean.
|
|
24
|
+
/// @notice Regression test for M-32: Re-initialization protection.
|
|
25
|
+
/// @dev The `initialized` boolean prevents calling initialize() more than once.
|
|
28
26
|
contract M32_ReinitAfterRenounceTest is Test {
|
|
29
27
|
UniV4DeploymentSplitHook public hookImpl;
|
|
30
28
|
UniV4DeploymentSplitHook public hook;
|
|
@@ -34,11 +32,9 @@ contract M32_ReinitAfterRenounceTest is Test {
|
|
|
34
32
|
MockJBPermissions public permissions;
|
|
35
33
|
MockPositionManager public positionManager;
|
|
36
34
|
|
|
37
|
-
address public owner;
|
|
38
35
|
address public attacker;
|
|
39
36
|
|
|
40
37
|
function setUp() public {
|
|
41
|
-
owner = makeAddr("owner");
|
|
42
38
|
attacker = makeAddr("attacker");
|
|
43
39
|
|
|
44
40
|
directory = new MockJBDirectory();
|
|
@@ -61,38 +57,29 @@ contract M32_ReinitAfterRenounceTest is Test {
|
|
|
61
57
|
|
|
62
58
|
// Clone and initialize
|
|
63
59
|
hook = UniV4DeploymentSplitHook(payable(LibClone.clone(address(hookImpl))));
|
|
64
|
-
hook.initialize(
|
|
60
|
+
hook.initialize(2, 3800); // feeProjectId=2, feePercent=38%
|
|
65
61
|
}
|
|
66
62
|
|
|
67
|
-
/// @notice
|
|
68
|
-
function
|
|
69
|
-
// Verify initial state
|
|
70
|
-
assertEq(hook.owner(), owner);
|
|
63
|
+
/// @notice Re-initialization should revert.
|
|
64
|
+
function test_reinitialize_reverts() public {
|
|
71
65
|
assertEq(hook.FEE_PROJECT_ID(), 2);
|
|
72
66
|
assertEq(hook.FEE_PERCENT(), 3800);
|
|
73
67
|
assertTrue(hook.initialized());
|
|
74
68
|
|
|
75
|
-
// Owner renounces ownership
|
|
76
|
-
vm.prank(owner);
|
|
77
|
-
hook.renounceOwnership();
|
|
78
|
-
|
|
79
|
-
// owner() is now address(0)
|
|
80
|
-
assertEq(hook.owner(), address(0));
|
|
81
|
-
|
|
82
69
|
// Attacker tries to re-initialize with malicious parameters
|
|
83
70
|
vm.prank(attacker);
|
|
84
71
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_AlreadyInitialized.selector);
|
|
85
|
-
hook.initialize(
|
|
72
|
+
hook.initialize(2, 10_000); // trying to set 100% fee
|
|
86
73
|
}
|
|
87
74
|
|
|
88
75
|
/// @notice The `initialized` flag is set to true after first initialization.
|
|
89
|
-
function test_initialized_flag_set() public {
|
|
76
|
+
function test_initialized_flag_set() public view {
|
|
90
77
|
assertTrue(hook.initialized(), "initialized should be true after initialize()");
|
|
91
78
|
}
|
|
92
79
|
|
|
93
|
-
/// @notice Double initialization
|
|
80
|
+
/// @notice Double initialization also still reverts.
|
|
94
81
|
function test_double_init_reverts() public {
|
|
95
82
|
vm.expectRevert(UniV4DeploymentSplitHook.UniV4DeploymentSplitHook_AlreadyInitialized.selector);
|
|
96
|
-
hook.initialize(
|
|
83
|
+
hook.initialize(2, 5000);
|
|
97
84
|
}
|
|
98
85
|
}
|