15,000 USDC
View results
Submission Details
Severity: medium
Valid

Chainlink.latestRoundData price not checked

Summary

AggregatorV3Interface.latestRoundData function returns the price of a specific asset. The price comes as a signed integer and has to be checked because there are possible scenarios where Chainlink oracle can return zero or even worse negative answer.

Source:
https://youtu.be/a5G6k6NFsCg?t=134

Vulnerability Details

The function priceFeed.staleCheckLatestRoundData() can return a negative price(int256) which after that is cast to uint256().
Currently, this oracle function is used in 2 places: getUsdValue and getTokenAmountFromUsd.
The problem is most likely to occur in the second function, especially on this specific line where we calculate the token amount from USD for the passed collateral.

In case of answer equal to 0, division by zero will occur on this line:

return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);

If the returned answer is lower than 0, there will be silent underflow. Let's assume that the oracle's answer is -1, after cast we will receive this number:

uint256(-1) = 115792089237316195423570985008687907853269984665640564039457584007913129639935

Impact

Liquidations will be blocked because getTokenAmountFromUsd will always revert when additional precision is applied (1e10) so it will be more than type(uint256).max.

If the price is 0 it will lead to division by 0 in getTokenAmountFromUsd and getUsdValue functions.

Tools Used

Manual

Recommendations

Check if the price is greater than 0. Consider using OpenZeppelin’s SafeCast library to prevent unexpected overflows when casting from uint256.

Support

FAQs

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