A similar logic to the _checkAndFillETHWithdrawBuffer logic was not implemented for the ERC20 token deposit. This means that the withdrawalBufferTarget through the fillERC20withdrawBuffer can be exceeded.
This could have a big impact on the system as there is a possibility of a large imbalance between the value of the depositQueue contract which does the restaking on the restakingManager contract. There could be a dearth of value on deposits if a large number of ERC20 ETH derivatives were deposited through the deposit function in the restakeManager contract and it takes 7 days before a withdrawal is claimed.
While there is an implementation of bufferFill in the restakeManager contract, the original impact is not solved which is having some value of ETH for staking in the Operator Delegate through the reStakingManager, instead the ERC20 tokens are sent to the OD.
Proof of Concept
Deploy and initialize the WithdrawQueue with ETH and stETH withdrawalBufferTarget of 1 ETH.
Deploy the DepositQueue contract
call the fillERC20withdrawBuffer with 2 stETH or add the update the depositQueue in the restakeManager and call the deposit
all stETH is transferred to the WithdrawQueue contract with no value left for restaking as the restakeManage
The implementation for erc20 withdraw buffer can be found here
function fillERC20withdrawBuffer(
address _asset,
uint256 _amount
) external nonReentrant onlyRestakeManager {
if (_amount == 0 || _asset == address(0)) revert InvalidZeroInput();
// safeTransfer from restake manager to this address
IERC20(_asset).safeTransferFrom(msg.sender, address(this), _amount);
// approve the token amount for withdraw queue
IERC20(_asset).safeApprove(address(withdrawQueue), _amount);
// call the withdraw queue to fill up the buffer
withdrawQueue.fillERC20WithdrawBuffer(_asset, _amount);
}
Tools Used
Manual Review
Recommended Mitigation Steps
implement the similar swap system in the WithdrawQueue to send the needed deficit and the rest of the ERC20 value is converted to ETH for ETH restaking.
send all ERC20 token to the depositQueue and then,
implement similar _checkAndFillETHWithdrawBuffer but for ERC20 token
execute withdrawQueue.fillERC20WithdrawBuffer(_asset, deficit);. deficit is bufferToFill
get the equivalent value of eth for the remaining ERC20 token after bufferToFill
swap ERC20 token e.g stETH for ETH
stakeEthFromQueue or stakeEthFromQueueMulti can be called at any time by restakeadmin when the value is up to 32 ETH
Lines of code
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Deposits/DepositQueue.sol#L134-L144 https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/RestakeManager.sol#L491-L576
Vulnerability details
Impact
A similar logic to the
_checkAndFillETHWithdrawBuffer
logic was not implemented for the ERC20 token deposit. This means that thewithdrawalBufferTarget
through thefillERC20withdrawBuffer
can be exceeded.This could have a big impact on the system as there is a possibility of a large imbalance between the value of the depositQueue contract which does the restaking on the restakingManager contract. There could be a dearth of value on deposits if a large number of ERC20 ETH derivatives were deposited through the
deposit
function in therestakeManager
contract and it takes 7 days before a withdrawal is claimed.While there is an implementation of bufferFill in the restakeManager contract, the original impact is not solved which is having some value of ETH for staking in the Operator Delegate through the reStakingManager, instead the ERC20 tokens are sent to the OD.
Proof of Concept
WithdrawQueue
with ETH and stETH withdrawalBufferTarget of 1 ETH.DepositQueue
contractfillERC20withdrawBuffer
with 2 stETH or add the update the depositQueue in the restakeManager and call the depositWithdrawQueue
contract with no value left for restaking as the restakeManageThe implementation for erc20 withdraw buffer can be found here
Tools Used
Manual Review
Recommended Mitigation Steps
implement the similar swap system in the
WithdrawQueue
to send the needed deficit and the rest of the ERC20 value is converted to ETH for ETH restaking._checkAndFillETHWithdrawBuffer
but for ERC20 tokenwithdrawQueue.fillERC20WithdrawBuffer(_asset, deficit);
.deficit
isbufferToFill
bufferToFill
stakeEthFromQueue
orstakeEthFromQueueMulti
can be called at any time by restakeadmin when the value is up to 32 ETHAssessed type
Other