code-423n4 / 2024-04-renzo-validation

2 stars 2 forks source link

Unrestricted ETH Withdrawal During `Deposit/Withdrawal` Pause #667

Closed c4-bot-6 closed 5 months ago

c4-bot-6 commented 5 months ago

Lines of code

https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Delegation/OperatorDelegator.sol#L501-L524 https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Deposits/DepositQueue.sol#L152-L156 https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Deposits/DepositQueue.sol#L294-L306 https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Withdraw/WithdrawQueue.sol#L182-L185

Vulnerability details

Impact

Users can withdraw ETH even when deposits and withdrawals are paused by the DepositWithdrawPauserAdmin. This can lead to a situation where users are unable to withdraw their staked assets (tokens) while ETH can still be withdrawn.

Proof of Concept

When deposits and withdrawals are paused, any rewards send to the operatorDelegator from eigenPod receives This ETH is then forwarded to the

     *        This is an internal protocol function.
     * @dev Handle ETH sent to this contract - will get forwarded to the deposit queue for restaking as a protocol reward
     * @dev If msg.sender is eigenPod then forward ETH to deposit queue without taking cut (i.e. full withdrawal from beacon chain)
     */
    receive() external payable nonReentrant {
        // check if sender contract is EigenPod. forward full withdrawal eth received
        if (msg.sender == address(eigenPod)) {
            restakeManager.depositQueue().forwardFullWithdrawalETH{ value: msg.value }();
        } else {
            // considered as protocol reward
            uint256 gasRefunded = 0;
            uint256 remainingAmount = msg.value;
            if (adminGasSpentInWei[tx.origin] > 0) {
                gasRefunded = _refundGas();
                // update the remaining amount
                remainingAmount -= gasRefunded;
                // If no funds left, return
                if (remainingAmount == 0) {
                    return;
                }
            }
            // Forward remaining balance to the deposit queue
            address destination = address(restakeManager.depositQueue());
            (bool success, ) = destination.call{ value: remainingAmount }("");
            if (!success) revert TransferFailed();

            emit RewardsForwarded(destination, remainingAmount);
        }
    }

RestakeManager.depositQueue().forwardFullWithdrawalETH{value: msg.value}() function if the sender is the eigenPod. This allows users to withdraw ETH even when deposits and withdrawals are paused.

worst scenario if user deposit eth and withdraw LST tokens.

Tools Used

Manual review

Recommended Mitigation Steps

Modify the forwardFullWithdrawalETH function to check the pause status before forwarding ETH withdrawals.

Assessed type

Access Control

DadeKuma commented 5 months ago

@howlbot reject