Incorrect Validation Of latestRoundData Function Can Lead to Stale Price Issue.
Summary
When OracleModule#_getOnchainPrice() fetches the price from Chainlink, it misses a very important check recommended by the Chainlink protocol to ensure the data is fresh and accurate.
Vulnerability Detail
The _getOnchainPrice() function depends on Chainlink's latestRoundData() but does not verify round completeness. The protocol developers (according to Discord chat) plan to set onchainOracle.maxAge to 24 hours and 10 seconds. This means that the price is considered not stale only when block.timestamp <= updatedAt (Last Time the price was updated) + onchainOracle.maxAge (24H + 10 seconds).
Chainlink could return stale data, which the protocol might accept when the keeper execute pending orders or liquidate, even though it primarily relies on Pyth's offchain price. However, if offchainInvalid == true, the on-chain price returned might not be accurate.
This issue for example could result to the liquidation of users who should not be liquidated when the canLiquidate function is called.
Add the following checks and reply on the returned value from latestRoundData to verify for price stale instead of onchainOracle.maxAge set by the protocol admin.
Bjorn_Bug
medium
Incorrect Validation Of latestRoundData Function Can Lead to Stale Price Issue.
Summary
When
OracleModule#_getOnchainPrice()
fetches the price from Chainlink, it misses a very important check recommended by the Chainlink protocol to ensure the data is fresh and accurate.Vulnerability Detail
The
_getOnchainPrice()
function depends on Chainlink'slatestRoundData()
but does not verify round completeness. The protocol developers (according to Discord chat) plan to setonchainOracle.maxAge
to 24 hours and 10 seconds. This means that the price is considered not stale only when block.timestamp <= updatedAt (Last Time the price was updated) + onchainOracle.maxAge (24H + 10 seconds).Impact
Chainlink could return stale data, which the protocol might accept when the keeper execute pending orders or liquidate, even though it primarily relies on Pyth's offchain price. However, if offchainInvalid == true, the on-chain price returned might not be accurate.
This issue for example could result to the liquidation of users who should not be liquidated when the
canLiquidate
function is called.Code Snippet
https://github.com/sherlock-audit/2023-12-flatmoney/blob/main/flatcoin-v1/src/OracleModule.sol#L145-L150
Tool used
Manual Review
Recommendation
Add the following checks and reply on the returned value from latestRoundData to verify for price stale instead of onchainOracle.maxAge set by the protocol admin.
Duplicate of #3