You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Dec 17, 2023. It is now read-only.
sherlock-admin opened this issue
Jun 11, 2023
· 0 comments
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelMediumA valid Medium severity issueRewardA payout will be made for this issue
Lack of checks to avoid stale prices from Chainlink oracle
Summary
getPriceFromChainlink function is not checking the returned values of Chainlink Registry to ensure the prices are fresh and not stale.
Vulnerability Detail
When getting prices from Chainlink oracles, it's necessary to ensure the prices are fresh and not stale, and getPriceFromChainlink function from PriceOracle contract is not checking that.
/** * @notice Get price from Chainlink. * @param base The base asset * @param quote The quote asset * @return The price */function getPriceFromChainlink(addressbase, addressquote) internalviewreturns (uint256) {
(, int256price,,,) = registry.latestRoundData(base, quote);
require(price >0, "invalid price"); // @audit No checks for stale prices// Extend the decimals to 1e18.returnuint256(price) *10** (18-uint256(registry.decimals(base, quote)));
}
Every Chainlink price feed has a different heartbeat, meaning it has to be updated every x amount of seconds depending on the feed, here some examples:
When getting prices from feeds, we have to ensure that the answer given by the oracle is fresh, meaning the answer given hasn't been updated more than a certain time ago. For ETH/USD oracle, the heartbeat is of 3600 seconds, meaning the oracle must be updated at least every 1 hour.
If the Chainlink oracle is returning stale prices, the protocol will use the wrong values to make decisions so it could lead to false liquidations or over-borrowing.
sherlock-admin2
added
Medium
A valid Medium severity issue
Duplicate
A valid issue that is a duplicate of an issue with `Has Duplicates` label
Reward
A payout will be made for this issue
and removed
Non-Reward
This issue will not receive a payout
labels
Jul 19, 2023
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelMediumA valid Medium severity issueRewardA payout will be made for this issue
santipu_
medium
Lack of checks to avoid stale prices from Chainlink oracle
Summary
getPriceFromChainlink
function is not checking the returned values of Chainlink Registry to ensure the prices are fresh and not stale.Vulnerability Detail
When getting prices from Chainlink oracles, it's necessary to ensure the prices are fresh and not stale, and
getPriceFromChainlink
function fromPriceOracle
contract is not checking that.Every Chainlink price feed has a different heartbeat, meaning it has to be updated every
x
amount of seconds depending on the feed, here some examples:When getting prices from feeds, we have to ensure that the answer given by the oracle is fresh, meaning the answer given hasn't been updated more than a certain time ago. For ETH/USD oracle, the heartbeat is of 3600 seconds, meaning the oracle must be updated at least every 1 hour.
Related reports:
Impact
If the Chainlink oracle is returning stale prices, the protocol will use the wrong values to make decisions so it could lead to false liquidations or over-borrowing.
Code Snippet
https://github.com/sherlock-audit/2023-05-ironbank/blob/main/ib-v2/src/protocol/oracle/PriceOracle.sol#L60-L72
Tool used
Manual Review
Recommendation
It's recommended to check
updatedAt
value returned from Chainlink against somemaxDelayTime
value set in the contract depending of the feed used.Example:
function getPriceFromChainlink(address base, address quote) internal view returns (uint256) { (, int256 price,, uint256 updatedAt,) = registry.latestRoundData(base, quote); require(price > 0, "invalid price"); + if(updatedAt < block.timestamp - maxDelayTime) revert(); // @audit Ensuring fresh prices // Extend the decimals to 1e18. return uint256(price) * 10 ** (18 - uint256(registry.decimals(base, quote))); }
Duplicate of #9
The text was updated successfully, but these errors were encountered: