RebateFi Hook

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

Incorrect ReFi Token Presence Validation in `_beforeInitialize`, Causes Rejection of Valid Pools

Incorrect ReFi Token Presence Validation in _beforeInitialize, Causes Rejection of Valid Pools

Description

  • The hook’s beforeInitialize function implements an incorrect validation check to ensure that the ReFi token is present in the pool. The logic only verifies currency1, and does so using a duplicated condition, which effectively ignores cases where ReFi is placed in currency0.


  • Since Uniswap V4 enforces a deterministic lexicographical ordering of token addresses during pool creation, it is entirely possible — and in many cases likely — that ReFi will be assigned to currency0. In such scenarios, the hook reverts with ReFiNotInPool(), even though the pool configuration is completely valid and expected to be supported.


  • As a result, legitimate ReFi trading pairs (e.g., ReFi/USDC, ReFi/WETH, ReFi/DAI) cannot be initialized, preventing liquidity provisioning and rendering the hook incompatible with standard Uniswap pool setups. This breaks core protocol functionality and severely restricts the usability of the ReFi ecosystem on Uniswap V4.


/// @notice Validates that ReFi token is in the pool before initialization
/// @param key The pool key containing currency pair information
/// @return Function selector for success
function _beforeInitialize(address, PoolKey calldata key, uint160) internal view override returns (bytes4) {
@> if (Currency.unwrap(key.currency1) != ReFi &&
@> Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
return BaseHook.beforeInitialize.selector;
}

Risk

Likelihood:

  • This always happens when trying to create a pool with ReFi token in currency0.


Impact:

  • There's a severe disruption of protocol functionality or availability.

Proof of Concept

<details>
<summary>POC</summary>
1. Add this test to `RebateFiHookTest.t.sol` test file.
```javascript
function test_LogicProof_CannotHaveReFiAsCurrency0() public view {
// ---------------------------------------------
// 1. Fake PoolKey where ReFi = currency0
// ---------------------------------------------
PoolKey memory fakeKey;
fakeKey.currency0 = reFiCurrency; // ReFi in token0
fakeKey.currency1 = tokenCurrency; // normal token in token1
// ---------------------------------------------
// 2. Reproduce the HOOK condition exactly
// ---------------------------------------------
bool condition =
(Currency.unwrap(fakeKey.currency1) != address(reFiToken)) &&
(Currency.unwrap(fakeKey.currency1) != address(reFiToken));
// According to the real hook:
// if (condition == true) revert ReFiNotInPool();
bool willRevert = condition;
console.log("--------------------------------------");
console.log("Simulating _beforeInitialize logic:");
console.log("ReFi is placed in currency0");
console.log("Hook checks ONLY currency1");
console.log("Condition evaluates to:", willRevert);
console.log("--------------------------------------");
// ---------------------------------------------
// 3. Assert the BUG: hook will ALWAYS revert
// ---------------------------------------------
assertTrue(
willRevert,
"BUG: Hook will always revert when ReFi is in currency0"
);
}
```
</details>

Recommended Mitigation

1.Modify the `_beforeInitialize` function so that the verification is working correctly.
```diff
/// @notice Validates that ReFi token is in the pool before initialization
/// @param key The pool key containing currency pair information
/// @return Function selector for success
function _beforeInitialize(address, PoolKey calldata key, uint160) internal view override returns (bytes4) {
- if (Currency.unwrap(key.currency1) != ReFi &&
+ if (Currency.unwrap(key.currency0) != ReFi &&
Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
return BaseHook.beforeInitialize.selector;
}
```
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!