Platform: Code4rena
Start Date: 01/07/2022
Pot Size: $75,000 USDC
Total HM: 17
Participants: 105
Period: 7 days
Judge: Jack the Pug
Total Solo HM: 5
Id: 143
League: ETH
Rank: 73/105
Findings: 2
Award: $53.10
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xNineDec
Also found by: 0x1f8b, 0x29A, 0x52, 0xDjango, 0xdanial, 0xf15ers, Cheeezzyyyy, Chom, Franfran, GalloDaSballo, Green, IllIllI, Meera, Ruhum, bardamu, cccz, codexploder, defsec, hake, hansfriese, horsefacts, hubble, hyh, jonatascm, kebabsec, oyc_109, pashov, rbserver, simon135, tabish, tintin, zzzitron
14.8726 USDC - $14.87
Insufficient validation of data feed to check if the data returned is stale which can potentially cause cascading erroneous calculations and state updates in payment, distribution and allowances.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Inside JBChainlinkV3PriceFeed.sol
, latestRoundData
is being used in currentPrice
to fetch the latest price of ETH/USD. However, there is insufficient validation of data feed to check if the data returned is stale.
This can result in an incorrect price data returned when priceFor
inside JBPrices.sol
is called, which will cause wrong calculations inside recordPaymentFrom
, recordDistributionFor
, recordUsedAllowanceOf
, _overflowingDuring
and _currentTotalOverflowOf
inside JBSingleTokenPaymentTerminalStore.sol
.
Code: #JBChainlinkV3PriceFeed.sol#L42-51
List of Functions that will be affected from potential stale data: #JBSingleTokenPaymentTerminalStore.sol#L387 #JBSingleTokenPaymentTerminalStore.sol#L585 #JBSingleTokenPaymentTerminalStore.sol#L661 #JBSingleTokenPaymentTerminalStore.sol#L830 #JBSingleTokenPaymentTerminalStore.sol#L868
Validate data feed appropriately.
function currentPrice(uint256 _decimals) external view override returns (uint256) { // Get the latest round information. Only need the price is needed. (uint80 roundID, int256 _price, ,uint256 timestamp, uint80 answeredInRound ) = feed.latestRoundData(); require(answer > 0, "Chainlink: Invalid oracle answer"); require(answeredInRound > roundID, "Chainlink: Stale price"); require(timestamp > 0, "Chainlink: Round not complete"); // Get a reference to the number of decimals the feed uses. uint256 _feedDecimals = feed.decimals(); // Return the price, adjusted to the target decimals. return uint256(_price).adjustDecimals(_feedDecimals, _decimals); }
#0 - drgorillamd
2022-07-12T15:44:23Z
Duplicate of #138
🌟 Selected for report: 0xA5DF
Also found by: 0v3rf10w, 0x09GTO, 0x1f8b, 0x29A, 0xDjango, 0xKitsune, 0xNazgul, 0xdanial, 0xf15ers, Aymen0909, Bnke0x0, Ch_301, Cheeezzyyyy, Chom, ElKu, Funen, Hawkeye, IllIllI, JC, JohnSmith, Kaiziron, Lambda, Limbooo, Meera, Metatron, MiloTruck, Noah3o6, Picodes, Randyyy, RedOneN, ReyAdmirado, Rohan16, Saintcode_, Sm4rty, TomJ, Tomio, Tutturu, UnusualTurtle, Waze, _Adam, __141345__, ajtra, apostle0x01, asutorufos, brgltd, c3phas, cRat1st0s, codexploder, defsec, delfin454000, djxploit, durianSausage, exd0tpy, fatherOfBlocks, hake, horsefacts, ignacio, jayfromthe13th, joestakey, jonatascm, kaden, kebabsec, m_Rassska, mektigboy, mrpathfindr, oyc_109, rajatbeladiya, rbserver, rfa, robee, sach1r0, sashik_eth, simon135
38.2306 USDC - $38.23
Inside JBController.sol: #JBController.sol#L913 #JBController.sol#L1014
Inside JBDirectory.sol: #JBDirectory.sol#L139 #JBDirectory.sol#L167 #JBDirectory.sol#L275-L276
Inside JBETHERERC20SplitsPayer.sol: #JBETHERC20SplitsPayer.sol#L466
Inside JBFundingCycleStore.sol: #JBFundingCycleStore.sol#L724
Inside JBOperatorStore.sol: #JBOperatorStore.sol#L85 #JBOperatorStore.sol#L135 #JBOperatorStore.sol#L165
Inside JBSingleTokenPaymentTerminalStore.sol: #JBSingleTokenPaymentTerminalStore.sol#L862
Inside JBSplitsStore.sol #JBSplitsStore.sol#L165 #JBSplitsStore.sol#L204 #JBSplitsStore.sol#L211 #JBSplitsStore.sol#L229 #JBSplitsStore.sol#L304
Replace
_i++
with
unchecked { _i++; }