Platform: Code4rena
Start Date: 08/06/2022
Pot Size: $115,000 USDC
Total HM: 26
Participants: 72
Period: 11 days
Judge: leastwood
Total Solo HM: 14
Id: 132
League: ETH
Rank: 52/72
Findings: 1
Award: $151.39
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedWardens
Also found by: 0x1f8b, 0x29A, 0x52, 0xNazgul, 0xNineDec, 0xf15ers, 0xkatana, 0xmint, Chom, ElKu, Funen, IllIllI, JMukesh, Jujic, Kaiziron, Lambda, MiloTruck, Ruhum, SmartSek, SooYa, TerrierLover, TomJ, WatchPug, Waze, _Adam, asutorufos, auditor0517, bardamu, c3phas, catchup, cccz, ch13fd357r0y3r, cloudjunky, cmichel, cryptphi, csanuragjain, defsec, fatherOfBlocks, hansfriese, hyh, jayjonah8, joestakey, k, kenta, obtarian, oyc_109, robee, sach1r0, shenwilly, simon135, slywaters, sorrynotsorry, tintin, unforgiven, xiaoming90, zzzitron
151.3887 USDC - $151.39
At ConnextPriceOracle.sol, getPriceFromChainlink()
function invokes aggregator.latestRoundData()
. However, there are no checks if the return value indicates stale or subzero data. This could lead to wrong prices.
function getPriceFromChainlink(address _tokenAddress) public view returns (uint256) { AggregatorV3Interface aggregator = aggregators[_tokenAddress]; if (address(aggregator) != address(0)) { (, int256 answer, , , ) = aggregator.latestRoundData(); // It's fine for price to be 0. We have two price feeds. if (answer == 0) { return 0; } // Extend the decimals to 1e18. uint256 retVal = uint256(answer); uint256 price = retVal.mul(10**(18 - uint256(aggregator.decimals()))); return price; }
According to the Chainlink documentation: “A timestamp with zero value means the round is not complete and should not be used.” “if answeredInRound < roundId could indicate stale data.”
See example of mitigation here: https://github.com/cryptexfinance/contracts/blob/master/contracts/oracles/ChainlinkOracle.sol#L58-L65
Manual review
Adding missing the checks to validate the data is not stale
(roundId, rawPrice,, updatedAt, answeredInRound) = aggregator.latestRoundData(); require(rawPrice > 0, "Chainlink price <= 0"); require(updateTime != 0, "Incomplete round"); require(answeredInRound >= roundId, "Stale price");
#0 - ecmendenhall
2022-06-20T05:27:08Z
Duplicate of #190
#1 - jakekidd
2022-06-24T20:54:47Z
closed as dup of #190