QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Quant pools will accept oracle stale prices due to difference of heartbeat

Summary

There is just a single staleness threshold per pool, thus it assumes that all oracles will have the same heartbeat

Vulnerability Details

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.

Proof of Concept

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

Impact

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.

Tools Used

Manual review

Recommendations

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.

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

invalid_oracle_same_threshold_for_assets_in_pool

This is by design, staleness is a strategy aspect: it requires all data to have been updated within n minutes. No more precision needed.

Support

FAQs

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