The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

SmartVaultV3 - insufficient slippage protection in swap()

Summary

The swap function in SmartVaultV3 does not have sufficient slippage protection because minimumAmountOut can be 0 in certain cases, making the swap vulnerable to MEV attacks.

Vulnerability Details

Let's take a look at the code:

function swap(bytes32 _inToken, bytes32 _outToken, uint256 _amount) external onlyOwner {
uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
address inToken = getSwapAddressFor(_inToken);
uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount); <---
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: inToken,
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount - swapFee,
amountOutMinimum: minimumAmountOut, <---
sqrtPriceLimitX96: 0
});
inToken == ISmartVaultManagerV3(manager).weth() ?
executeNativeSwapAndFee(params, swapFee) :
executeERC20SwapAndFee(params, swapFee);
}

The function passes amountOutMinimum: minimumAmountOut for slippage protection. Let's see how minimumAmountOut is calculated:

function calculateMinimumAmountOut(bytes32 _inTokenSymbol, bytes32 _outTokenSymbol, uint256 _amount) private view returns (uint256) {
ISmartVaultManagerV3 _manager = ISmartVaultManagerV3(manager);
uint256 requiredCollateralValue = minted * _manager.collateralRate() / _manager.HUNDRED_PC();
uint256 collateralValueMinusSwapValue = euroCollateral() - calculator.tokenToEur(getToken(_inTokenSymbol), _amount);
return collateralValueMinusSwapValue >= requiredCollateralValue ?
0 : calculator.eurToToken(getToken(_outTokenSymbol), requiredCollateralValue - collateralValueMinusSwapValue);
}

The function calculates requiredCollateralValue, which is the amount of collateral that needs to be maintained in the vault.
Then it calculates collateralValueMinusSwapValue which is the current collateral value in the vault (euroCollateral()) minus the EUR equivalent of the _amount of the input token being swapped.
Then in the case where collateralValueMinusSwapValue is greater than or equal to requiredCollateralValue it returns 0 offering no slippage protection to the swap.

Impact

The swap will be subject to MEV attacks and will result in unfavorable swapping conditions leading to a loss of funds.

Tools Used

Manual review

Recommendations

You can implement a default slippage protection value that gets returned by the calculateMinimumAmountOut() function instead of returning 0.
Or you could add a user-specified slippage parameter that gets passed to the calculateMinimumAmountOut() function and is returned instead of returning 0.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Slippage-issue

icebear Auditor
over 1 year ago
hrishibhat Lead Judge
over 1 year ago
hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Slippage-issue

Support

FAQs

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