The expected behavior is that the hook validates whether the ReFi token is present in the pool before initialization. The pool uses currency0 and currency1 to represent its paired assets. Proper validation requires checking both currencies so that initialization cannot proceed unless either currency0 or currency1 equals the ReFi token.
Protocol invariants relying on ReFi presence are broken, potentially enabling misconfigured liquidity pools and downstream accounting or reward distribution errors.
function test_PoC_beforeInitialize_reverts_when_ReFi_is_currency0() public {
deployFreshManagerAndRouters();
MockERC20 other = new MockERC20("OTHER", "OTH", 18);
MockERC20 refi = new MockERC20("RE-FI", "RFI", 18);
Currency cOther = Currency.wrap(address(other));
Currency cRefi = Currency.wrap(address(refi));
uint256 attempts = 0;
while (address(refi) >= address(other) && attempts < 50) {
other = new MockERC20("OTHER", "OTH", 18);
cOther = Currency.wrap(address(other));
attempts++;
}
require(address(refi) < address(other), "Could not make refi address < other address; retry test");
bytes memory creationCode = type(ReFiSwapRebateHook).creationCode;
bytes memory constructorArgs = abi.encode(manager, address(refi));
uint160 flags = uint160(
Hooks.BEFORE_INITIALIZE_FLAG |
Hooks.AFTER_INITIALIZE_FLAG |
Hooks.BEFORE_SWAP_FLAG
);
(address expectedHook, bytes32 salt) = HookMiner.find(
address(this),
flags,
creationCode,
constructorArgs
);
ReFiSwapRebateHook hook = new ReFiSwapRebateHook{salt: salt}(manager, address(refi));
require(address(hook) == expectedHook, "Hook address mismatch (mined)");
bytes memory expectedErr = abi.encodeWithSelector(ReFiSwapRebateHook.ReFiNotInPool.selector);
vm.expectRevert(expectedErr);
initPool(cRefi, cOther, hook, LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1_s);
}
*/
[68231765] TestReFiSwapRebateHook::test_PoC_beforeInitialize_reverts_when_ReFi_is_currency0()
├─ [6957545] → new PoolManager@0xD16d567549A2a2a2005aEACf7fB193851603dd70
│ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: TestReFiSwapRebateHook: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ └─ ← [Return] 34623 bytes of code
├─ [2064771] → new PoolSwapTest@0x96d3F6c20EEd2697647F543fE6C08bC2Fbf39758
│ └─ ← [Return] 10310 bytes of code
├─ [1101289] → new SwapRouterNoChecks@0x13aa49bAc059d709dd0a18D6bb63290076a702D7
│ └─ ← [Return] 5498 bytes of code
├─ [1846957] → new PoolModifyLiquidityTest@0xDB25A7b768311dE128BBDa7B8426c3f9C74f3240
│ └─ ← [Return] 9222 bytes of code
├─ [1375580] → new PoolModifyLiquidityTestNoChecks@0x3381cD18e2Fb4dB236BF0525938AB6E43Db0440f
│ └─ ← [Return] 6868 bytes of code
├─ [1550396] → new PoolDonateTest@0x756e0562323ADcDA4430d6cb456d9151f605290B
│ └─ ← [Return] 7741 bytes of code
├─ [1296683] → new PoolTakeTest@0x1aF7f588A501EA2B5bB3feeFA744892aA2CF00e6
│ └─ ← [Return] 6474 bytes of code
├─ [924111] → new PoolClaimsTest@0xe8dc788818033232EF9772CB2e6622F1Ec8bc840
│ └─ ← [Return] 4613 bytes of code
├─ [6353741] → new PoolNestedActionsTest@0x3Cff5E7eBecb676c3Cb602D0ef2d46710b88854E
│ ├─ [4514755] → new NestedActionExecutor@0x04cf47d237A7e4358C874a9767f79bBFC62F8495
│ │ └─ ← [Return] 21188 bytes of code
│ └─ ← [Return] 8546 bytes of code
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← [Return] feeController: [0xb52F5153576Ca8b1d3eD645A8F76809Bd1a62620]
├─ [0] VM::label(feeController: [0xb52F5153576Ca8b1d3eD645A8F76809Bd1a62620], "feeController")
│ └─ ← [Return]
├─ [3003679] → new ActionsRouter@0x27cc01A4676C73fe8b6d0933Ac991BfF1D77C4da
│ └─ ← [Return] 14777 bytes of code
├─ [23988] PoolManager::setProtocolFeeController(feeController: [0xb52F5153576Ca8b1d3eD645A8F76809Bd1a62620])
│ ├─ emit ProtocolFeeControllerUpdated(protocolFeeController: feeController: [0xb52F5153576Ca8b1d3eD645A8F76809Bd1a62620])
│ └─ ← [Stop]
├─ [1193737] → new MockERC20@0x796f2974e3C1af763252512dd6d521E9E984726C
│ └─ ← [Return] 5720 bytes of code
├─ [1193737] → new MockERC20@0x92a6649Fdcc044DA968d94202465578a9371C7b1
│ └─ ← [Return] 5720 bytes of code
├─ [1193737] → new MockERC20@0xDA5A5ADC64C8013d334A0DA9e711B364Af7A4C2d
│ └─ ← [Return] 5720 bytes of code
├─ [1736687] → new ReFiSwapRebateHook@0x91D6dF936455e866cA64f1d4297A25d5ED997080
│ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: TestReFiSwapRebateHook: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ └─ ← [Return] 8533 bytes of code
├─ [0] VM::expectRevert(custom error 0xf28dceb3: 000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000047ac0d4d700000000000000000000000000000000000000000000000000000000)
│ └─ ← [Return]
├─ [7547] PoolManager::initialize(PoolKey({ currency0: 0x92a6649Fdcc044DA968d94202465578a9371C7b1, currency1: 0xDA5A5ADC64C8013d334A0DA9e711B364Af7A4C2d, fee: 8388608 [8.388e6], tickSpacing: 60, hooks: 0x91D6dF936455e866cA64f1d4297A25d5ED997080 }), 79228162514264337593543950336 [7.922e28])
│ ├─ [1598] ReFiSwapRebateHook::beforeInitialize(TestReFiSwapRebateHook: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], PoolKey({ currency0: 0x92a6649Fdcc044DA968d94202465578a9371C7b1, currency1: 0xDA5A5ADC64C8013d334A0DA9e711B364Af7A4C2d, fee: 8388608 [8.388e6], tickSpacing: 60, hooks: 0x91D6dF936455e866cA64f1d4297A25d5ED997080 }), 79228162514264337593543950336 [7.922e28])
│ │ └─ ← [Revert] ReFiNotInPool()