shealtielanz
medium
The Chainlink
price feed's input is not validated and latestRoundData()
has no check for round completeness.
There is no check in the getPriceUSD()
function of the oracles for round completeness, or the returned timestamp
, and this could lead to stale, outdated, or wrong price return value, which could affect other functions that depend on the getPriceUSD()
function.
The issue occurs in the following Oracle contracts respectively.
contracts/oracles/StableOracleDAI.sol
Lines of Code
contracts/oracles/StableOracleWBGL.sol
Lines of Code
contracts/oracles/StableOracleWBTC.sol
Lines of Code
contracts/oracles/StableOracleWETH.sol
Lines of code
Sample of the code.
(, int256 price, , , ) = priceFeedDAIETH.latestRoundData();
//@audit no check for `latestRoundData` if it's zero or a negative number.
//@audit no check for `latestRoundData` for the returned timestamp.
return
(wethPriceUSD * 1e18) /
((DAIWethPrice + uint256(price) * 1e10) / 2);
as seen in the code above the returned timestamp
is not checked, and there is no check for round completeness
.
function calculateMint(address _token, uint256 _amount) public view returns (uint256 stableCoinAmount) {
//@audit here it calls the getPriceUSD function.
uint256 assetPrice = collateral[getCollateralIndex(_token)].oracle.getPriceUSD();
return (((assetPrice * _amount) / 1e18) * (10 ** decimals())) / (10 ** IERC20MetadataUpgradeable(_token).decimals());
USSD.sol
The calculateMint
function could malfunction and be exploited due to incorrect values that can be gotten from the getPriceUSD()
function from the Oracle
.
According to Chainlink's
documentation, this function does not error if no answer has been reached but returns 0 or outdated
round data. The external Chainlink oracle
, which provides index price information to the system, introduces risk inherent to any dependency on third-party
data sources. For example, the oracle
could fall behind or otherwise fail to be maintained, resulting in outdated
data being fed to the index price calculations. Oracle's
reliance has historically resulted in crippled on-chain systems
, and complications that lead to these outcomes can arise from things as simple as network congestion
.
More Information/Reason for this Click this
This could lead to stale prices
and wrong price return value, or outdated
prices.
As a result, the functions that rely on accurate price feed might not work as expected due to wrong calculations made with stale prices, which sometimes can lead to fund loss. The impacts vary and depend on specific situations.
https://github.com/USSDofficial/ussd-contracts/blob/f44c726371f3152634bcf0a3e630802e39dec49c/contracts/oracles/StableOracleWBTC.sol#LL21C1-L25C38 https://github.com/USSDofficial/ussd-contracts/blob/f44c726371f3152634bcf0a3e630802e39dec49c/contracts/oracles/StableOracleWBGL.sol#LL24C1-L40C2 https://github.com/USSDofficial/ussd-contracts/blob/f44c726371f3152634bcf0a3e630802e39dec49c/contracts/oracles/StableOracleDAI.sol#LL33C1-L54C2
Manual Review
Validate
data feed for round completeness
and for returned timestamp
An instance of Validation
with code
- (, int256 price, , , ) = priceFeedDAIETH.latestRoundData();
+ (, int256 exchangeRate, , uint256 updatedAt , ) = priceFeedDAIETH.latestRoundData();
+ if(price <= 0) revert ZeroExchangeRate.
+ if(if (updatedAt < block.timestamp - 60 * 60 /* 1 hour */) {
+ revert OutdatedTimestamp();
+}
return
(wethPriceUSD * 1e18) /
((DAIWethPrice + uint256(price) * 1e10) / 2);