Platform: Code4rena
Start Date: 25/10/2022
Pot Size: $50,000 USDC
Total HM: 18
Participants: 127
Period: 5 days
Judge: 0xean
Total Solo HM: 9
Id: 175
League: ETH
Rank: 117/127
Findings: 1
Award: $0.38
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: rbserver
Also found by: 0x1f8b, 0xNazgul, 0xc0ffEE, 8olidity, Aymen0909, Chom, Franfran, Jeiwan, Jujic, Lambda, M4TZ1P, Olivierdem, Rolezn, Ruhum, TomJ, Wawrdog, __141345__, bin2chen, c7e7eff, carlitox477, catchup, cccz, codexploder, cuteboiz, d3e4, dipp, djxploit, eierina, elprofesor, hansfriese, horsefacts, idkwhatimdoing, imare, immeas, joestakey, ladboy233, leosathya, martin, minhtrng, pashov, peanuts, pedroais, rokinot, rvierdiiev, saneryee, sorrynotsorry, tonisives
0.385 USDC - $0.38
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L116
The getPrice
function in Oracle.sol
makes use of the latestAnswer
function from the Chainlink feed. However, there is no check if the price returned is stale or not. This could lead to outdated/incorrect prices used in the protocol.
getPrice
function in Oracle.sol
:
function getPrice(address token, uint collateralFactorBps) external returns (uint) { if(fixedPrices[token] > 0) return fixedPrices[token]; if(feeds[token].feed != IChainlinkFeed(address(0))) { // get price from feed uint price = feeds[token].feed.latestAnswer(); require(price > 0, "Invalid feed price"); // normalize price uint8 feedDecimals = feeds[token].feed.decimals(); uint8 tokenDecimals = feeds[token].tokenDecimals; uint8 decimals = 36 - feedDecimals - tokenDecimals; uint normalizedPrice = price * (10 ** decimals); // potentially store price as today's low uint day = block.timestamp / 1 days; uint todaysLow = dailyLows[token][day]; if(todaysLow == 0 || normalizedPrice < todaysLow) { dailyLows[token][day] = normalizedPrice; todaysLow = normalizedPrice; emit RecordDailyLow(token, normalizedPrice); } // get yesterday's low uint yesterdaysLow = dailyLows[token][day - 1]; // calculate new borrowing power based on collateral factor uint newBorrowingPower = normalizedPrice * collateralFactorBps / 10000; uint twoDayLow = todaysLow > yesterdaysLow && yesterdaysLow > 0 ? yesterdaysLow : todaysLow; if(twoDayLow > 0 && newBorrowingPower > twoDayLow) { uint dampenedPrice = twoDayLow * 10000 / collateralFactorBps; return dampenedPrice < normalizedPrice ? dampenedPrice: normalizedPrice; } return normalizedPrice; } revert("Price not found"); }
The price of the token is given by the latestAnswer
function of the Chainlink feed above and is only checked to be > 0.
It is recommended to use the latestTimestamp
of the feed to make sure retrieved prices aren't stale.
#0 - c4-judge
2022-11-05T22:42:12Z
0xean marked the issue as duplicate
#1 - Simon-Busch
2022-12-05T15:29:23Z
Issue marked as satisfactory as requested by 0xean
#2 - c4-judge
2022-12-07T08:14:13Z
Simon-Busch marked the issue as duplicate of #584