The owner can manually set the fee > 100%, which will result in the pool lock.
Description
The owner can manually set the fee > 100%, and because of this, any swap will cause LPFeeTooLarge revert, which will result in the pool being lock.
function ChangeFee(bool _isBuyFee, uint24 _buyFee, bool _isSellFee, uint24 _sellFee) external onlyOwner {
@> if (_isBuyFee) buyFee = _buyFee;
@> if (_isSellFee) sellFee = _sellFee;
}
Risk
Likelihood:
Impact:
Proof of Concept
1) Set extreme sell fee > 100%;
2) Make swap. Now any swap must break the pool with a LPFeeTooLarge revert;
3) If the pool was locked, you will see a message "As expected, the pool is locked due to too large fee > 100%".
function test_PoC_PoolBlockedByTooLargeFee() public {
uint24 extremeSellFee = 1_000_001;
rebateHook.ChangeFee(false, 0, true, extremeSellFee);
(, uint24 currentSellFee) = rebateHook.getFeeConfig();
assertEq(currentSellFee, extremeSellFee, "Sell fee should be updated to extreme value");
uint256 reFiAmount = 0.001 ether;
vm.startPrank(user1);
reFiToken.approve(address(swapRouter), type(uint256).max);
SwapParams memory params = SwapParams({
zeroForOne: true, amountSpecified: -int256(reFiAmount), sqrtPriceLimitX96: TickMath.MIN_SQRT_PRICE + 1
});
PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, extremeSellFee));
swapRouter.swap(key, params, testSettings, ZERO_BYTES);
vm.stopPrank();
console.log("As expected, the pool is locked due to too large fee > 100%");
}
Recommended Mitigation
Limit the hook to the safest possible fee range, for example ≤ 50% depending on the tokenomics, and check the limit inside ReFiSwapRebateHook::ChangeFee().
+uint24 constant MAX_FEE = 500_000; // 50%
function ChangeFee(bool _isBuyFee, uint24 _buyFee, bool _isSellFee, uint24 _sellFee) external onlyOwner {
- if (_isBuyFee) buyFee = _buyFee;
+ if (_isBuyFee) {
+ require(_buyFee <= MAX_FEE, "BuyFeeTooHigh");
+ buyFee = _buyFee;
+ }
- if (_isSellFee) sellFee = _sellFee;
+ if (_isSellFee) {
+ require(_sellFee <= MAX_FEE, "SellFeeTooHigh");
+ sellFee = _sellFee;
+ }
}