RebateFi Hook

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

Incorrect ReFi buy/sell detection in _isReFiBuy function

Root + Impact

Description

Under normal behavior, the _isReFiBuy function should correctly determine whether the current swap is buying the ReFi token or selling it.
To do this, the function must consider two things:

  • whether ReFi is currency0 or currency1 in the pool

  • the direction of the swap, defined by the zeroForOne flag:

    • zeroForOne = true means swapping currency0 → currency1

    • zeroForOne = false means swapping currency1 → currency0

However, the current implementation only checks whether ReFi is currency0 and does not properly combine this with the swap direction.
Because of this, the function often returns the wrong result — identifying a sell as a buy, or a buy as a sell.

function _isReFiBuy(PoolKey calldata key, bool zeroForOne) internal view returns (bool) {
bool IsReFiCurrency0 = Currency.unwrap(key.currency0) == ReFi;
// @ Incorrect logic: only checks position of ReFi, not the actual swap direction
if (IsReFiCurrency0) {
return zeroForOne;
} else {
return !zeroForOne;
}
}

Risk

Likelihood:

  • Every swap that involves the ReFi token goes through _isReFiBuy. Since the function misclassifies buy/sell direction, the wrong branch is taken on every single swap involving ReFi.

  • Any user, bot, or LP (=liquidity provider) interacting with this pool triggers the faulty logic automatically — no special conditions or rare edge cases are required.

Impact:

  • Buy swaps can be treated as sells and charged a high sell fee, creating unexpected losses for users.

  • Sell swaps can be treated as buys and charged the low buy fee, causing the protocol to lose revenue and completely breaking the intended tokenomics.

Proof of Concept

// Scenario: ReFi is currency0 in the pool
PoolKey key;
key.currency0 = ReFi;
key.currency1 = USDC;
// Swap direction: zeroForOne = true (currency0 -> currency1)
// This means we are SELLING ReFi.
bool zeroForOne = true;
// Call the function
bool result = _isReFiBuy(key, zeroForOne);
// EXPECTED: false (this is a sell)
// ACTUAL: true (function thinks it's a buy)

Recommended Mitigation

- if (IsReFiCurrency0) {
- return zeroForOne;
- } else {
- return !zeroForOne;
- }
+ // Correct buy/sell logic based on token position and swap direction
+ bool IsReFiCurrency0 = Currency.unwrap(key.currency0) == ReFi;
+
+ if (IsReFiCurrency0) {
+ // ReFi is token0:
+ // zeroForOne=true → selling token0 (ReFi)
+ // zeroForOne=false → buying token0 (ReFi)
+ if (zeroForOne) {return false};
+ else {return true};
+ } else {
+ // ReFi is token1:
+ // zeroForOne=true → buying token1 (ReFi)
+ // zeroForOne=false → selling token1 (ReFi)
+ if (zeroForOne) {return true};
+ else {return false};
+ }
Updates

Lead Judging Commences

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