There is just a single staleness threshold per pool, thus it assumes that all oracles will have the same heartbeat
The way to protect against stale oracle prices is by checking the last update with the staleness threshold. However, this threshold is unique to the pool and it assumes that all oracles will have the same heartbeat. This is really problematic taking into account the wide range of heartbeats that a price feed can take.
The most common heartbeats are 3600s (1 hour) and 86400s (24 hours). Taking this into account, the staleness threshold MUST always be the highest heartbeat between all oracles because if not, the highest heartbeat oracle would be considered stale most of the time. However, taking the maximum staleness threshold for all oracles is also problematic, because staleness on most frequent oracle will be undetected.
Imagine that there is a pool with BTC and USDC in Ethereum. The Chainlink oracles used would be the BTC/USD price feed and the USDC/USD price feed. For the first oracle it takes 1 hour to update and for the second one 24 hours. Hence, the oracleStalenessThreshold must be of at least 24 hours. Imagine the following situation:
The update weight runner can perform an update in the pool every hour
Timestamp 1 (0 hours):
UpdateWeightRunner performs an update with correct data from oracles
Timestamp 2 (1 hour):
The BTC/USD oracle becomes stale
Timestamp 3 (2 hours):
UpdateWeightRunner performs an update. Even though the BTC price is stale, it will be considered valid because 2 hours < 24 hours which is the staleness threshold
This will continue to happen until reaching 24 hours of price staleness
Medium, taking into account that at least 2 tokens must be listed in the pool and also each token can have several backup oracles, this staleness issue will becomes even more possible. Using stale prices could be considered as High because volatile assets can lose 50% or more of value in a matter of hours. It is true that is rare that oracles become stale but it is possible. It is also worth noting that 1 hour and 24 hours are not the most far heartbeats, there are oracles that can take 172800 seconds (2 days). An example would be the AMPL/USD price feed. This is a huge amount of time compared to price feeds with just 1 hour of refresh.
Manual review
Since oracles are stored in the UpdateWeightRunner it could already have the specific heartbeat for each one to check its staleness. Hence, instead of having a single staleness threshold per pool, every oracle should store itself the heartbeat and check for the staleness during each fetch of prices.
This is by design, staleness is a strategy aspect: it requires all data to have been updated within n minutes. No more precision needed.
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.