Malicious user can block the deposits of all collateralToken into the protocol so as
to steal all the rewards from the EigenLayer strategy and
also cause a denial of service for other users who want to deposit into the protocol as all deposits after the attackers deposit will fail
Proof of Concept
This attack is a combination because of the donation and first depositor Attack
For simplicity, I assume withdrawalBufferTarget = 11 ether (although not needed)
File: RestakeManager.sol
491: function deposit(
492: IERC20 _collateralToken,
493: uint256 _amount,
494: uint256 _referralId
495: ) public nonReentrant notPaused {
496: // Verify collateral token is in the list - call will revert if not found
497: uint256 tokenIndex = getCollateralTokenIndex(_collateralToken);
498:
499: // Get the TVLs for each operator delegator and the total TVL
500: (
501: uint256[][] memory operatorDelegatorTokenTVLs,
502: uint256[] memory operatorDelegatorTVLs,
504: uint256 totalTVL
505: ) = calculateTVLs();
538: ...
564: // Calculate how much ezETH to mint
565: @> uint256 ezETHToMint = renzoOracle.calculateMintAmount(
610: totalTVL,
611: collateralTokenValue,
612: ezETH.totalSupply()
613: );
File: RenzoOracle.sol
124: function calculateMintAmount(
125: uint256 _currentValueInProtocol, // totalTVL
126: uint256 _newValueAdded,
127: uint256 _existingEzETHSupply
128: ) external pure returns (uint256) {
129: // For first mint, just return the new value added.
130: // Checking both current value and existing supply to guard against gaming the initial mint
131: if (_currentValueInProtocol == 0 || _existingEzETHSupply == 0) {
132: return _newValueAdded; // value is priced in base units, so divide by scale factor
134: }
135:
136: // Calculate the percentage of value after the deposit
137: uint256 inflationPercentaage = (SCALE_FACTOR * _newValueAdded) / (_currentValueInProtocol + _newValueAdded);
138:
139: // Calculate the new supply ==>> targetv supply
140: uint256 newEzETHSupply = (_existingEzETHSupply * SCALE_FACTOR) / (SCALE_FACTOR - inflationPercentaage);
141:
142: // Subtract the old supply from the new supply to get the amount to mint
143: uint256 mintAmount = newEzETHSupply - _existingEzETHSupply;
144:
145: // Sanity check
146: @> if (mintAmount == 0) revert InvalidTokenAmount();
147:
148: return mintAmount;
149: }
Bob frontruns the first depositor with by calling RestakeManager::deposit(...) with 1 wei of any _collateralToken Bob gets minted 1 wie of ezETH and totalTVL is 1 wei
immediately after he donates (or transfers) 10 ether of any _collateralToken into the WithdrawalQueue contract to inflate the protocols totalTVL to (10ETH + 1 wei = 10000000000000000001 wei)
Alice attempts to deposit by calling RestakeManager::deposit(...) with 10 ether of any _collateralToken of her choice but because there is a huge imbalance between the totalTVL and ezETH totalSupply,
when RenzoOracle.calculateMintAmount(...) is called at L565 with Alice 10 ether, and the inflated totalTVL = (10ETH + 1 wei) and and ezETH totalSupply = 1 wei of ezETH the amount of ezETHToMint to Alice returns 0 and reverts as shown below.
Lines of code
https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/RestakeManager.sol#L565-L569 https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Oracle/RenzoOracle.sol#L123-L149
Vulnerability details
Impact
Malicious user can block the deposits of all
collateralToken
into the protocol so asstrategy
andProof of Concept
This attack is a combination because of the donation and first depositor Attack
For simplicity, I assume
withdrawalBufferTarget
= 11 ether (although not needed)RestakeManager::deposit(...)
with 1wei
of any_collateralToken
Bob gets minted 1wie
of ezETH andtotalTVL
is 1 wei_collateralToken
into theWithdrawalQueue
contract to inflate the protocolstotalTVL
to (10ETH + 1 wei = 10000000000000000001 wei)RestakeManager::deposit(...)
with 10 ether of any_collateralToken
of her choice but because there is a huge imbalance between thetotalTVL
and ezETHtotalSupply
,RenzoOracle.calculateMintAmount(...)
is called atL565
with Alice 10 ether, and the inflatedtotalTVL
= (10ETH + 1 wei) and and ezETHtotalSupply
= 1 wei of ezETH the amount ofezETHToMint
to Alice returns 0 and reverts as shown below.Tools Used
Manual review
Recommended Mitigation Steps
Consider making a sacrificial deposit of substantial amount at the point of deployment.
Assessed type
Other