Open hats-bug-reporter[bot] opened 4 months ago
We intentionally have the OrigamiStableChainlinkOracle
abstraction over fetching the chainlink price in order to apply validation but also to allow upgrades of our abstraction if required.
While the spotPriceOracle
is indeed immutable within OrigamiStableChainlinkOracle
, it is an instance of IOrigamiOracle
which can be upgraded by the protocol if/when required in future for where it's used
For example in lovDSR's manager: https://github.com/TempleDAO/origami-public/blob/185a93e25071b6a110ca190e94a6a826e982b2d6/apps/protocol/contracts/investments/lovToken/managers/OrigamiLovTokenErc4626Manager.sol#L136
Github username: @0xRizwan Twitter username: 0xRizwann Submission hash (on-chain): 0x27095c8f3023725b44de9df598d7603ab0c7ff9d0da5d3dd8cc767f458f40979 Severity: medium
Description: Description
The
price()
function from chainlink library is extensively used in contracts.price()
makes use of Chainlink'slatestRoundData()
to get the latest price. However, there is no fallback logic to be executed when the access to the Chainlink data feed is denied by Chainlink's multisigs. Chainlink's multisigs can immediately block access to price feeds at will. Therefore, to prevent denial of service scenarios, it is recommended to query Chainlink price feeds using a defensive approach with Solidity’s try/catch structure. In this way, if the call to the price feed fails, the caller contract is still in control and can handle any errors safely and explicitly.Referring chainlink documentation on how chainlink services are updated. Please note chainlink multisig holds the power of Chainlink’s multisigs can immediately block access to price feeds at will.
This chainlink price feeds are passed in constructor with no setter functions and these feeds used in contracts will acts as immutable.
Impact
Call to
latestRoundData
could potentially revert and make it impossible to query any prices. This could lead to permanent denial of service.Recommendation to fix
Surround the call to
latestRoundData()
withtry/catch
instead of calling it directly. In a scenario where the call reverts, the catch block can be used to call a fallback oracle or handle the error in any other suitable way.For example understanding:
References
1)Openzeppelin reference: Refer to https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/ for more information regarding potential risks to account for when relying on external price feed providers.
2)Reference news article: https://cryptonews.net/news/defi/20502745/