DittoETH

Ditto
DeFiFoundryOracle
55,000 USDC
View results
Submission Details
Severity: medium
Valid

Potential DoS (blocked) on rETH unstake

Summary

Potential DoS (blocked) on rETH unstake

Vulnerability Details

The rETH token has a feature that makes sure a certain amount of time has passed since the last deposit. It does this using a timelock system in the _beforeTokenTransfer function.

https://github.com/rocket-pool/rocketpool/blob/master/contracts/contract/token/RocketTokenRETH.sol#L157-L170

function _beforeTokenTransfer(address from, address, uint256) internal override {
// Don't run check if this is a mint transaction
if (from != address(0)) {
// Check which block the user's last deposit was
bytes32 key = keccak256(abi.encodePacked("user.deposit.block", from));
uint256 lastDepositBlock = getUint(key);
if (lastDepositBlock > 0) {
// Ensure enough blocks have passed
uint256 depositDelay = getUint(keccak256(abi.encodePacked(keccak256("dao.protocol.setting.network"), "network.reth.deposit.delay")));
uint256 blocksPassed = block.number.sub(lastDepositBlock);
require(blocksPassed > depositDelay, "Not enough time has passed since deposit");
// Clear the state as it's no longer necessary to check this until another deposit is made
deleteUint(key);
}
}
}

This function is called before all transfer, mint, and burns.

in DittoETH, there is an unstake on BridgeReth which will burn the rETH.

File: BridgeReth.sol
098: function unstake(address to, uint256 amount) external onlyDiamond {
099: IRocketTokenRETH rocketETHToken = _getRethContract();
100: uint256 rethValue = rocketETHToken.getRethValue(amount);
101: uint256 originalBalance = address(this).balance;
102: @> rocketETHToken.burn(rethValue);
103: uint256 netBalance = address(this).balance - originalBalance;
104: if (netBalance == 0) revert NetBalanceZero();
105: (bool sent,) = to.call{value: netBalance}("");
106: assert(sent);
107: }

Originally, it took 24 hours before you could withdraw your deposit. However, at some point, this was changed to zero, meaning there's a chance it might be changed back to a non-zero value. This could potentially prevent withdrawals from Reth because when someone deposits into Rocket Pool, they can only withdraw (or "burn") after a certain number of blocks have passed.

So, whenever the Reth contract deposits into Rocket Pool, it updates a value called lastDepositBlock, and then withdrawals are blocked for a number of blocks equal to depositDelay. This means users can't withdraw from all the different parts (or "derivatives") because the process of unstaking goes through all of them.

Additionally, a user with bad intentions could stake their deposit at regular intervals (every depositDelay amount of blocks) in order to block withdrawals for others.

Thus, any valid user may be blocked to unstake due to some bad user keep blocking the withdrawals.

There is a thread discussion about this on rocketpool which you may want to read.

And also, for a referrence, this same issue was classified as accepted medium issue on Code4rena:

  • https://code4rena.com/reports/2023-03-asymmetry#m-08-possible-dos-on-unstake

  • https://github.com/code-423n4/2023-03-asymmetry-findings/issues/685

  • https://github.com/code-423n4/2023-03-asymmetry-findings/issues/202

  • https://github.com/code-423n4/2023-03-asymmetry-findings/issues/522

Impact

If the delay value is changed again for any reason, any withdrawals that don't wait for the required delay time since the last deposit will not work. Since users can keep adding more ETH, this would make the admins have to shut down the Rocket Pool derivative for an unknown amount of time so that users can take their ETH out.

Tools Used

Manual analysis

Recommendations

Consider changing the Reth so that users can also get rETH through the UniswapV3 pool. This might mean users get slightly less rETH on average because of slippage, but it would help avoid potential problems with the deposit delay mechanism in the future.

Updates

Lead Judging Commences

0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-88

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.