RebateFi Hook

First Flight #53
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

H03 Fee Denominator Mismatch in _beforeSwap

Root + Impact

Description

In normal behavior, _beforeSwap calculates a dynamic LP fee based on the buy or sell direction. The fee is used to generate the LP fee override applied to swaps in Uniswap V4.

The issue is that the code computes feeAmount using a denominator of 100_000, while Uniswap V4 pools expect fees scaled to 1_000_000 (MAX_LP_FEE). This creates a 10× discrepancy between the intended and actual fee:

  • For example, a configured sellFee = 3_000 is treated as 3% by the hook, but Uniswap interprets it as 0.3%, causing misreporting and incorrect fee application.

// Root cause in the codebase with @> marks to highlight the relevant section
uint256 feeAmount = (swapAmount * sellFee) / 100_000; // @> incorrect denominator

Risk

Likelihood:

  • High, since any sell swap triggers this calculation.

  • Medium, because users assume fees match reported percentages, but actual fees are off by 10×.

Impact:

  • Users are overcharged or undercharged compared to intended ReFi economics.

  • Protocol revenue projections and tokenomics incentives are misaligned.

Proof of Concept

Explanation

This test demonstrates that a swap reports an incorrect fee amount due to the denominator mismatch.

function test_SellFeeMismatch() public {
uint256 reFiAmount = 1 ether;
// Set sellFee to 30_000 (intended as 30%)
rebateHook.ChangeFee(false, 0, true, 30_000);
vm.startPrank(user1);
reFiToken.approve(address(swapRouter), type(uint256).max);
SwapParams memory params = SwapParams({
zeroForOne: false, // ReFi -> ETH
amountSpecified: -int256(reFiAmount),
sqrtPriceLimitX96: TickMath.MAX_SQRT_PRICE - 1
});
PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({
takeClaims: false,
settleUsingBurn: false
});
// Perform swap
swapRouter.swap(key, params, testSettings, ZERO_BYTES);
// Compute expected fee with correct denominator
uint256 expectedFee = (reFiAmount * 30_000) / 1_000_000; // Uniswap V4 uses 1_000_000
uint256 actualFee = (reFiAmount * 30_000) / 100_000; // current hook logic
assertGt(actualFee, expectedFee, "Hook calculates 10x larger fee than Uniswap V4 expects");
vm.stopPrank();
}
  • This demonstrates that the fee applied to swaps is mis-scaled, leading to unintended financial behavior.

Recommended Mitigation

Adjust _beforeSwap to use the correct denominator corresponding to Uniswap V4’s MAX_LP_FEE (1_000_000).

Function modified: _beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata)
- uint256 feeAmount = (swapAmount * sellFee) / 100_000;
+ uint256 feeAmount = (swapAmount * sellFee) / 1_000_000;
Updates

Lead Judging Commences

chaossr Lead Judge
15 days ago
chaossr Lead Judge 12 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!