LibChainlinkOracle
is not fully compatible with Chainlink's data model due to the lack of support for phaseId and aggregatorRoundId
. Chainlink's roundID
is a composite number combining a phaseID and an aggregatorRoundID
.
The phaseID
changes whenever there is an upgrade to the underlying aggregator, and this change causes
a significant jump in the roundID
values due to the bit-shifting operation described in the documentation.
ref here: https://docs.chain.link/data-feeds/historical-data#solidity
The Beanstalk LibChainlinkOracle
misinterprets the progression of roundID
as sequential, overlooking Chainlink's unique bundling of phaseId
and aggregatorRoundId
. With the advancement of phaseID
, there's an exponential increase in roundID by 2^64,
leading to a temporal suspension until a new interval commences. This will instigate a denial-of-service scenario. The getEthUsdTwap and getEthUsdPrice
functions are particularly susceptible to this vulnerability, as they rely on accurate TWAP values for their computations, which effects for example any calls reliant on Oracle data.
https://etherscan.io/address/0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419#code
The code segment extracted from the ETH/USD Chainlink aggregator above highlights the composite structure of roundId
,
integrating both phaseId and aggregatorRoundId
. As highlighted, an increment in phaseId
leads to a substantial
leap in roundId by 2^64
, thereby bypassing a number of "rounds." Consequently, any attempt to query
currentRound - 1 post-upgrade encounters a non-existent round, triggering a revert. This condition could persist up to 24 hours based on configuration, impacting the timely execution of getEthUsdTwap and getEthUsdPrice.
These functions, once operational again, might utilize altered TWAP values for computations, diverging from
expected outcomes
If a phaseID
increment occurs, it results in a jump in ``````roundID values, creating a gap in the sequence.
When there are attempts to access round data for roundIDs
within this gap, it will encounter inaccurate
rounds, potentially causing the function to fail or return incorrect data, considering when the phaseID
is incremented the roundID increases by 2 ** 64.
This discrepancy can lead to a denial-of-servicein any calls to the oracle.
Manual Review
Check return values of roundId. If the roundID
is a nonzero value and is reverting then the oracle needs to try again with a lower phaseId.
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.