As stale price is determined by time since last timestamp, the price that is most recent, but wasn't updated for more than _PRICE_ORACLE_STALE_THRESHOLD (say there were no trades on the market) will be rejected, which makes system unavailable in such a case. This can be deemed as a conservative choice.
In the same time real stale price will be accepted as long as it happens to be within _PRICE_ORACLE_STALE_THRESHOLD window. I.e. getAssetPrice do not require the price to be the most recent / fresh, simply accepting any price given that it is not older than _PRICE_ORACLE_STALE_THRESHOLD.
Proof of Concept
getAssetPrice ignores round data, only requiring the timestamp to be new enough:
function getAssetPrice() public view override returns (uint256 price) {
(, int256 eurAnswer, , uint256 eurUpdatedAt, ) = _eurOracle.latestRoundData();
require(eurAnswer > 0, "EUR price data not valid");
require(block.timestamp - eurUpdatedAt < _PRICE_ORACLE_STALE_THRESHOLD, "EUR price data is stale");
(, int256 answer, , uint256 assetUpdatedAt, ) = _assetOracle.latestRoundData();
require(answer > 0, "Price data not valid");
require(block.timestamp - assetUpdatedAt < _PRICE_ORACLE_STALE_THRESHOLD, "Price data is stale");
I.e., recent timestamp doesn't guarantee fresh price, while fresh price can have non-recent timestamp (simply because of slow trading), so this check alone doesn't provide much protection.
Recommended Mitigation Steps
Consider imposing checks for positive price and for the round id, timestamp fields as it's suggested in the docs:
Lines of code
https://github.com/code-423n4/2022-04-mimo/blob/b18670f44d595483df2c0f76d1c57a7bfbfbc083/core/contracts/inception/priceFeed/ChainlinkInceptionPriceFeed.sol#L73-L80
Vulnerability details
As stale price is determined by time since last timestamp, the price that is most recent, but wasn't updated for more than _PRICE_ORACLE_STALE_THRESHOLD (say there were no trades on the market) will be rejected, which makes system unavailable in such a case. This can be deemed as a conservative choice.
In the same time real stale price will be accepted as long as it happens to be within _PRICE_ORACLE_STALE_THRESHOLD window. I.e. getAssetPrice do not require the price to be the most recent / fresh, simply accepting any price given that it is not older than _PRICE_ORACLE_STALE_THRESHOLD.
Proof of Concept
getAssetPrice ignores round data, only requiring the timestamp to be new enough:
https://github.com/code-423n4/2022-04-mimo/blob/b18670f44d595483df2c0f76d1c57a7bfbfbc083/core/contracts/inception/priceFeed/ChainlinkInceptionPriceFeed.sol#L73-L80
I.e., recent timestamp doesn't guarantee fresh price, while fresh price can have non-recent timestamp (simply because of slow trading), so this check alone doesn't provide much protection.
Recommended Mitigation Steps
Consider imposing checks for positive price and for the round id, timestamp fields as it's suggested in the docs:
https://docs.chain.link/docs/feed-registry/#latestrounddata