The Standard

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

Different Price Calculations During Liquidation of Vault and Asset Distribution Could Cause Bad Debt

Summary

If PriceCalculator::tokenToEurAvg / the last Chainlink price > SmartVaultManagerV5::collateralRate, the protocol will incur bad debt after liquidation.

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:

  • Two types of prices are used during liquidation:

    • PriceCalculator.tokenToEurAvg is the average price for some period (currently 4h), used to determine if a vault can be liquidated:

      • SmartVaultV3::liquidate -> SmartVaultV3::undercollateralised -> SmartVaultV3::maxMintable -> SmartVaultV3::euroCollateral.

    • The latest Chainlink price during collateral distribution:

      • LiquidationPool::distributeAssets.

  • On a falling/rising market, PriceCalculator::tokenToEurAvg and the last Chainlink price could be different (with the current average duration of 4h - dramatically different).

If PriceCalculator::tokenToEurAvg / the last Chainlink price > collateralRate, the protocol will incur bad debt after liquidation. Given that the current collateralRate is 110% and the average period is 4h, it's a realistic scenario, especially for volatile assets like BTC, which could fall more than 20% within 4 hours.

Possible scenario (all calculations are simplified for illustration):

  • Falling market (prices provided to simplify calculations)

    • The last BTC price (PriceCalculator::tokenToEur) 10,000 EUR/BTC.

    • Average BTC price (PriceCalculator::tokenToEurAvg) 12,000 EUR/BTC.

  • User deposits 1 BTC.

  • User mints 10_900 EUROs (maximum considering collateralRate).

  • Average price (PriceCalculator::tokenToEurAvg) falls to 11_500 eur/btc after some time.

  • Liquidation is triggered.

  • In LiquidationPool::distributeAssets():

    • 10_000 EUROs are repaid and burnt (using the last price)

      • Not considering dividing by collateralRate in the calculation of costInEuros due to another finding.

      • If it were taken into account, the burnt amount would be even less.

As a result, 10_900 EUROs were minted, but only 10_000 EUROs were burnt, leaving 900 EUROs as bad debt.

Impact

This discrepancy in price calculations during liquidation could lead to the protocol incurring bad debt.

Tools Used

Manual review

Recommended Mitigation

  • Use PriceCalculator as the sole source of price data in all places

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

Updates

Lead Judging Commences

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

Bad-debt

khramov 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.