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: 81/122
Findings: 1
Award: $1.48
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: t0x1c
Also found by: 0xCiphky, 0xDemon, Bauchibred, DanielArmstrong, FastChecker, MSaptarshi, Maroutis, NentoR, Ocean_Sky, PNS, Rhaydden, SBSecurity, Shaheen, Tigerfrake, ZanyBonzy, atoko, btk, carlitox477, crypticdefense, honey-k12, hunter_w3b, ilchovski, jokr, ladboy233, rbserver, twcctop, umarkhatab_465
1.479 USDC - $1.48
https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/RestakeManager.sol#L491 https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Withdraw/WithdrawQueue.sol#L206
In the absence of slippage protection, users may not receive the exact amount of assets they expect during deposits and withdrawals. This can occur due to several factors, including:
The price of the asset may change between the time the transaction is initiated and the time it is executed. Most chainlink LST/ETH price feeds allow a price difference of +/- 2%. This can result in the user receiving more or fewer assets than they expected.
Slashing of operators and validators, can affect the total TVL (Total Value Locked), which is used to calculate the amount of assets owed to users.
function deposit( IERC20 _collateralToken, uint256 _amount, uint256 _referralId ) public nonReentrant notPaused { // Verify collateral token is in the list - call will revert if not found uint256 tokenIndex = getCollateralTokenIndex(_collateralToken); // Get the TVLs for each operator delegator and the total TVL ( uint256[][] memory operatorDelegatorTokenTVLs, uint256[] memory operatorDelegatorTVLs, uint256 totalTVL ) = calculateTVLs(); // Get the value of the collateral token being deposited uint256 collateralTokenValue = renzoOracle.lookupTokenValue(_collateralToken, _amount); [...] // Call deposit on the operator delegator operatorDelegator.deposit(_collateralToken, _amount); // Calculate how much ezETH to mint uint256 ezETHToMint = renzoOracle.calculateMintAmount( totalTVL, collateralTokenValue, ezETH.totalSupply() ); [...] }
function withdraw(uint256 _amount, address _assetOut) external nonReentrant { [...] // calculate totalTVL (, , uint256 totalTVL) = restakeManager.calculateTVLs(); // Calculate amount to Redeem in ETH uint256 amountToRedeem = renzoOracle.calculateRedeemAmount( _amount, ezETH.totalSupply(), totalTVL ); [...] }
Manual review
Implement a minimum expected amount parameter that will halt the transaction if the expected amount deviates significantly from the actual amount. This will provide users with more control over their transactions and protect them from unexpected losses.
Example implementation:
function deposit( IERC20 _collateralToken, uint256 _amount, + uint256 minEzETHAmountExpected, uint256 _referralId ) public nonReentrant notPaused { [...] // Calculate how much ezETH to mint uint256 ezETHToMint = renzoOracle.calculateMintAmount( totalTVL, collateralTokenValue, ezETH.totalSupply() ); + if (ezETHToMint < minEzETHAmountExpected) { + revert MinimumAmountToReceiveNotMet(); + } [...] }
Invalid Validation
#0 - c4-judge
2024-05-17T13:28:46Z
alcueca marked the issue as satisfactory