Summary
In dexAdapter
, there is insufficiant slippage check.
Vulnerability Details
BaseAdapter.sol
95: function getExpectedOutput(
address tokenIn,
address tokenOut,
uint256 amountIn
)
public
view
returns (uint256 expectedAmountOut)
{
if (amountIn == 0) revert Errors.ZeroExpectedSwapOutput();
UD60x18 priceTokenInX18 = IPriceAdapter(swapAssetConfigData[tokenIn].priceAdapter).getPrice();
UD60x18 priceTokenOutX18 = IPriceAdapter(swapAssetConfigData[tokenOut].priceAdapter).getPrice();
UD60x18 amountInX18 = Math.convertTokenAmountToUd60x18(swapAssetConfigData[tokenIn].decimals, amountIn);
expectedAmountOut = Math.convertUd60x18ToTokenAmount(
swapAssetConfigData[tokenOut].decimals, amountInX18.mul(priceTokenInX18).div(priceTokenOutX18)
);
if (expectedAmountOut == 0) revert Errors.ZeroExpectedSwapOutput();
}
128:function calculateAmountOutMin(uint256 amountOutMinExpected) public view returns (uint256 amountOutMin) {
amountOutMin =
(amountOutMinExpected * (Constants.BPS_DENOMINATOR - slippageToleranceBps)) / Constants.BPS_DENOMINATOR;
}
https://github.com/Cyfrin/2025-01-zaros-part-2/blob/main/src/utils/dex-adapters/UniswapV3Adapter.sol#L98
function executeSwapExactInputSingle(SwapExactInputSinglePayload calldata swapPayload)
external
returns (uint256 amountOut)
{
IERC20(swapPayload.tokenIn).transferFrom(msg.sender, address(this), swapPayload.amountIn);
IUniswapV3RouterInterface swapRouter = IUniswapV3RouterInterface(uniswapV3SwapStrategyRouter);
IERC20(swapPayload.tokenIn).approve(address(swapRouter), swapPayload.amountIn);
uint256 expectedAmountOut = getExpectedOutput(swapPayload.tokenIn, swapPayload.tokenOut, swapPayload.amountIn);
98: uint256 amountOutMin = calculateAmountOutMin(expectedAmountOut);
return swapRouter.exactInputSingle(
IUniswapV3RouterInterface.ExactInputSingleParams({
tokenIn: swapPayload.tokenIn,
tokenOut: swapPayload.tokenOut,
fee: feeBps,
recipient: swapPayload.recipient,
deadline: deadline,
amountIn: swapPayload.amountIn,
amountOutMinimum: amountOutMin,
sqrtPriceLimitX96: 0
})
);
}
As we can see, expectedAmountOut
and amountOutMin
are calculated in the same transaction.
If the prices from the priceAdapter
and the dexAdapter
are both subject to slippage, then this slippage check may not be necessary
Impact
Insufficient slippage checks for users can result in the loss of funds due to price fluctuations.
Recommendations
Consider allowing users to enter an amountOutMin
.