RebateFi Hook

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

_beforeInitialize() does not check if currency0 is ReFi, causing initPool() to revert with error ReFiNotInPool() even if currency0 is in fact ReFi

_beforeInitialize() does not check if currency0 is ReFi, causing initPool() to revert with error ReFiNotInPool() even if currency0 is in fact ReFi

Description

  • In RebateFiHook.sol, the _beforeInitialize() function checks to ensure that the ReFi token is in the pool.

  • However, it erroneously checks key.currency1 twice instead of checking both key.currency0and key.currency1.

  • As a result, even if currency0 is ReFi, the function will revert, preventing the creation of pools where the ReFi token is currency0 rather than currency1.

  • Since UniswapV4's PoolManager.sol reverts if currency0 >= currency1 (forcing trading pairs to be sorted properly), developers cannot simply force the ReFi token address into currency1 each time. If a token's address is greater than the ReFi token address, every attempt to pair them in a pool together with the RebateFi Hook will fail.

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: High

  • Depends on the ReFi token contract's address (could be very high or very low), but on average half of all possible pools would fail to initialize.

Impact: Medium

  • Denial of service. The RebateFi hook simply cannot be used with some tokens.

Proof of Concept

Paste the following into RebateFiHookTest.t.sol:

function test_initializeBiggerToken() public {
// Depends on the addresses generated.
MockERC20 bigToken = new MockERC20("BigToken", "BT", 18);
Currency bigTokenCurrency = Currency.wrap(address(bigToken));
PoolKey memory newKey;
(newKey, ) = initPool(
reFiCurrency,
bigTokenCurrency,
rebateHook,
LPFeeLibrary.DYNAMIC_FEE_FLAG,
SQRT_PRICE_1_1_s
);
}

Recommended Mitigation

Check both currency1 and currency0 for 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) {
+ Currency.unwrap(key.currency0) != ReFi) {
revert ReFiNotInPool();
}
return BaseHook.beforeInitialize.selector;
}
Updates

Lead Judging Commences

chaossr Lead Judge 12 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!