Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: low
Invalid

Calculating the amountOutMinimum of swaps onchain allows MEV sandwitch attack on the swap

Summary

Calculating the amountOutMinimum of swaps onchain allows MEV sandwitch attack on the swap, amountOutMinimum should be supplied as input to the function. Calculating the amountOutMinimum can be handled on the frontend.

Vulnerability Details

The swap logic of the following function calculates the amountOutMinimum onchain.

  1. CurveAdapter.sol#executeSwapExactInputSingle(....)

  2. CurveAdapter.sol#executeSwapExactInput(...)

  3. UniswapV2Adapter.sol#executeSwapExactInputSingle(...)

  4. UniswapV2Adapter.sol#executeSwapExactInput(...)

  5. UniswapV3Adapter.sol#executeSwapExactInputSingle(...)

  6. UniswapV3Adapter.sol#executeSwapExactInput(...)

Calculating amountOutMinimum onchain is worthless because:

  1. The MEV attacker bots will have adjusted the price of the pool by frontrunning

  2. After the price adjustment, then calculation of amountOutMinimum is done when executing the swap

  3. Attacker back runs the swap to sell back to the pool to make profit

So the amountOutMinimum will be calculated from the state of an already manipulated pool before in the swap transaction. That is why it is better to calculate the amountOutMinimum offchain then passed to the swap function. Calculation of `amountOutMinimum can be handled on the frontend just like it is done on swap dapps like Uniswap.

File: UniswapV3Adapter.sol
/// inheritdoc IDexAdapter
function executeSwapExactInput(SwapExactInputPayload calldata swapPayload) external returns (uint256 amountOut) {
// transfer the tokenIn from the send to this contract
IERC20(swapPayload.tokenIn).transferFrom(msg.sender, address(this), swapPayload.amountIn);
// cache uniswap v3 swap strategy router
IUniswapV3RouterInterface swapRouter = IUniswapV3RouterInterface(uniswapV3SwapStrategyRouter);
// approve the tokenIn to the swap router
IERC20(swapPayload.tokenIn).approve(address(swapRouter), swapPayload.amountIn);
// get the expected output amount
@> uint256 expectedAmountOut = getExpectedOutput(swapPayload.tokenIn, swapPayload.tokenOut, swapPayload.amountIn);
// Calculate the minimum acceptable output based on the slippage tolerance
@> uint256 amountOutMinimum =
(expectedAmountOut * (Constants.BPS_DENOMINATOR - slippageToleranceBps)) / Constants.BPS_DENOMINATOR;
return swapRouter.exactInput(
IUniswapV3RouterInterface.ExactInputParams({
path: swapPayload.path,
recipient: swapPayload.recipient,
deadline: deadline,
amountIn: swapPayload.amountIn,
amountOutMinimum: amountOutMinimum
})
);
}

Impact

Sandwich attack by MEV bots to adjust the price in a frontrunning attack and sell back to the pool after the swap there by making profit from the adjusted price. The swap buys the loss from adjusted price.

Tools Used

Manual Review

Recommendations

Consider passing amountOutMinimum as input to the swap function. This amountOutMinimum can calculated on the frontend before sending the transaction.

Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

[INVALID]On-chain slippage calculation

Support

FAQs

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