The Standard

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

Vault executes swaps without slippage protection if collateral amount is higher than threshold

Summary

The SmartVaultV3::swap() is used to swap collateral in the vault to allow the adjustment of risk. In the swap function the SmartVaultV3::calculateMinimumAmountOut() is called, user can swap any tokens that are not whitelisted as collateral for the vault if the collateralValueMinusSwapValue is more than requiredCollateralValue.

The SmartVaultV3::calculateMinimumAmountOut() is used to check if the collateral in the vault is in excess, which means that the amount of collateral is higher than the threshold of collateral.

However in the SmartVaultV3::calculateMinimumAmountOut(), user swap amountOutMinimum will be set to 0, which invites sandwich attacks.

This is similar to my other report, but the vulnerability is different thus a different report.

Vulnerability Details

//SmartVaultV3.sol
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);
//@audit If there are excess collateral and is more than the threshold, the minimum is set to 0 inviting sandwich attacks
return collateralValueMinusSwapValue >= requiredCollateralValue ?
0 : calculator.eurToToken(getToken(_outTokenSymbol), requiredCollateralValue - collateralValueMinusSwapValue); //@audit-issue
}
...
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); // @audit used wrapped ether as price feeds?
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: inToken,
tokenOut: getSwapAddressFor(_outToken),
fee: 3000,
recipient: address(this),
deadline: block. Timestamp,
amountIn: _amount - swapFee,
amountOutMinimum: minimumAmountOut, // @audit Invites sandwich attacks
sqrtPriceLimitX96: 0
});
inToken == ISmartVaultManagerV3(manager).weth() ?
executeNativeSwapAndFee(params, swapFee) :
executeERC20SwapAndFee(params, swapFee);
}

Impact

Swaps will be sandwiched causing a loss of funds for users you withdraw their rewards.

Tools Used

Manual Review

Recommendations

Allow the caller pass a minAmountOut parameter to the function, which checks that the final output in tokens is not too low.

Updates

Lead Judging Commences

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

Slippage-issue

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.