RebateFi Hook

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

Mishandling of the tokens - A miscalculation in the fee amount causes users to pay more tokens for fee than expected.

Root + Impact

Description

  • Due to a miscalculation in the ReFiSwapRebateHook::_beforeSwap function, the user will be charged 10 times more. For instance, instead of the expected initial sellFee of 0.3%, the user's balance will be deducted by 3% for the swap fee.

  • The problem is that currently, the denominator of the division is 100_000. However, it is supposed to be the standard 1_000_000.

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) / 100_000;
emit ReFiSold(sender, swapAmount, feeAmount);
}
return (
BaseHook.beforeSwap.selector,
BeforeSwapDeltaLibrary.ZERO_DELTA,
fee | LPFeeLibrary.OVERRIDE_FEE_FLAG
);
}

Risk

Likelihood: High

  • Since it is an unconditional part of the system, it happens every time a user sells their ReFi tokens (swaps for another ERC20 token)

Impact:

  • It severely affects the program because it charges the users 10x the expected swap fee amount.


Proof of Concept

It can be easily and manually calculated. The initial sellFee is set to 3_000, and the denominator is 100_000. The result of 3000 / 100000 = 0.03. By multipying it by 100 to get the percentage, we will have 3% which drastically differs from what we expected (0.3%).

Recommended Mitigation

To solve the issue, please make the following changes to the code.

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) / 100_000;
+ uint256 feeAmount = (swapAmount * sellFee) / 1_000_000;
emit ReFiSold(sender, swapAmount, feeAmount);
}
return (
BaseHook.beforeSwap.selector,
BeforeSwapDeltaLibrary.ZERO_DELTA,
fee | LPFeeLibrary.OVERRIDE_FEE_FLAG
);
}
Updates

Lead Judging Commences

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!