Open code423n4 opened 1 year ago
0xean marked the issue as satisfactory
tbrent marked the issue as sponsor confirmed
Nice find! When StalePrice()
is thrown in OracleLib.sol
, it should revert with the latest price, and this latest price should be used in the asset plugin. S
tbrent marked the issue as sponsor acknowledged
Lines of code
https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/plugins/assets/Asset.sol#L144-L145
Vulnerability details
Impact
Asset.lotPrice()
has a fallback mechanism in case thattryPrice()
fails - it uses the last saved price and multiplies its value bylotMultiplier
(a variable that decreases as the time since the last saved price increase) and returns the results. However, thetryPrice()
might fail due to oracle timeout, in that case the last saved price might be older than the oracle's price.This can cause the backing manager to misestimate the value of the asset, trade it at a lower price, or do an unnecessary haircut.
Proof of Concept
In the PoC below:
lotPrice()
is calculated based on the oracle price from day 0 even though a price from day 5 is available from the oraclelotPrice()
goes down to zero since it considers the price from day 0 (which is more than a week ago) to be the last saved price, even though a price from a day ago is available from the oracleOutput:
Recommended Mitigation Steps
Allow specifying a timeout to
tryPrice()
, in case thattryPrice()
fails due to oracle timeout then call it again withpriceTimeout
as the timeout. If the call succeeds the second time then use it as the most recent price for fallback calculations.