The Standard

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

Differences in the `PriceCalculator::tokenToEur` and `PriceCalculator::tokenToEurAvg` will lead to swap attack causing protocol loss

Summary

This attack could still be executed when PriceCalculator::tokenToEur < PriceCalculator::tokenToEurAvg, but with less impact.

Vulnerability Details

Bad debt note

The main invariant of collateralised stablecoins: Issued stable coin value <= collateral value * collateral factor (or euro value < collateral value / collateralRate in terms of The Standard protocol), where 0 <= collateral factor <= 1. This invariant should be valid both for each position and for the whole protocol.

There are two cases of invariant break for a position:

  • collateral value * collateral factor < Issued stable coin value <= collateral value - in such cases, the position is liquidated, collateral is sold, and its value is enough to repay (burn) all issued stablecoins.

  • Issued stable coin value > collateral value - in such cases, the position is also liquidated, collateral is sold, but its value is not enough to repay (burn) all issued stablecoins:

    • X - issued stablecoins, Y - repaid and burnt during liquidation stablecoins where Y < X. X-Y is the protocol's bad debt. It means if all users close their positions, X-Y stablecoins are still issued. But this amount is backed by nothing.

When the protocol has bad debt, the fair price of a stablecoin = (Issued stablecoins - Bad debt) / Issued stablecoins and it is < 1. It means that the stablecoin tends to be unpegged.

To return the peg, the protocol must buy stablecoins from the market and burn them. It means that Bad debt is the direct protocol loss.

Key facts:

  • There are two types of prices in the PriceCalculator interface and they are used in the SmartVaultV3.

  • tokenToEurAvg is the average price for some period (currently 4h).

  • In general, on a falling/rising market, PriceCalculator::tokenToEur and PriceCalculator::tokenToEurAvg could be different (with the current average duration of 4h - dramatically different).

Attack example (similar to the attack described in the tweet):

  • Falling market (prices provided to simplify calculations)

    • Current BTC price (PriceCalculator::tokenToEur) 10000 euro/btc.

    • Average BTC price (PriceCalculator::tokenToEurAvg) 11000 euro/btc.

    • Current Eth price (PriceCalculator::tokenToEur) 1000 euro/eth.

  • Attacker deposits 1 BTC.

  • Attacker mints 5000 EUROs.

  • Attacker initiates swap of 1 BTC (see SmartVaultManagerV5::swap and SmartVaultManagerV5::calculateMinimumAmountOut):

    • Calculations inside of SmartVaultManagerV5::calculateMinimumAmountOut:

      • requiredCollateralValue = 5000 * 110 / 100 = 5500.

      • euroCollateral = 11000 (since it is calculated by avg prices), calculator.tokenToEur(1 BTC) = 10000.

      • collateralValueMinusSwapValue = 11000 - 10000 = 1000.

      • Result of calculateMinimumAmountOut() = calculator.eurToToken(5500 - 1000) = calculator.eurToToken(4500) = 4.5 eth.

  • Attacker manipulates the liquidity of the btc/eth pool and manages to get 4.5 eth from swapping 1 BTC.

  • Attacker has outside of the vault:

    • 5000 minted EUROs.

    • 1 BTC (10000 euros) - 4.5 eth (4500 euros) = 5500 euros value of profit.

    • Total attacker profit = 10500 euros - flash loans and Uniswap fees for manipulations.

  • Protocol has:

    • Minted = 5000 EUROs.

    • Collateral value = 4500 euros.

    • Bad debt = 500 EUROs.

So the attack could be executed when PriceCalculator::tokenToEur < PriceCalculator::tokenToEurAvg. More difference makes more profit for the attacker and more losses for the protocol.

Impact

The protocol will lose funds due to bad debt.

Tools Used

Manual review

Recommended Mitigation

In general, it is incorrect to use different types of prices in one formula (this also applies to calculations of eur/usd in the PriceCalculator::tokenToEurAvg).

Chainlink uses the VWAP algorithm (https://chain.link/education-hub/twap-vs-vwap) for price calculations, manual average calculation could be skipped and only the last price used.

Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

Bad-debt

khramov Submitter
almost 2 years ago
hrishibhat Lead Judge almost 2 years 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.

Give us feedback!