20,000 USDC
View results
Submission Details
Severity: high
Valid

Tokens in Fees.sol can be drained due to bad UniV3 swap configuration

Summary

Fees.sol's publicly accessible sellProfits() accepts 100% slippage and price deviation from the Uniswap V3 swap.

Vulnerability Details

The culprit is this call:

ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: _profits,
tokenOut: WETH,
fee: 3000,
recipient: address(this),
deadline: block.timestamp,
amountIn: amount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});

There are 3 apparent problems:

  • amountOutMinimum is set to 0, which means that the swap will not revert even if it received 0 WETH in exchange.

  • sqrtPriceLimitX96 is set to 0, which means that the swap can have infinite price impact on the pool.

  • fee is hardcoded to 0.3% and no check is made that the 0.3%-fee pool is the most liquid or liquid at all.

Read more at Uniswap V3: Swap Input Parameters.

Impact

Critical. A sophisticated actor can listen for sellProfits() calls in the mempool and sandwich attack the sellProfits() transaction to extract 100% of the token, leaving 0.

This is highly automated in production on Ethereum, as there are many specialized and general MEV bots that look out for such sandwich attack opportunities.

Tools Used

Manual Review, Uniswap V3 Documentation

Recommendations

Selling on-chain is hard without running into MEV issues. One option is to use a shielded swapping service such as CoWSwap.

Another option is to read Uniswap V3's built-in TWAP oracle to impose restrictions on transaction slippage and price impact. The most liquid fee-tier can be chosen on-demand by querying historical liquidity, which can be used to impose a minimum liquidity.

Support

FAQs

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