RebateFi Hook

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

Incorrect Check in `_beforeInitialize` Prevents Pool Creation

Incorrect Check in _beforeInitialize Prevents Pool Creation

Description

  • The _beforeInitialize hook is designed to ensure that any new liquidity pool using this hook includes the ReFi token.

  • However, the implementation contains a logical flaw: if (Currency.unwrap(key.currency1) != ReFi && Currency.unwrap(key.currency1) != ReFi). It incorrectly checks key.currency1 twice and fails to check key.currency0 at all.

  • As a result, the hook will incorrectly revert and prevent the creation of any pool where ReFi is currency0, which occurs whenever the other token's address is alphabetically greater than the ReFi token's address.

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 bug will prevent the creation of any Uniswap v4 pool using this hook where the ReFi token's address is lower than the other token's address, a condition which makes ReFi the currency0 in the PoolKey.

Impact:

  • The hook fails its primary purpose of allowing ReFi to be paired with any other token. It arbitrarily blocks the creation of valid liquidity pools, limiting the utility and reach of the ReFi ecosystem on Uniswap v4.

  • This creates a significant barrier to liquidity providers who wish to create pools with common tokens that happen to have a higher address value than the ReFi token.

Proof of Concept

The provided test case demonstrates that pool initialization reverts when ReFi is currency0. The hook should allow this, but due to the bug, it reverts.

function test_Revert_WhenReFiIsCurrency0() public {
// Ensure currency0 < currency1 for the pool key
Currency currency0 = reFiCurrency; // 0x212224D2F2d262cd093eE13240ca4873fcCBbA3C
Currency currency1 = Currency.wrap(0x222224d2f2d262Cd093EE13240cA4873FCCBba3c);
// Create a pool key with ReFi as one of the currencies
PoolKey memory newPoolKey = PoolKey({
currency0: currency0,
currency1: currency1,
fee: LPFeeLibrary.DYNAMIC_FEE_FLAG,
tickSpacing: 60,
hooks: rebateHook
});
vm.expectRevert();
// Attempt to initialize the pool
manager.initialize(newPoolKey, SQRT_PRICE_1_1_s);
}

Recommended Mitigation

The logic should be corrected to check both currency0 and currency1, and it should revert only if neither of them is the ReFi token.

function _beforeInitialize(address, PoolKey calldata key, uint160) internal view override returns (bytes4) {
- if (Currency.unwrap(key.currency1) != ReFi && 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!