RebateFi Hook

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

Inverted Buy/Sell Fee Logic Applies Wrong Fees

Root + Impact

The _isReFiBuy function has inverted logic when ReFi is currency0, causing buy fees to be applied on sells and sell fees on buys, breaking the core fee mechanism.

Description

  • The hook applies different fees for buying ReFi (0%) vs selling ReFi (0.3%) to incentivize holding.

  • In Uniswap V4, zeroForOne=true means swapping currency0 FOR currency1. When ReFi is currency0, zeroForOne=true means SELLING ReFi, not buying.

function _isReFiBuy(PoolKey calldata key, bool zeroForOne) internal view returns (bool) {
bool IsReFiCurrency0 = Currency.unwrap(key.currency0) == ReFi; // @> should be key.currency1 instead
@> if (IsReFiCurrency0) {
@> return zeroForOne; // @> WRONG: zeroForOne=true when ReFi is currency0 means SELLING
} else {
return !zeroForOne;
}
}

Risk

Likelihood:

  • Occurs on every swap in pools where ReFi is currency0

  • Users attempting to buy ReFi pay sell fees (0.3%) while sellers pay no fee

Impact:

  • Complete reversal of intended economic incentives

  • Buyers are penalized instead of sellers, discouraging accumulation

  • Protocol loses fee revenue on actual sells

Proof of Concept

Here is the basic steps to understand the issue in the logic

// Pool: ReFi (currency0) / ETH (currency1)
// User wants to BUY ReFi (swap ETH → ReFi)
// This requires zeroForOne = false (swapping currency1 for currency0)
//
// _isReFiBuy logic:
// IsReFiCurrency0 = true
// return zeroForOne = false → Treated as SELL, applies 0.3% fee
//
// User wants to SELL ReFi (swap ReFi → ETH)
// This requires zeroForOne = true
// return zeroForOne = true → Treated as BUY, applies 0% fee

Recommended Mitigation

Invert the return value when ReFi is currency0:

function _isReFiBuy(PoolKey calldata key, bool zeroForOne) internal view returns (bool) {
bool IsReFiCurrency0 = Currency.unwrap(key.currency0) == ReFi;
if (IsReFiCurrency0) {
- return zeroForOne;
+ return !zeroForOne; // Buying ReFi means receiving currency0, so zeroForOne=false
} else {
return !zeroForOne;
}
}
Updates

Lead Judging Commences

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

Inverted buy/sell logic when ReFi is currency0, leading to incorrect fee application.

Support

FAQs

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

Give us feedback!