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: 138/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
Tag | Issue | Contexts |
---|---|---|
L-1 | Wrong error reverted in the verifyOrder function | 1 |
L-2 | Potential for USDe to end up in custodian wallet | 1 |
L-3 | Use safeTransfer instead of transfer in USDeSilo::withdraw | 1 |
Total: 3 contexts over 3 issues
Tag | Issue | Contexts |
---|---|---|
NC-1 | Unnecessary addition of getUnvestedAmount() in the transferInRewards function | 1 |
Total: 1 context over 1 issue
verifyOrder
functionThe revert message for when the order.beneficiary
address is a zero address is wrong as it logs InvalidAmount
which is literally non-related to a zero address check error name you'd expect.
Context: EthenaMinting::verifyOrder
// @> Line 343: if (order.beneficiary == address(0)) revert InvalidAmount();
As confirmed by the sponsor, the custodian wallet is expected to never be sent/hold USDe as the custodian wallet literally holds the assets transferred after minting of USDe e.g stETH, ETH, etc before it gets delegated to the perps exchange. With this in mind, it makes sense to revert transactions that attempt to transfer USDe to the custodian wallet when the transferToCustody
function is called.
Context: EthenaMinting::transferToCustody
function transferToCustody(address wallet, address asset, uint256 amount) external nonReentrant onlyRole(MINTER_ROLE) { if (wallet == address(0) || !_custodianAddresses.contains(wallet)) revert InvalidAddress(); // @> let's have a check here to revert txns that attempt to transfer USDe to the custodian wallet if (asset == NATIVE_TOKEN) { (bool success,) = wallet.call{value: amount}(""); if (!success) revert TransferFailed(); } else { IERC20(asset).safeTransfer(wallet, amount); } emit CustodyTransfer(wallet, asset, amount); }
Usually, when this occurs right now funds will just be retreived from the custodian wallet and another transfer of the intended asset
will be initiated but it's a great thing to consider only allowing transfers of assets that are supposed to be sent to the custodian address. A whitelist could suffice in this scenario and render a check similar to this below:
if (!_custodianAssets.contains(asset)) revert InvalidAsset();
safeTransfer
instead of transfer
in USDeSillo::withdraw
It is good to add a require() statement that checks the return value of token transfers or to use something like OpenZeppelin’s safeTransfer/safeTransferFrom unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures of transfers and affect token accounting in contract.
Context: USDeSillo::withdraw.
function withdraw(address to, uint256 amount) external onlyStakingVault { @> USDE.transfer(to, amount); }
getUnvestedAmount()
in the transferInRewards
function.Function transferInRewards
in StakedUSDe.sol has an unnecessary operation which always results in adding zero.
Context: StakedUSDe::transferInRewards
uint256 newVestingAmount = amount + getUnvestedAmount();
As the function first checks if (getUnvestedAmount() > 0) revert StillVesting();
, the value of getUnvestedAmount()
will always be zero at the next line.
Mitigation steps: Simply delete this part + getUnvestedAmount()
at line 91 in the code of StakedUSDe.sol
#0 - c4-pre-sort
2023-11-02T03:39:47Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-14T16:43:02Z
fatherGoose1 marked the issue as grade-b