RebateFi Hook

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

Miscomputed fee amount in ReFiSold event (10× too large)

Description

  • Uniswap v4 dynamic LP fees are expressed in units where 1e6 = 100%, i.e., fee rates are in hundredths of a bip. A sell fee of 3000 represents 0.3% (3000 / 1_000_000). When emitting analytics events, the computed feeAmount should use the same denominator so off-chain systems and dashboards reflect the correct fee magnitude.

  • In _beforeSwap(), the event ReFiSold(sender, swapAmount, feeAmount) computes feeAmount using a denominator of 100000 instead of 1_000_000. This scales the reported fee by 10× (e.g., 3000 becomes ~3%), misleading analytics, alerting systems, and revenue accounting that rely on the event.

// Root cause in the codebase with @> marks to highlight the relevant section
function _beforeSwap(
address sender,
PoolKey calldata key,
SwapParams calldata params,
bytes calldata
) internal override returns (bytes4, BeforeSwapDelta, uint24) {
bool isReFiBuy = _isReFiBuy(key, params.zeroForOne);
uint256 swapAmount = params.amountSpecified < 0
? uint256(-params.amountSpecified)
: uint256(params.amountSpecified);
uint24 fee;
if (isReFiBuy) {
fee = buyFee;
emit ReFiBought(sender, swapAmount);
} else {
fee = sellFee;
@> uint256 feeAmount = (swapAmount * sellFee) / 100000; // <-- wrong denominator (should be 1_000_000)
emit ReFiSold(sender, swapAmount, feeAmount);
}
return (
BaseHook.beforeSwap.selector,
BeforeSwapDeltaLibrary.ZERO_DELTA,
fee | LPFeeLibrary.OVERRIDE_FEE_FLAG
);
}

Risk

Likelihood: High

  • Happens on every sell swap where the hook emits ReFiSold, regardless of pool, users, or amounts.

  • Occurs continuously in production usage; no special edge case required.

Impact: Low

  • Analytics misinformation: Off‑chain dashboards and data pipelines will record 10× larger fees than actually charged, corrupting revenue metrics, trader cost analysis, and protocol reporting.

  • Operational errors: Treasury forecasting, alerts, and fee‑based automations may trigger incorrectly (e.g., assuming unusually high fees or revenue), leading to misguided decisions.

Proof of Concept

  • This test that demonstrates the discrepancy between the event’s feeAmount and the correct calculation:

function test_ReFiSoldEventFeeIs10xTooLarge() public {
// Arrange: set sell fee to the default 3000 (0.3%)
( , uint24 currentSellFee) = rebateHook.getFeeConfig();
assertEq(currentSellFee, 3000);
// Perform a sell of 1 ether worth of ReFi
uint256 reFiAmount = 1 ether;
vm.startPrank(user1);
reFiToken.approve(address(swapRouter), type(uint256).max);
// Expect event and capture arguments
//vm.expectEmit(true, false, false, false);
// We compute expected WRONG amount using current code path to demonstrate the mismatch
uint256 wrongFeeAmount = (reFiAmount * currentSellFee) / 100000; // 10x too large
//emit ReFiSwapRebateHook.ReFiSold(user1, reFiAmount, wrongFeeAmount);
SwapParams memory params = SwapParams({
zeroForOne: false, // ReFi -> other (sell)
amountSpecified: -int256(reFiAmount),
sqrtPriceLimitX96: TickMath.MAX_SQRT_PRICE - 1
});
PoolSwapTest.TestSettings memory testSettings = PoolSwapTest.TestSettings({
takeClaims: false,
settleUsingBurn: false
});
swapRouter.swap(key, params, testSettings, ZERO_BYTES);
vm.stopPrank();
// Compute the CORRECT fee amount using 1e6 denominator:
uint256 correctFeeAmount = (reFiAmount * currentSellFee) / 1_000_000;
assertEq(wrongFeeAmount, correctFeeAmount * 10, "Event fee is 10x the correct amount");
}

Recommended Mitigation

  • Use the correct denominator 1_000_000 (1e6) for dynamic fees:

- uint256 feeAmount = (swapAmount * sellFee) / 100000;
+ uint256 feeAmount = (swapAmount * sellFee) / 1_000_000; // 1e6 = 100%
Updates

Lead Judging Commences

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

Incorrect denominator (100000 instead of likely 1000000 or 10000) in fee calculation for ReFiSold event.

Support

FAQs

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

Give us feedback!