The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

`LiquidationPool::distributeAssets()` does not perform price staleness checks for oracle calls

Summary

LiquidationPool::distributeAssets() makes use of Chainlink's price feeds but does not perform the recommended staleness checks.

Vulnerability Details

The Chainlink price feeds can return stale data for a variety of reasons. Currently, calls to the oracles inside LiquidationPool::distributeAssets() do not perform the recommended checks to protect against this.

L207:

(,int256 priceEurUsd,,,) = Chainlink.AggregatorV3Interface(eurUsd).latestRoundData();

L218:

(,int256 assetPriceUsd,,,) = Chainlink.AggregatorV3Interface(asset.token.clAddr).latestRoundData();

This is also present in the PriceCalculator contract and will lead to similar issues wherever its functions are used. While that one is out of scope for this contest, I believe it is still worth mentioning.

For a detailed explanation of why this might occur, refer to the following resource: https://ethereum.stackexchange.com/questions/133242/how-future-resilient-is-a-chainlink-price-feed/133843#133843

Impact

  • Wrongly updated EUROs positions of all stakers

  • Wrong amount of EUROs being burned from the contract

  • Wrong reward distribution

Tools Used

Manual Analysis

Recommendations

Read the updatedAt parameter returned from latestRoundData() and verify that it isn't older than a set threshold amount:

(, int256 price, , uint256 updatedAt, ) = Chainlink.AggregatorV3Interface(eurUsd).latestRoundData();
if (updatedAt < block.timestamp - 60 * 60 /* 1 hour */) {
revert("stale price feed");
}

The staleness threshold should correspond to the heartbeat duration of the feed. These can be checked in the official Chainlink docs (make sure to check "Show more details"):
https://docs.chain.link/data-feeds/price-feeds/addresses/?network=arbitrum&page=1.

It's also important to note that different feeds have different heartbeats, so it's advisable to store these values somewhere and incorporate them into the staleness check logic on a feed to feed basis.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Chainlink-price

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Chainlink-price

Support

FAQs

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