RebateFi Hook

First Flight #53
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Severity: high
Valid

H02. beforeInitialize - Incorrect Pool Token Validation

Root + Impact

Description

  • Normally, _beforeInitialize is supposed to validate that the pool being initialized contains the designated ReFi token in either currency0 or currency1. This ensures that the hook only attaches to relevant pools.

  • The specific issue is that _beforeInitialize contains a logic bug where it checks currency1 twice instead of checking both currency0 and currency1.

// Root cause in the codebase with @> marks to highlight the relevant section
function _beforeInitialize(address, PoolKey calldata key, uint160) internal view override returns (bytes4) {
if (Currency.unwrap(key.currency1) != ReFi &&
Currency.unwrap(key.currency1) != ReFi) { // @> should check key.currency0 here
revert ReFiNotInPool();
}
return BaseHook.beforeInitialize.selector;
}

Risk

Likelihood:

  • The hook will attach to any pool where currency0 is ReFi but currency1 is not, because currency0 is never checked.

  • The hook could also attach to pools that contain neither token if currency1 happens to be something else, bypassing the intended validation.

Impact:

  • The hook will incorrectly execute fee logic on pools that do not actually contain the ReFi token.

  • Swap operations in these misconfigured pools may apply buy/sell fees to irrelevant token pairs, leading to unexpected token deductions or fee misapplications.

Proof of Concept

The following test demonstrates that the hook allows initialization of a pool that does not include the ReFi token:

function test_IncorrectPoolTokenValidation() public {
// Deploy a fake token that is not ReFi
MockERC20 fakeToken = new MockERC20("FAKE", "FKE", 18);
Currency fakeCurrency = Currency.wrap(address(fakeToken));
// Try to initialize a pool with FAKE as currency0 and ReFi as currency1
vm.expectRevert(ReFiSwapRebateHook.ReFiNotInPool.selector);
PoolKey memory fakeKey = PoolKey({
currency0: fakeCurrency,
currency1: Currency.wrap(address(reFiToken)), // currency1 is ReFi
tickSpacing: 1,
fee: LPFeeLibrary.DYNAMIC_FEE_FLAG
});
rebateHook._beforeInitialize(address(this), fakeKey, 0);
}

Explanation:
Because _beforeInitialize only checks currency1 twice, the check incorrectly passes if currency0 is not ReFi, allowing the hook to attach to the pool. Any subsequent swaps in this pool will apply ReFi fee logic incorrectly.

Recommended Mitigation

- if (Currency.unwrap(key.currency1) != ReFi &&
- Currency.unwrap(key.currency1) != ReFi) {
+ if (Currency.unwrap(key.currency0) != ReFi &&
+ Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
You said:
Updates

Lead Judging Commences

chaossr Lead Judge 11 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Faulty pool check; only checks currency1 twice, omitting currency0.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!