Platform: Code4rena
Start Date: 30/04/2024
Pot Size: $112,500 USDC
Total HM: 22
Participants: 122
Period: 8 days
Judge: alcueca
Total Solo HM: 1
Id: 372
League: ETH
Rank: 87/122
Findings: 3
Award: $0.41
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: guhu95
Also found by: 0rpse, 0x007, 0x73696d616f, 0xCiphky, 0xabhay, Audinarey, Bauchibred, Fassi_Security, GalloDaSballo, GoatedAudits, KupiaSec, LessDupes, MSaptarshi, OMEN, Ocean_Sky, RamenPeople, SBSecurity, Tendency, WildSniper, aslanbek, bill, blutorque, crypticdefense, cu5t0mpeo, d3e4, gjaldon, grearlake, gumgumzum, honey-k12, ilchovski, jokr, josephdara, kennedy1030, p0wd3r, peanuts, stonejiajia, t0x1c, tapir, underdog, zzykxx
0.4071 USDC - $0.41
When requesting a withdrawal, the amount of collateral that will be withdrawn is set at the moment of request, and never changes afterwards. Therefore, regardless of slashings during the coolDownPeriod, the requester will be able to claim exactly the requested amount.
ezETH exchange rate should be computed at the moment of claiming the withdrawal, not at the moment of request.
MEV
#0 - c4-judge
2024-05-16T10:57:49Z
alcueca marked the issue as satisfactory
#1 - c4-judge
2024-05-16T11:01:20Z
alcueca marked the issue as duplicate of #326
#2 - c4-judge
2024-05-24T10:26:53Z
alcueca changed the severity to 3 (High Risk)
🌟 Selected for report: pauliax
Also found by: 0rpse, 0x73696d616f, 0xAadi, 0xCiphky, 0xPwned, 0xhacksmithh, 0xnev, 0xnightfall, 0xordersol, 14si2o_Flint, Aamir, Aymen0909, BiasedMerc, DanielArmstrong, Fassi_Security, FastChecker, GoatedAudits, Greed, KupiaSec, LessDupes, Maroutis, NentoR, OMEN, SBSecurity, Stefanov, TheFabled, adam-idarrha, ak1, aman, araj, aslanbek, b0g0, baz1ka, bigtone, blutorque, carlitox477, carrotsmuggler, crypticdefense, eeshenggoh, fyamf, gesha17, gjaldon, grearlake, guhu95, honey-k12, hunter_w3b, ilchovski, josephdara, kinda_very_good, lanrebayode77, m_Rassska, maxim371, mt030d, mussucal, oakcobalt, p0wd3r, peanuts, rbserver, shui, siguint, t0x1c, tapir, twcctop, ustazz, xg, zhaojohnson, zigtur, zzykxx
0.0026 USDC - $0.00
RestakeManager#calculateTVLs computes the total value of assets stored in the system:
For each OperatorDelegator, for each collateral token, it retrieves OD's balance and adds its ETH value to the total sum;
At i = 0
(first OD), totalWithdrawalQueueValue
is being computed by iterating through each token (j= 0, 1, ..., tokenLength - 1
):
if (!withdrawQueueTokenBalanceRecorded) { totalWithdrawalQueueValue += renzoOracle.lookupTokenValue( collateralTokens[i], collateralTokens[j].balanceOf(withdrawQueue) ); }
Since the first parameter of lookupTokenValue is the address of the token, and the second is its amount, each token will be accounted with the price of the first one.
Imagine there's 5 ODs, and 3 collateral tokens: stETH, wbETH, mETH.
Let's debug the first iteration of the external loop:
for (uint256 i = 0; i < odLength; ) { /* ... */ for (uint256 j = 0; j < tokenLength; ) { /* ... */ if (!withdrawQueueTokenBalanceRecorded) { totalWithdrawalQueueValue += renzoOracle.lookupTokenValue( collateralTokens[i], collateralTokens[j].balanceOf(withdrawQueue) ); } unchecked { ++j; } } /* ... */ totalWithdrawalQueueValue = true; }
i = 0, j = 0
- totalWithdrawalQueueValue is increased by stETH's value, using stETH's price.
i = 0, j = 1
- totalWithdrawalQueueValue is increased by WithdrawalQueue's wbETH balance; still using stETH price.
i = 0, j = 2
- totalWithdrawalQueueValue is increased by WithdrawalQueue's wbETH balance; still using stETH price.
Imagine there's 10 stETH in the system; collateralTokens = [mETH, stETH]; 1 mETH = 1.1 ETH, 1 stETH = 1 ETH;
calculateTVLs
wrongly returns 1.1 ETH. Bob gets 1 ezETH.calculateTVLs
wrongly returns 2.2 ETH. Alice receives her 1 stETH back, and has 0.090909... ezETH remaining, which she then redeems for mETH, effectively stealing Bob's deposited collateral.if (!withdrawQueueTokenBalanceRecorded) { totalWithdrawalQueueValue += renzoOracle.lookupTokenValue( - collateralTokens[i], + collateralTokens[j], collateralTokens[j].balanceOf(withdrawQueue) ); }
Other
#0 - c4-judge
2024-05-16T10:28:48Z
alcueca marked the issue as satisfactory
#1 - c4-judge
2024-05-16T10:38:47Z
alcueca changed the severity to 2 (Med Risk)
#2 - c4-judge
2024-05-16T10:39:08Z
alcueca changed the severity to 3 (High Risk)
#3 - c4-judge
2024-05-20T04:26:26Z
alcueca changed the severity to 2 (Med Risk)
#4 - c4-judge
2024-05-23T13:47:20Z
alcueca changed the severity to 3 (High Risk)
🌟 Selected for report: Sathish9098
Also found by: 0x73696d616f, 0xCiphky, 0xmystery, ABAIKUNANBAEV, Bauchibred, BiasedMerc, Fassi_Security, FastChecker, GalloDaSballo, GoatedAudits, K42, KupiaSec, LessDupes, Limbooo, ReadyPlayer2, Rhaydden, SBSecurity, Sabit, Sparrow, WildSniper, ZanyBonzy, adam-idarrha, adeolu, araj, aslanbek, atoko, b0g0, carlitox477, crypticdefense, fyamf, gesha17, gjaldon, grearlake, gumgumzum, hihen, honey-k12, hunter_w3b, inzinko, jesjupyter, jokr, kennedy1030, kind0dev, kinda_very_good, ladboy233, lanrebayode77, oakcobalt, oualidpro, pauliax, rbserver, t0x1c, tapir, underdog, xg, zzykxx
0 USDC - $0.00
DepositQueue is expected to receive rewards in any of the collateral tokens. They are expected to be forwarded to OperatorDelegators via sweepERC20
.
As the collateral balances of DepositQueue
are not included in RestakeManager#calculateTVLs
, one can monitor DepositQueue#sweepERC20
transactions, deposit
before them, initiate the withdrawal right after (at a higher ezETH exchange rate), and claim it after coolDownPeriod
, stealing rewards from honest depositors who have been holding ezETH for a significantly longer duration.
sweepERC20
transaction in the mempool;sweepERC20
transaction is mined;coolDownPeriod
.Include DepositQueue's balance in calculateTVL's, minus the fee that would be deduced during sweepERC20
.
Other
#0 - c4-judge
2024-05-16T05:47:32Z
alcueca marked the issue as not a duplicate
#1 - c4-judge
2024-05-16T05:47:39Z
alcueca changed the severity to 3 (High Risk)
#2 - c4-judge
2024-05-16T05:47:51Z
alcueca marked the issue as duplicate of #326
#3 - c4-judge
2024-05-16T05:56:53Z
alcueca changed the severity to 2 (Med Risk)
#4 - c4-judge
2024-05-17T12:47:56Z
alcueca marked the issue as satisfactory
#5 - c4-judge
2024-05-24T10:26:55Z
alcueca changed the severity to 3 (High Risk)
#6 - aslanbekaibimov
2024-05-26T12:00:45Z
@alcueca
I believe this should be a duplicate of #383 as long as #383 is a separate issue from #326.
The root cause is "DepositQueue ERC20 balances are not accounted in TVL", and the attack path is "sandwiching sweepERC20".
#7 - c4-judge
2024-05-27T10:02:19Z
alcueca marked the issue as not a duplicate
#8 - c4-judge
2024-05-27T10:02:28Z
alcueca changed the severity to QA (Quality Assurance)
#9 - c4-judge
2024-05-27T10:02:32Z
alcueca marked the issue as grade-b