Platform: Code4rena
Start Date: 24/10/2023
Pot Size: $36,500 USDC
Total HM: 4
Participants: 147
Period: 6 days
Judge: 0xDjango
Id: 299
League: ETH
Rank: 142/147
Findings: 1
Award: $4.52
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xmystery
Also found by: 0x11singh99, 0xAadi, 0xAlix2, 0xG0P1, 0xStalin, 0xWaitress, 0x_Scar, 0xhacksmithh, 0xhunter, 0xpiken, Al-Qa-qa, Arz, Avci, Bauchibred, BeliSesir, Breeje, Bughunter101, DarkTower, Eeyore, Fitro, HChang26, Imlazy0ne, J4X, JCK, Kaysoft, Kral01, Madalad, Mike_Bello90, Noro, PASCAL, PENGUN, Proxy, Rickard, Shubham, SovaSlava, Strausses, Team_Rocket, ThreeSigma, Topmark, Udsen, Walter, Yanchuan, Zach_166, ZanyBonzy, adam-idarrha, adeolu, almurhasan, arjun16, ast3ros, asui, ayden, btk, cartlex_, castle_chain, cccz, chainsnake, codynhat, critical-or-high, cryptonue, csanuragjain, deepkin, degensec, dirk_y, erebus, foxb868, ge6a, hunter_w3b, jasonxiale, kkkmmmsk, lanrebayode77, lsaudit, marchev, matrix_0wl, max10afternoon, nuthan2x, oakcobalt, oxchsyston, pavankv, peanuts, pep7siup, pipidu83, pontifex, ptsanev, qpzm, radev_sw, rokinot, rotcivegaf, rvierdiiev, sorrynotsorry, squeaky_cactus, supersizer0x, tnquanghuy0512, twcctop, twicek, young, zhaojie, ziyou-
4.5226 USDC - $4.52
https://github.com/code-423n4/2023-10-ethena/blob/ee67d9b542642c9757a6b826c82d0cae60256509/contracts/StakedUSDeV2.sol#L111-L122 https://github.com/code-423n4/2023-10-ethena/blob/ee67d9b542642c9757a6b826c82d0cae60256509/contracts/StakedUSDeV2.sol#L95-L106
The cooldownAssets()
and cooldownShares()
functions of the staking contract are used to start the cooldown period for either asset or shares conversions for a given user, provided as an argument. A lack of access control would allow malicious users with allowance for the USDe to prevent them from unstaking.
A malicious allowance spender can extend the cooldown period by simply calling the function and covering the minimal amount threshold for the owner.
Add the following test to StakedUSDeV2.cooldownEnabled.t.sol
:
function testCanDosWithdrawal() public { vm.startPrank(bob); stakedUSDe.approve(alice, type(uint256).max); vm.stopPrank(); uint256 amount = 100000 ether; _mintApproveDeposit(alice, amount); _mintApproveDeposit(bob, amount); vm.startPrank(bob); stakedUSDe.cooldownShares(1 ether, bob); vm.stopPrank(); (uint104 cooldownEndFirst, ) = stakedUSDe.cooldowns(bob); vm.warp(cooldownEndFirst + 1); vm.startPrank(alice); stakedUSDe.cooldownShares(1 ether, bob); vm.stopPrank(); (uint104 cooldownEndSecond, ) = stakedUSDe.cooldowns(bob); console.log("Cooldown end 1: ", cooldownEndFirst); console.log("Cooldown end 2: ", cooldownEndSecond); }
[PASS] testCanDosWithdrawal() (gas: 342615) Logs: Cooldown end 1: 7776001 Cooldown end 2: 15552002
As you can see, the cooldown period does indeed increase even if the caller is not the owner of the tokens, as long as the malicious actor has allowance on the tokens, which isn't hard and can be the case for a number of reasons. The DoS is not permanent, due to the allowance factor, but it can indeed be very long, since the default set cooldown period is 90 days. There is a possible race condition by front-running the allowance cancellation with yet another cooldown increase, so 90 days is the bare-minimum time a user can be unwillingly locked out from unstaking.
Manual Review
Do not allow arbitrary users to tamper with others' cooldown periods by requiring only the owner to be the caller of the 2 functions.
Access Control
#0 - c4-pre-sort
2023-10-31T04:07:51Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-10-31T04:08:05Z
raymondfam marked the issue as duplicate of #4
#2 - c4-pre-sort
2023-11-01T19:36:34Z
raymondfam marked the issue as duplicate of #514
#3 - c4-judge
2023-11-10T21:27:01Z
fatherGoose1 marked the issue as unsatisfactory: Invalid
#4 - PlamenTSV
2023-11-15T08:00:55Z
I believe issue #666 https://github.com/code-423n4/2023-10-ethena-findings/issues/666 covers a similar scenario regarding allowances and their potential abuse. As of the current issue, that in the dupe gets invalidated due to the approve being voluntary - there are an enormous number of cases where a person would grant allowance to a 3rd party. Giving them rights to some of our tokens should NOT grant them privilege over our vesting periods. The minimum amount of time that a malicious allowance holder can lock up is 90 days if he does so immediately which I believe complies with C4 rules. In the event that you still believe approval is such a user-driven error and not an error in the code that allows such impacts, I still believe this is QA at worst, as well as all other duplicates. Thank you.
#5 - c4-judge
2023-11-17T17:04:08Z
fatherGoose1 changed the severity to QA (Quality Assurance)
#6 - c4-judge
2023-11-20T20:19:18Z
fatherGoose1 marked the issue as grade-b