RestakeManager susceptible to an inflation attack #60
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
duplicate-35
edited-by-warden
🤖_13_group
AI based duplicate group recommendation
sufficient quality report
This report is of sufficient quality
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Oracle/RenzoOracle.sol#L123-L149
Vulnerability details
Impact
First depositor can inflate the exchange rate of ezETH token such that any user who deposits afterwards receives less ezETH tokens for their deposits than they should. More info here, check example 2.
Proof of Concept
RestakeManager accepts ETH and ERC20 both as a collateral for minting ezETH token. Both could be used to perform this attack, however for simplicity, I'm going to show it for ETH deposits.
Let's have a look at the formula that is used to calculate the
ezETHToMint
,https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/RestakeManager.sol#L605-L609
https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Oracle/RenzoOracle.sol#L123-L149
The mintAmount is determined by subtracting
_existingEzETHSupply
from thenewEzETHSupply
, since those value already calculated above, we can simplified it futher for better view.the _existingEzETHSupply and _currentValueInProtocol(e.g. tvl) intiallialy are 0,
To perform an attack;
ezETHToMint
is same as 1 weihttps://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Oracle/RenzoOracle.sol#L130-L132
depositETH()
txn sent by a legimate user with 2 ETH of assets. Attacker saw it and try to frontrun it by adepositQueue.forwardFullWithdrawalETH(1 ether)
call,Note here, we cannot directly sent 1 ETH to depositQueue, since receive() will triggered and charge fee on the attacker sent amount.
The
forwardFullWithdrawalETH()
function here doing same as direct deposit will, also this call fill the withdraw buffer if required(means sending required fraction to withdrawQueue), but that won't be a problem, we'll see ahead._newValueAdded = 2 ETH,
_existingEzETHSupply = 1 WEI,
_currentValueInProtocol = totalTVL
totalTVL is retrieved from
calculateTVLs()
function during the deposits, it can seen below that the totalTVL includes eth balance from depositQueue and withdrawQueue(which possibly filled duringforwardFullWithdrawalETH
call above) contract as well,https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/RestakeManager.sol#L351-L356
So the totalTVL = 1 wei + 1 ETH from attacker
Due to rounding, the victim gets
(2 ether * 1) / (1 ether + 1) == 1 shares
which is same amount as the attacker. Attacker manage to steal(3 ether / 2) - 1 ether == 0.5 ether
worth of extra shares from the victim.Tools Used
Manual review
Recommended Mitigation Steps
There are few mitigation strategies shared here, which could be implemented by Renzo.
Assessed type
ERC4626
The text was updated successfully, but these errors were encountered: