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

2 stars 2 forks source link

Withdraw Queue Hindered by Current ezEthToken Pause Implementation #40

Closed c4-bot-6 closed 3 months ago

c4-bot-6 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/Withdraw/WithdrawQueue.sol#L214 https://github.com/code-423n4/2024-04-renzo/blob/519e518f2d8dec9acf6482b84a181e403070d22d/contracts/token/EzEthToken.sol#L69

Vulnerability details

Description

The ezEthToken contract is designed to allow minting and burning operations to continue even when the token contract is in paused state. However, due to an implementation oversight, the current pause mechanism also inadvertently blocks the initial transfer of ezETH tokens to the WithdrawQueue contract (required for initiating withdrawal). This results in the inability for users to initiate withdrawal requests during the pause state.

Impact

When the ezEthToken contract is paused, users are unable to transfer their ezETH tokens to the WithdrawQueue contract to initiate the withdrawal process. This affects the liquidity and accessibility of users' funds as they are prevented from performing withdrawals, despite the intention for the contract to allow minting and burning during the pause. The inability to withdraw during pause modes could create user dissatisfaction and erode trust in the platform, as well as potentially have financial implications for token holders.

Proof of Concept

Tools Used

Manual code review and logical analysis of the pause mechanism within the smart contract.

Recommended Mitigation Steps

The pause functionality needs to be extended to allow a user-to-contract transfer of ezETH tokens specifically for the withdrawal process. This can be achieved by modifying the _beforeTokenTransfer function to allow for exceptions when transferring to certain whitelisted contracts, such as WithdrawQueue, even when the contract is paused. The modified logic could look like the following:

function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
) internal virtual override {
    super._beforeTokenTransfer(from, to, amount);

    if (paused) {
        bool isMinting = from == address(0);
        bool isBurning = to == address(0);
        bool isWithdrawQueueTransfer = to == address(WithdrawQueue); // Assuming WithdrawQueue is set

        if (!(isMinting || isBurning || isWithdrawQueueTransfer)) {
            revert ContractPaused();
        }
    }
}

Assessed type

DoS

DadeKuma commented 3 months ago

@howlbot accept