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: 8/127
Findings: 3
Award: $3,422.45
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: Ruhum
3397.8465 USDC - $3,397.85
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L124
The two-day feature of the oracle can be gamed where you only have to manipulate the oracle for ~2 blocks.
The oracle computes the day using:
uint day = block.timestamp / 1 days;
Since we're working with uint
values here, the following is true:
$1728799 / 86400 = 1$
$172800 / 86400 = 2$
Meaning, if you manipulate the oracle at the last block of day $X$, e.g. 23:59:50, and at the first block of day $X + 1$, e.g. 00:00:02, you bypass the two-day feature of the oracle. You only have to manipulate the oracle for two blocks.
This is quite hard to pull off. I'm also not sure whether there were any instances of Chainlink oracle manipulation before. But, since you designed this feature to prevent small timeframe oracle manipulation I think it's valid to point this out.
none
If you increase it to a three-day interval you can fix this issue. Then, the oracle has to be manipulated for at least 24 hours.
#0 - c4-sponsor
2022-11-15T14:51:00Z
08xmt marked the issue as sponsor acknowledged
#1 - 08xmt
2022-11-15T14:51:46Z
This is an issue if a 24 hour period elapse without any calls to the oracle and the underlying oracle is manipulable. The two day low is meant to be an added layer of security, but not bullet proof.
#2 - c4-judge
2022-11-28T19:35:26Z
0xean marked the issue as satisfactory
#3 - c4-judge
2022-12-01T15:58:36Z
0xean marked the issue as selected for report
🌟 Selected for report: adriro
Also found by: 8olidity, BClabs, CertoraInc, Chom, Franfran, Lambda, RaoulSchaffranek, Ruhum, codexploder, cryptphi, eierina, joestakey, kaden, neumo, pashov, rvierdiiev, sorrynotsorry
24.2165 USDC - $24.22
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L121
The oracle expects the token to have at most 18 decimals. But, there are tokens with more, e.g. 24. A prominent example is NEAR. It's in place 17 in Etherscan's ERC20 token ranking (by market cap)
The normalization logic will produce wrong results.
The price is normalized using:
uint8 feedDecimals = feeds[token].feed.decimals(); uint8 tokenDecimals = feeds[token].tokenDecimals; uint8 decimals = 36 - feedDecimals - tokenDecimals; uint normalizedPrice = price * (10 ** decimals);
With NEAR, you have the following result:
// using real chainlink feed data: https://etherscan.io/address/0xC12A6d1D827e23318266Ef16Ba6F397F2F91dA9b#readContract chainlink round ID = 18446744073709556379 answer = 306615587 ($3.07) normalizedPrice = 306615587 * (10 ** (36 - 24 - 8)) = 30661.5587
The price is scaled to 12 decimals instead of 18. The collateral's value will be lower than it should be and thus unusable.
none
You can scale the value to 18 decimals using
price * (10 ** (18 - feed.decimals()))
The token's own decimals can be ignored. Just scale the oracle's value to 18 decimals and you should be fine.
#0 - c4-judge
2022-11-04T23:41:58Z
0xean marked the issue as duplicate
#1 - c4-judge
2022-11-28T16:04:51Z
0xean marked the issue as not a duplicate
#2 - c4-judge
2022-11-28T16:05:00Z
0xean marked the issue as duplicate of #540
#3 - Simon-Busch
2022-12-05T15:33:38Z
Issue marked as satisfactory as requested by 0xean
#4 - c4-judge
2022-12-07T08:18:20Z
Simon-Busch marked the issue as duplicate of #533
🌟 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#L82
The Chainlink oracle latestAnswer()
function is deprecated. Instead, you're supposed to use latestRoundData()
.
Using deprecated functions can result in the PriceOracleImplementation not returning the correct value anymore. It will affect the availability of that module.
Usage of latestAnswer()
: https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L82
You can find the deprecation notice in the used contract itself: https://etherscan.io/address/0x986b5E1e1755e3C2440e960477f25201B0a8bbD4#code#L142
none
Use latestRoundData()
and verify its return values properly, e.g. that the price was updated recently.
#0 - neumoxx
2022-10-31T08:46:22Z
Duplicate of #601
#1 - c4-judge
2022-11-05T17:50:24Z
0xean marked the issue as duplicate
#2 - Simon-Busch
2022-12-05T15:26:40Z
Issue marked as satisfactory as requested by 0xean
#3 - c4-judge
2022-12-07T08:14:13Z
Simon-Busch marked the issue as duplicate of #584