The Standard

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

Lack of slippage check allows sandwich attacks when a vault owner execute a swap

Description

SmartVaultV3::swap does not allow to specify the min amount of _outToken the vault owner is willing to receive. Instead, it use as slippage the min amount of this token to receive in order to keep the vault collateralized. Therefore, anyone who front run a SmartVaultV3::swap transaction can take advantage by manipulating the price before and after the transaction

Impact

The current implementation of SmartVaultV3::swap is susceptible to sandwich attacks.

POC

  1. Alice has a vault with 10 WBTC valued at 1_100_000 EUR

  2. Alice mint 10_000 EUROS through this vault

  3. Alice wants to swap 1 WBTC for ETH. Current rate according AMM where the swap is done through ``SmartVaultV3::swap` is 1 WBTC = 10 ETH. So Alice sent the transcation expecting to get 1 ETH

  4. Bob see these and he has enough funds to manipulate WBTC/ETH LP price, therefore the exchange rate in this LP now is 1 WBTC = 0.01 ETH

  5. Alice transaction pass, but she gets just 0.01 ETH

  6. Bob return the LP to its initial state, getting around 9.99 ETH as profit

Severity justification

Enable theft of funds

Recommended mitigation

Add a parameter to SmartVaultV3::swap that consider _outToken slippage

function swap(
bytes32 _inToken,
bytes32 _outToken,
- uint256 _amount
+ uint256 _amount,
+ uint256 minAmountOut
) external onlyOwner {
// Fee to pay
uint256 swapFee = _amount * ISmartVaultManagerV3(manager).swapFeeRate() / ISmartVaultManagerV3(manager).HUNDRED_PC();
// Token to exchange
address inToken = getSwapAddressFor(_inToken);
uint256 minimumAmountOut = calculateMinimumAmountOut(_inToken, _outToken, _amount);
+ if(minimumAmountOut < minAmountOut) minimumAmountOut = minAmountOut; // max(minimumAmountOut, minAmountOut)
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);
}
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!