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: 81/147
Findings: 2
Award: $10.98
🌟 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
Issue | Instances | |
---|---|---|
LOW-1 | ownership transfer in constructor is not implemented on Ownable2Step way | 1 |
LOW-2 | transaction fails on one of the variant of token & to | 1 |
LOW-3 | FULL_RESTRICTED_STAKER_ROLE can be frontran | 1 |
USDe::constructor
ownership transfer for first time in constructor is not implemented on Ownable2Step methodtransferOwnership(admin)
then from admin key, call acceptOwnership()
- _transferOwnership(admin); + transferOwnership(admin);
StakedUSDe.rescueTokens()
transaction fails if token
== stUSDE
&& to
== address with FULL_RESTRICTED_STAKER_ROLE
EthenaMinting.setDelegatedSigner(address)
is implemented in 2 step process like ownable2step.function rescueTokens(address token, uint256 amount, address to) external onlyRole(DEFAULT_ADMIN_ROLE) { if (address(token) == asset()) revert InvalidToken(); - IERC20(token).safeTransfer(to, amount); } function rescueTokens(address token, uint256 amount, address to) external onlyRole(DEFAULT_ADMIN_ROLE) { if (address(token) == asset()) revert InvalidToken(); + if (address(token) != address(this) && !hasRole(FULL_RESTRICTED_STAKER_ROLE, to)) { + IERC20(token).safeTransfer(to, amount); + } }
StakedUSDe._beforeTokenTransfer
can be frontran by a bot.BLACKLIST_MANAGER_ROLE
makes a tx, it can be searched via mempool and a bot with approval of the (to be blacklisted)'s address will transfer the funds to the delegate already set. Or a owner with key can run a bot to frontrun it.#0 - c4-pre-sort
2023-11-02T03:26:26Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-14T16:48:27Z
fatherGoose1 marked the issue as grade-b
🌟 Selected for report: 0xVolcano
Also found by: 0x11singh99, 0xAadi, 0xAnah, 0xgrbr, 0xhacksmithh, 0xhex, 0xpiken, 0xta, J4X, JCK, K42, Raihan, Rolezn, SAQ, SM3_SS, Sathish9098, SovaSlava, ThreeSigma, Udsen, arjun16, aslanbek, brakelessak, castle_chain, evmboi32, hunter_w3b, lsaudit, naman1778, niser93, nuthan2x, oakcobalt, pavankv, petrichor, phenom80, radev_sw, shamsulhaq123, tabriz, thekmj, unique, yashgoel72, ybansal2403
6.4563 USDC - $6.46
Issue | Instances | |
---|---|---|
GAS-1 | additional warm sload and memory expansion | 2 |
GAS-2 | update the state after validating the returned bool | 1 |
EthenaMinting::_setMaxRedeemPerBlock()
Gas inefficient due to additional warm sload and memory expansion.EthenaMinting._setMaxMintPerBlock()
, there is a new local variable oldMaxMintPerBlock
is declared to cache the storage to emit later after updating it.EthenaMinting._setMaxRedeemPerBlock()
& EthenaMinting._setMaxRedeemPerBlock()
EthenaMinting._setMaxRedeemPerBlock()
functionfunction _setMaxRedeemPerBlock(uint256 _maxRedeemPerBlock) internal { - uint256 oldMaxRedeemPerBlock = maxRedeemPerBlock; maxRedeemPerBlock = _maxRedeemPerBlock; - emit MaxRedeemPerBlockChanged(oldMaxRedeemPerBlock, maxRedeemPerBlock); } function _setMaxRedeemPerBlock(uint256 _maxRedeemPerBlock) internal { + emit MaxRedeemPerBlockChanged(maxRedeemPerBlock, _maxRedeemPerBlock); maxRedeemPerBlock = _maxRedeemPerBlock; }
EthenaMinting._deduplicateOrder()
, update the state only if valid
== true.valid
is validated after updating storage, so if valid == false, then its a gas inefficient.EthenaMinting._setMaxRedeemPerBlock()
functionfunction _deduplicateOrder(address sender, uint256 nonce) private returns (bool) { (bool valid, uint256 invalidatorSlot, uint256 invalidator, uint256 invalidatorBit) = verifyNonce(sender, nonce); - mapping(uint256 => uint256) storage invalidatorStorage = _orderBitmaps[sender]; - invalidatorStorage[invalidatorSlot] = invalidator | invalidatorBit; return valid; } function _deduplicateOrder(address sender, uint256 nonce) private returns (bool) { (bool valid, uint256 invalidatorSlot, uint256 invalidator, uint256 invalidatorBit) = verifyNonce(sender, nonce); + if(valid) { + mapping(uint256 => uint256) storage invalidatorStorage = _orderBitmaps[sender]; + invalidatorStorage[invalidatorSlot] = invalidator | invalidatorBit; + } return valid; }
#0 - c4-pre-sort
2023-11-01T15:39:25Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-10T20:11:03Z
fatherGoose1 marked the issue as grade-b