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: 118/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/main/contracts/StakedUSDeV2.sol#L42-L45
Users could have to face a cooldown period of MAX_COOLDOWN_DURATION
i.e. 90 days if they attempt to set assets
or shares
into cooldown before the DEFAULT_ADMIN_ROLE
sets the cooldownDuration
to 14 days using setCooldownDuration
function setCooldownDuration(uint24 duration) external onlyRole(DEFAULT_ADMIN_ROLE) { if (duration > MAX_COOLDOWN_DURATION) { revert InvalidCooldown(); } uint24 previousDuration = cooldownDuration; cooldownDuration = duration; emit CooldownDurationUpdated(previousDuration, cooldownDuration); }
This is at odds with the documentation
" Q: Why is there a cooldown period during launch? During the closed initial launch, there is a 14-day cooldown from requesting to unstake sUSDe to receiving USDe in return. Users must first request their USDe be unstaked wherein their USDe will be placed in a USDeSilo smart contract. Once the cooldown period has elapsed, users will be able to withdraw their USDe from the USDeSilo smart contract. "
and would mean users' assets are held in cooldown longer than necessary, potentially leading to loss of reputation / disengagement from users.
In cooldownAssets
and cooldownShares
, the cooldowns[owner].cooldownEnd
variable is set to uint104(block.timestamp) + cooldownDuration
function cooldownAssets(uint256 assets, address owner) external ensureCooldownOn returns (uint256) { if (assets > maxWithdraw(owner)) revert ExcessiveWithdrawAmount(); uint256 shares = previewWithdraw(assets); cooldowns[owner].cooldownEnd = uint104(block.timestamp) + cooldownDuration; cooldowns[owner].underlyingAmount += assets; _withdraw(_msgSender(), address(silo), owner, assets, shares); return shares; } function cooldownShares(uint256 shares, address owner) external ensureCooldownOn returns (uint256) { if (shares > maxRedeem(owner)) revert ExcessiveRedeemAmount(); uint256 assets = previewRedeem(shares); cooldowns[owner].cooldownEnd = uint104(block.timestamp) + cooldownDuration; cooldowns[owner].underlyingAmount += assets; _withdraw(_msgSender(), address(silo), owner, assets, shares); return assets; }
That means users can unstake
only after block.timestamp >= uint104(block.timestamp_initial) + cooldownDuration
as per function definition
function unstake(address receiver) external { UserCooldown storage userCooldown = cooldowns[msg.sender]; uint256 assets = userCooldown.underlyingAmount; if (block.timestamp >= userCooldown.cooldownEnd) { userCooldown.cooldownEnd = 0; userCooldown.underlyingAmount = 0; silo.withdraw(receiver, assets); } else { revert InvalidCooldown(); } }
meaning that if user calls cooldownAssets
or cooldownShares
before the cooldownDuration
is set to 14 days, he is going to have to wait for at least 14 days plus the time difference between the second and first call to cooldownAssets
or cooldownShares
to unstake ANY amount of shares
or assets
(this is linked to another vulnerability submitted as HIGH detailing the fact that calling cooldownAssets
or cooldownShares
more than once will effectively reset the cooldown period of ALL assets
or shares
to the cooldownDuration
at the time of the second call).
Visual Studio / Manual Review
Set cooldownDuration = 14 days
in StakedUSDeV2
's constructor.
Other
#0 - c4-pre-sort
2023-11-01T00:25:52Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-11-01T00:26:03Z
raymondfam marked the issue as duplicate of #4
#2 - c4-pre-sort
2023-11-01T19:31:05Z
raymondfam marked the issue as not a duplicate
#3 - c4-pre-sort
2023-11-01T19:31:13Z
raymondfam marked the issue as duplicate of #29
#4 - c4-judge
2023-11-13T19:07:00Z
fatherGoose1 marked the issue as satisfactory
#5 - c4-judge
2023-11-17T02:45:06Z
fatherGoose1 changed the severity to QA (Quality Assurance)
#6 - c4-judge
2023-11-17T16:47:08Z
This previously downgraded issue has been upgraded by fatherGoose1
#7 - c4-judge
2023-11-27T20:00:09Z
fatherGoose1 changed the severity to QA (Quality Assurance)
#8 - c4-judge
2023-11-27T20:01:25Z
fatherGoose1 marked the issue as grade-b