The Standard

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

Vault executes swaps with chances of sandwich attack

Summary

The vault executes swaps with no slippage protection which will cause a loss of funds due of sandwich attacks.

Vulnerability Details

The concept of slippage is often associated with market orders, where the executed price might deviate from the expected price due to market fluctuations. In the context of SmartVaultV3.sol contract, slippage might occur if the calculated minimumAmountOut is not set appropriately. If it's set too low, there's a risk that the actual output tokens received might be less than expected, potentially causing the transaction to revert.

This is the swap function that performs the swap:

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

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

function setOwner(address _newOwner) external onlyVaultManager {
    owner = _newOwner;
}

This is the calculateMinimumAmountOut function that calculates the minimum amount out:

https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/SmartVaultV3.sol#L206

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

Impact

Swaps will be sandwiched that causes loss of funds.

Here's a scenario:

1, Legitimate Transaction: A user initiates a legitimate swap with the contract, and calculateMinimumAmountOut returns 0 because the collateral after the swap is sufficient.

2, Sandwich Attack: An attacker quickly executes a series of transactions, including one before and one after the legitimate swap. The attacker aims to manipulate prices or take advantage of the legitimate trader's actions.

3, Outcome: The attacker's transactions could impact the price and lead to undesirable results for the legitimate trader.

Tools Used

Manual Review

Recommendations

A slippage tolerance parameter can be used. Ex:

             uint256 slippageTolerance = 5; // 5% slippage tolerance

             uint256 minimumAmountOut = (expectedAmountOut * (100 - slippageTolerance)) / 100;
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.