The Standard

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

Slippage can be set to 0

Summary

The SmartVault contract has a function that allows the user to perform swaps with amountOutMinimum = 0.

Vulnerability Details

The SmartVaultV3::swap() allows users to swaps the assets the vault has for another asset.

https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/SmartVaultV3.sol#L222-L232

@> 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
});

The amountOutMinimum variable of the swap is calculated through the calculateMinimumAmountOut(). This function makes sure that there will be enough collateral to cover the current minted position even after the swap.

https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/SmartVaultV3.sol#L213-L214

uint256 requiredCollateralValue = minted * _manager.collateralRate() / _manager.HUNDRED_PC();
uint256 collateralValueMinusSwapValue = euroCollateral() - calculator.tokenToEur(getToken(_inTokenSymbol), _amount);

In the event the swapped amount doesn't impact the collaterisation rate of the loan, the calculateMinimumAmountOut() function will return 0. which means that the swap will be executed without slippage.

https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/SmartVaultV3.sol#L215-L216

return collateralValueMinusSwapValue >= requiredCollateralValue ?
@> 0 : calculator.eurToToken(getToken(_outTokenSymbol), requiredCollateralValue - collateralValueMinusSwapValue);

Impact

The swapped funds of the borrower can be lost as they are exposed to a 0 slippage swap.

Tools Used

manual review

Recommendations

Allow the user to set slippage if the position remains. This logic below will fix the function.

function calculateMinimumAmountOut(bytes32 _inTokenSymbol, bytes32 _outTokenSymbol, uint256 _amount, uint256 minOut) private view returns (uint256) {
ISmartVaultManagerV3 _manager = ISmartVaultManagerV3(manager);
uint256 requiredCollateralValue = minted * _manager.collateralRate() / _manager.HUNDRED_PC();
uint256 collateralValueMinusSwapValue = euroCollateral() - calculator.tokenToEur(getToken(_inTokenSymbol), _amount);
uint256 minRequiredOut = calculator.eurToToken(getToken(_outTokenSymbol), requiredCollateralValue - collateralValueMinusSwapValue)
return collateralValueMinusSwapValue >= requiredCollateralValue ?
@> minOut : getMax(minRequiredOut, minOut) ;
}
function getMax(uint256 var1, uint256 var2) public pure returns (uint256) {
if (var1 >= var2) {
return var1;
} else {
return var2;
}
}
Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

Slippage-issue

hrishibhat Lead Judge almost 2 years 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.

Give us feedback!