The returned price from Chainlik's latestRoundData
isn't checked for a stale price. This can be a problem as the protocol will work with outdated price
LiquidationPool::distributeAssets
uses Chainlink oracle to determine the price of an asset.
(,int256 priceEurUsd,,,) = Chainlink.AggregatorV3Interface(eurUsd).latestRoundData();
(,int256 assetPriceUsd,,,) = Chainlink.AggregatorV3Interface(asset.token.clAddr).latestRoundData();
However it uses the answer without checking for staleness.
Here is a quote from Chainlink documentation (https://docs.chain.link/data-feeds/#check-the-timestamp-of-the-latest-answer):
Your application should track the latestTimestamp
variable or use the updatedAt
value from the latestRoundData()
function to make sure that the latest answer is recent enough for your application to use it. If your application detects that the reported answer is not updated within the heartbeat or within time limits that you determine are acceptable for your application, pause operation or switch to an alternate operation mode while identifying the cause of the delay.
The protocol working with outdated price which can cause manipulations.
Manual Review
Read the updatedAt
parameter from latestRoundData
and verify that it is lowe than the heartbeat
uint256 secondsSince = block.timestamp - updatedAt;
if (secondsSince > 60 * 60 * 24 /* 24 hours which is the heartbeat for EUR / USD */) revert("Stale price");
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.