Platform: Code4rena
Start Date: 19/04/2022
Pot Size: $30,000 USDC
Total HM: 10
Participants: 43
Period: 3 days
Judges: moose-code, JasoonS
Total Solo HM: 7
Id: 90
League: ETH
Rank: 43/43
Findings: 1
Award: $22.05
🌟 Selected for report: 0
🚀 Solo Findings: 0
22.0499 USDC - $22.05
Detailed description of the impact of this finding.
Stale price from data feed can lead to incorrect value of assetPerBaseInUQ
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Oracle data feed is insufficiently validated. There is no check for stale price and round completeness.
/// @inheritdoc IPriceOracle function refreshedAssetPerBaseInUQ(address _asset) public override returns (uint) { AssetInfo storage assetInfo = assetInfoOf[_asset]; (, int basePrice, , , ) = baseAggregator.latestRoundData(); (, int quotePrice, , , ) = assetInfo.aggregator.latestRoundData(); require(basePrice > 0 && quotePrice > 0, "ChainlinkPriceOracle: NEGATIVE"); uint assetPerBaseInUQ = ((uint(basePrice) * 10**assetInfo.decimals).mulDiv( FixedPoint112.Q112, (uint(quotePrice) * 10**baseDecimals) ) * 10**assetInfo.answerDecimals) / 10**baseAnswerDecimals; assetInfo.lastAssetPerBaseInUQ = assetPerBaseInUQ; return assetPerBaseInUQ; }
Validate data feed
/// @inheritdoc IPriceOracle function refreshedAssetPerBaseInUQ(address _asset) public override returns (uint) { AssetInfo storage assetInfo = assetInfoOf[_asset]; (uint80 roundID, int basePrice, , uint256 timestamp, uint80 answeredInRound) = baseAggregator.latestRoundData(); require(basePrice > 0, "ChainLink: base price <= 0"); require(answeredInRound >= roundID, "ChainLink: Stale price"); require(timestamp > 0, "ChainLink: Round not complete"); (uint80 roundID, int quotePrice, , uint256 timestamp, uint80 answeredInRound) = assetInfo.aggregator.latestRoundData(); require(quotePrice > 0, "ChainLink: asset price <= 0"); require(answeredInRound >= roundID, "ChainLink: Stale price"); require(timestamp > 0, "ChainLink: Round not complete"); uint assetPerBaseInUQ = ((uint(basePrice) * 10**assetInfo.decimals).mulDiv( FixedPoint112.Q112, (uint(quotePrice) * 10**baseDecimals) ) * 10**assetInfo.answerDecimals) / 10**baseAnswerDecimals; assetInfo.lastAssetPerBaseInUQ = assetPerBaseInUQ; return assetPerBaseInUQ; }
#0 - olivermehr
2022-05-02T20:31:07Z
Duplicate issue of #1