The Standard

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

Vault's `calculateMinimumAmountOut()` will always allow for swaps prone to a slippage attack

Summary

The way calculateMinimumAmountOut() calculates the minimum amount out expected from swap executed within the vault is making it prone to slippage attacks in both cases (as it returns 2 results depending whether there'll be enough collateral left to cover the minted EUROs).

Vulnerability Details

When calculating the minimum amount expected of _outTokenSymbol in SmartVaultV3#swap(), the value returned is never in favour of the owner of the vault.
Let's observe the calculateMinimumAmountOut() function itself:

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 following are defined:

  1. requiredCollateralValue - the collateral required to stay in the vault for the amount of EUROs that it has minted (minted)

  2. collateralValueMinusSwapValue - the total collateral within the vault minus the amount of the token we are swapping priced in euro.

Getting to the return statement we have 2 scenarios possible:

  1. collateralValueMinusSwapValue >= requiredCollateralValue
    Meaning if there's is enough collateral to cover the EUROs amount minted, the minimum amount of _outToken (the one we swapping for) will be 0. This is an absolute no-go when performing swaps as such can be sandwiched and the swap can be forcefully executed at unfavourable prices for a third party's profit. This is mentioned in the Known Issues, however nothing is said about the second case.

  2. collateralValueMinusSwapValue < requiredCollateralValue
    In this case, we get the required collateral value minus swap value in euro, subtract the result from the required collateral value and convert that last result to an amount of _outToken.
    Let's take this for example:

    • Required collateral (requiredCollateralValue) = 1000 €

    • Collateral value in € (euroCollateral()) = 1100 € (User haven't used up all of his collateral when minting EUROs)

    • Token in amount to € (calculator.tokenToEur(getToken(_inTokenSymbol), _amount)) = 500 €

    • Collateral value in € - token in amount in € (collateralValueMinusSwapValue) = 1100 € - 500 € = 600 €

    • Minimum amount out (return value of function) = required collateral - (collateral value in € - token in amount to €) = 1000 € - (1100 € - 500 €) = 1000 € - 600 € = 400 €

    Which leads to the following situation: We want to swap 1 token worth of 500 €, expecting to get minimum 400 € and essentially leaving the door open for sandwich attacking this swap and causing it to execute at unfavourable prices at loss for the owner of the vault.
    ``

Impact

All swaps executed within a vault will eventually be executed in a manner prone to being sandwiched and forcefully going through at unfavourable prices for the owner of the vault, causing them to realize losses.

Tools Used

Manual review

Recommendations

I'm unsure what the whole idea behind the current implementation of the calculateMInimumAmountOut function is, but since you are only allowing swapping between accepted tokens, it'd be best to just calculate the amount of outToken that the amount of inToken is worth in order to ensure a minimum slippage when the trades execute.

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.