The Standard

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

Chainlink price feed not checked for stale prices, leading to invalid price

Summary

Chainlink oracle price feeds are used to determine the prices of EUR/USD, and collateralToken/USD (this includes tokens in TokenManagerMock.acceptedTokens such as ETH, WBTC, ARB, LINK, & PAXG). However, these price feed calls are not being adequately validated.

Vulnerability Details

The protocol currently lacks a check for stale prices. This means outdated prices might be used if the Oracle fails to update them in time.

Impact

Various reasons can cause Oracle price feeds to become stale (details here). Using stale prices leads to inaccurate costInEuros calculations. Consequently, users may receive more or less than they are entitled to during distributeAssets, affecting other users unfairly.

Tools Used

Manual Review

Recommendations

To prevent stale data issues, it is advised to add checks that ensure the prices returned by Chainlink are current. The proposed changes are:

-(, int256 priceEurUsd, , , ) = Chainlink
+(uint80 roundId, int256 priceEurUsd, , uint256 updatedAt, uint80 answeredInRound) = Chainlink
.AggregatorV3Interface(eurUsd)
.latestRoundData();
+require(block.timestamp - updatedAt <= eurUsdHeartbeatInterval);
+require(priceEurUsd > 0, "Chainlink price <= 0");
+require(updatedAt != 0, "Incomplete round");
+require(answeredInRound >= roundId, "Stale price");
...
-(, int256 assetPriceUsd, , , ) = Chainlink
+(uint80 roundId, int256 assetPriceUsd, , uint256 updatedAt, uint80 answeredInRound) = Chainlink
.AggregatorV3Interface(asset.token.clAddr)
.latestRoundData();
+require(block.timestamp - updatedAt <= collateralHeartbeatInterval);
+require(assetPriceUsd > 0, "Chainlink price <= 0");
+require(updatedAt != 0, "Incomplete round");
+require(answeredInRound >= roundId, "Stale price");

It is critical to choose appropriate heartbeat intervals, which may vary across different chains and feed pairs.

Regarding the ETH / USD oracles on various EVM chains, the update frequencies are as follows:

  • Ethereum: approximately every 1 hour.

  • Polygon: approximately every 27 seconds.

  • BNB (BSC): approximately every 60 seconds.

  • Optimism: approximately every 20 minutes.

  • Arbitrum: approximately every 24 hours.

  • Avalanche: approximately every 24 hours.

The appropriate heartbeats can be found on Chainlink’s list of Ethereum mainnet price feeds by checking the “Show More Details” box, which will show the “Heartbeat” column for each feed.

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.