DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: low
Invalid

wrong LibsUsdOracle::getUsdPrice calculation leads to incorrect liquidations

Summary

/**
* @dev Returns the price of a given token in in USD with the option of using a lookback. (Usd:token Price)
* lookback should be 0 if the instantaneous price is desired. Otherwise, it should be the
* TWAP lookback in seconds.
* If using a non-zero lookback, it is recommended to use a substantially large lookback
* (> 900 seconds) to protect against manipulation.
*/

The core issue stems from how the function getUsdPrice interprets and calculates the USD price of a given token. The documentation suggests it aims to return the value of a token in terms of USD (e.g., $1,500 for 1 ETH). However, the calculation performed does the opposite. It tries to find out how much of a token you can get for 1 unit of USD, which is not the direct USD price of the token.

Vulnerability Details

/**
* @dev Returns the price of a given token in in USD with the option of using a lookback. (Usd:token Price)
* lookback should be 0 if the instantaneous price is desired. Otherwise, it should be the
* TWAP lookback in seconds.
* If using a non-zero lookback, it is recommended to use a substantially large lookback
* (> 900 seconds) to protect against manipulation.
*/

The function documentation suggests it aims to return the price of a given token in USD (e.g., how many USD one unit of the token is worth). However, the calculation performed (uint256(1e24).div(ethUsdPrice)) inversely calculates the price, potentially leading to a misunderstanding of what value is being returned. If ethUsdPrice represents the number of USD cents (or a similarly scaled unit) one ETH is worth, then simply returning ethUsdPrice would be more appropriate than attempting to invert this value. The current calculation might suggest an attempt to calculate how many tokens one can buy with one unit of USD, scaled up by a factor of 1e24, which contradicts the stated purpose.

Impact

With the oracle reporting 1 WETH = $3,500, the correct collateral value should be $35,000 USD (10 WETH * $3,500/WETH), which still meets the loan's collateralization requirement.
However, due to the calculation error, the platform incorrectly concludes that the collateral value has fallen below the required threshold and initiates a liquidation of the user's collateral.
The user's collateral is wrongly liquidated, causing a loss of funds based on an inaccurate valuation of the collateral.

Tools Used

Manual Review

Recommendations

The function should directly return the oracle-reported price without attempting to invert it, ensuring the returned value aligns with the common understanding and expectations of a "price in USD."

if (token == C.WETH) { uint256 ethUsdPrice = LibEthUsdOracle.getEthUsdPrice(lookback); if (ethUsdPrice == 0) return 0; // Directly return the price assuming ethUsdPrice is already scaled appropriately. return ethUsdPrice; }

Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

Support

FAQs

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