DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Invalid

LibChainlinkOracle TWAP will fail in case of aggregator update

Summary

LibChainlinkOracle.getTwap() iterates through all the round that took place in period [block.timestamp; block.timestamp - lookback], every iteration it decrements roundId to get previous roundId:

// Loop through previous rounds and compute cumulative sum until
// a round at least `lookback` seconds ago is reached.
while (timestamp > t.endTimestamp) {
t.cumulativePrice = t.cumulativePrice.add(
uint256(answer).mul(t.lastTimestamp.sub(timestamp))
);
@> roundId -= 1;
t.lastTimestamp = timestamp;
@> (answer, timestamp) = getRoundData(priceAggregator, roundId);
if (
checkForInvalidTimestampOrAnswer(
timestamp,
answer,
t.lastTimestamp,
maxTimeout
)
) {
return 0;
}
}

Problem is that roundId doesn't increase monotonically as described in Chainlink docs

Vulnerability Details

According to docs roundId consists of 2 values:

  1. phaseId which means aggregator version and increments on upgrade. This value is shifted left by 64 bits.

  2. originalId which monotonically increments in new round.

Problem is that if TWAP wants to read price in period where aggregator upgrade was performed, then it will try to access non-existent roundId because it always decrements roundId. And as a result price fetch will fail.

Impact

In case TWAP lookback tries to fetch price from period with Chainlink aggregator upgrade, price fetch will fail.

Tools Used

Manual Review

Recommendations

Use specific function to get previous roundId for pair https://docs.chain.link/data-feeds/feed-registry/feed-registry-functions#getpreviousroundid

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Known - Bean Part 1

Support

FAQs

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