The validation function checks `currency1` twice instead of checking both `currency0` and `currency1`, allowing pools without the ReFi token to be initialized.
**Description**:
* The normal behavior expects the hook to validate that the ReFi token is present in the pool (either as currency0 or currency1) before allowing pool initialization.
* The specific issue is that the condition checks `currency1` against `ReFi` twice, never checking `currency0`, which means pools where ReFi is currency0 will incorrectly revert, and pools without ReFi at all might pass validation incorrectly.
**Root cause in the codebase**:
```solidity
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();
}
```
The condition `currency1 != ReFi && currency1 != ReFi` is always false (a value cannot be both equal and not equal to ReFi), so this check never reverts. Additionally, `currency0` is never checked.
The validation logic is fundamentally broken. Here are three scenarios demonstrating the issue:
```solidity
PoolKey memory key;
key.currency0 = Currency.wrap(ReFi);
key.currency1 = Currency.wrap(otherToken);
if (Currency.unwrap(key.currency1) != ReFi &&
Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
key.currency0 = Currency.wrap(otherToken);
key.currency1 = Currency.wrap(ReFi);
if (Currency.unwrap(key.currency1) != ReFi &&
Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
key.currency0 = Currency.wrap(tokenA);
key.currency1 = Currency.wrap(tokenB);
if (Currency.unwrap(key.currency1) != ReFi &&
Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}
```
**Step-by-step execution demonstrating the critical bug:**
1. Attacker creates a pool with two arbitrary tokens (no ReFi)
2. Pool initialization calls hook's `_beforeInitialize()`
3. Validation checks: `currency1 != ReFi && currency1 != ReFi`
4. This condition can never be true (same value compared to itself)
5. Validation always passes, pool initializes without ReFi
6. Hook's `_isReFiBuy()` logic fails because ReFi is not in the pool
7. Fee application becomes unpredictable, breaking protocol functionality
```diff
// src/RebateFiHook.sol:122-126
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();
}
```