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
The _beforeTokenTransfer function in ezEthToken.sol currently prohibits all transfers except minting and burning when paused:
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
if (paused) {
if (from != address(0) && to != address(0)) {
revert ContractPaused();
}
}
}
The withdraw function in WithdrawQueue.sol is designed to transfer ezETH funds from users to itself:
This violates the pause logic since it's a transfer from a user address (non-zero) to a contract address (also non-zero), so when paused, the above logic will cause the withdrawal to fail.
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();
}
}
}
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 theWithdrawQueue
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 theWithdrawQueue
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
The
_beforeTokenTransfer
function inezEthToken.sol
currently prohibits all transfers except minting and burning when paused:withdraw
function inWithdrawQueue.sol
is designed to transfer ezETH funds from users to itself: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 asWithdrawQueue
, even when the contract is paused. The modified logic could look like the following:Assessed type
DoS