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).
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:
The following are defined:
requiredCollateralValue
- the collateral required to stay in the vault for the amount of EUROs that it has minted (minted
)
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:
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.
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.
``
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.
Manual review
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.