-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stale price can be used in getValueFromChainlinkFeed
function
#1501
Comments
DadeKuma marked the issue as duplicate of #917 |
DadeKuma marked the issue as not a duplicate |
DadeKuma marked the issue as primary issue |
DadeKuma marked the issue as sufficient quality report |
needs to be fixed. the recommended mitigation step is accepted. |
gzeon-c4 marked the issue as satisfactory |
gzeon-c4 marked the issue as selected for report |
fix in commit c8ccd96c4aea5161f052cd17dd8263425d2560a0 |
Hi @pksq90, I believe this is not a duplicate of 917, this report and its duplicates talk about how the lower bound of the stale check is not safe for some feeds a they are going to always ingest stale prices since their heartbeats are shorter than the lower bound. Whereas 917 and its duplicates hints why using a fixed |
Thank you, I think you are right. They are indeed two different issues. |
Thanks @Bauchibred |
Lines of code
https://github.com/code-423n4/2024-04-noya/blob/cc3854f634a72bd4a8b597021887088ca2d6d29f/contracts/helpers/valueOracle/oracles/ChainlinkOracleConnector.sol#L56-L62
https://github.com/code-423n4/2024-04-noya/blob/cc3854f634a72bd4a8b597021887088ca2d6d29f/contracts/helpers/valueOracle/oracles/ChainlinkOracleConnector.sol#L115-L135
Vulnerability details
Impact
According to the following
updateChainlinkPriceAgeThreshold
function, the minimum possiblechainlinkPriceAgeThreshold
would be 61 seconds. However, there are Chainlink oracles that have heartbeat that is less than 61 seconds; these oracles are essential for providing prices for the ERC20 tokens that should be supported by this protocol in which these tokens have the in scope token behaviors and exist on the intended chains described in https://code4rena.com/audits/2024-04-noya. For example, the USDC / USD Chainlink oracle on Polygon has a heartbeat of 27 seconds according to the popup of the Trigger parameters section's information icon in https://data.chain.link/feeds/polygon/mainnet/usdc-usd.https://github.com/code-423n4/2024-04-noya/blob/cc3854f634a72bd4a8b597021887088ca2d6d29f/contracts/helpers/valueOracle/oracles/ChainlinkOracleConnector.sol#L56-L62
For Chainlink oracles that have heartbeat that is less than 61 seconds,
block.timestamp - updatedAt > chainlinkPriceAgeThreshold
in the followinggetValueFromChainlinkFeed
function can be false when theupdatedAt
actually corresponds to a stale price. For instance, when theupdatedAt
returned by the USDC / USD Chainlink oracle on Polygon isblock.timestamp - 27 * 2
, a newer price should be reported atblock.timestamp - 27
but that did not happen so the corresponding price reported atblock.timestamp - 27 * 2
is already stale; yet, becauseblock.timestamp - updatedAt > chainlinkPriceAgeThreshold
is false for suchupdatedAt
, thegetValueFromChainlinkFeed
function does not revert with theNoyaChainlinkOracle_DATA_OUT_OF_DATE
error. As a result, the stale price is used in thegetValueFromChainlinkFeed
function.Moreover, the
chainlinkPriceAgeThreshold
being set to only one value can fail to accommodate all Chainlink oracles that are intended to be supported by theChainlinkOracleConnector
contract when these oracles have different heartbeats. In this case, thechainlinkPriceAgeThreshold
that ensures that one oracle's price is not stale can fail to ensure that the other oracle's price is not stale if the latter oracle's heartbeat is smaller than the former's.https://github.com/code-423n4/2024-04-noya/blob/cc3854f634a72bd4a8b597021887088ca2d6d29f/contracts/helpers/valueOracle/oracles/ChainlinkOracleConnector.sol#L115-L135
Proof of Concept
Please add the following test in
testFoundry\testOracle.sol
. This test will pass to demonstrate the described scenario.Tools Used
Manual Review
Recommended Mitigation Steps
chainlinkPriceAgeThreshold
can be updated to be a mapping by Chainlink oracle in which each oracle has onechainlinkPriceAgeThreshold
value. Then, theupdateChainlinkPriceAgeThreshold
function can be updated to set thechainlinkPriceAgeThreshold
value for the corresponding oracle in which such value can be set to be less than 61 seconds. At last, thegetValueFromChainlinkFeed
function can be updated to use the corresponding oracle'schainlinkPriceAgeThreshold
value for checking whether the reported price is stale or not.Assessed type
Oracle
The text was updated successfully, but these errors were encountered: