The Standard

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

Old vulnerability in SwapRouterV2 is not fixed probably, attacker still can exploit when token price gradually reduce

Summary

Old vulnerability in SwapRouterV2 is not fixed probably, attacker still can exploit when token price gradually reduce by abusing difference of value between average price and current price

Vulnerability Details

As discussed by sponor, function calculateMinimumAmountOut() is used to ensures that the amount out is minimum amount to keep the vault collateralised:

img

But it is not enough to avoid. Take a look at calculate amount out function:

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

collateralValueMinusSwapValue is calculated based on two variable: variable returned from euroCollateral() function, and variable returned from tokenToEur() function. Function euroCollateral() is calculated based on average price in 4 hours of token:

function euroCollateral() private view returns (uint256 euros) {
    ITokenManager.Token[] memory acceptedTokens = getTokenManager().getAcceptedTokens();
    for (uint256 i = 0; i < acceptedTokens.length; i++) {
        ITokenManager.Token memory token = acceptedTokens[i];
        euros += calculator.tokenToEurAvg(token, getAssetBalance(token.symbol, token.addr));    //<-------
    }
}

tokenToEurAvg() function:

function tokenToEurAvg(ITokenManager.Token memory _token, uint256 _tokenValue) external view returns (uint256) {
    Chainlink.AggregatorV3Interface tokenUsdClFeed = Chainlink.AggregatorV3Interface(_token.clAddr);
    uint256 scaledCollateral = _tokenValue * 10 ** getTokenScaleDiff(_token.symbol, _token.addr);
    uint256 collateralUsd = scaledCollateral * avgPrice(4, tokenUsdClFeed);     //   <--- price of collateral to usd is calculated based on average price in 4 hours
    (, int256 eurUsdPrice,,,) = clEurUsd.latestRoundData();
    return collateralUsd / uint256(eurUsdPrice);
}

About tokenToEur() function, it is calculated based on lastest price of token:

function tokenToEur(ITokenManager.Token memory _token, uint256 _tokenValue) external view returns (uint256) {
    Chainlink.AggregatorV3Interface tokenUsdClFeed = Chainlink.AggregatorV3Interface(_token.clAddr);
    uint256 scaledCollateral = _tokenValue * 10 ** getTokenScaleDiff(_token.symbol, _token.addr);
    (,int256 _tokenUsdPrice,,,) = tokenUsdClFeed.latestRoundData();    //  <---- get lastest price
    uint256 collateralUsd = scaledCollateral * uint256(_tokenUsdPrice);
    (, int256 eurUsdPrice,,,) = clEurUsd.latestRoundData();
    return collateralUsd / uint256(eurUsdPrice);
}

The gap between average price and actual price can be exploited. Consider scenario, when collateralRate = 110%:

  • Price of WBTC gradually reduce from 40000 to 30000 in 4 hours, assume at that time price returned from function tokenToEurAvg() is 35000

  • Deposit 1 WBTC, which is worth 30000 in that time

  • Mint all EUROs token possible with that number of collateral

  • Swap WBTC to another token. At this step, collateralValueMinusSwapValue should returned 0, but it returned 5000 due to the gap between euroCollateral() and calculator.tokenToEur(getToken(_inTokenSymbol), _amount)

  • Repeat old steps like the way SmartVaultV2 was exploited before, link. But not like old one, it only can be exploit by using gap of 2 variables

Profit from this attack will depend on collateral rate, minting fee and total % price drop in 4 hours. But as described below, this attack vector is possible

Impact

Attack can mint more EUROs token that he should, which will harm to protocol

Tools Used

Manual review

Recommendations

Let user submit their own minimumAmountOut variable, but make sure that vault will not be under collateralised when swap

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Slippage-issue

greatlake Submitter
over 1 year ago
hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

avg-spot-price

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.