DittoETH

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

Lack of input validation whether or not a given amount of unstaking ETH would be more than the minimum amount of Lido and less than the maximum amount of Lido

Summary

According to the "Request" part in the documentation of the Lido, the minimal withdrawal amount is 100 wei and the maximum withdrawal amount is 1000 eth when a user send a withdrawal request to Lido.

However, within the BridgeSteth#unstake(), there is no input validation to check whether or not a given amount of unstaking would be more than the minimal withdrawal amount(100 wei) for a withdrawal request of Lido and less than the maximum withdrawal amount (1000 ETH) for a withdrawal request of Lido.

Therefore, if a user the BridgeSteth#unstake() via the BridgeRouterFacet#unstakeEth() with less than 100 wei or more than 1000 ether, the transaction will be reverted.

Vulnerability Details

When a user withdraw the amount of native ETH, the user call the BridgeRouterFacet#unstakeEth().
Within the BridgeRouterFacet#unstakeEth(), the BridgeSteth#unstake() would be called like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/facets/BridgeRouterFacet.sol#L138

function unstakeEth(address bridge, uint88 zethAmount)
external
nonReentrant
onlyValidBridge(bridge)
{
...
uint88 ethAmount = _ethConversion(vault, zethAmount);
vault.removeZeth(zethAmount, fee);
IBridge(bridge).unstake(msg.sender, ethAmount); ///<------- @audit
...

Within the BridgeSteth#unstake(), stETH#requestWithdrawals() would be called like this:
https://github.com/Cyfrin/2023-09-ditto/blob/main/contracts/bridges/BridgeSteth.sol#L94

function unstake(address to, uint256 amount) external onlyDiamond {
uint256[] memory amountArray = new uint256[](1);
amountArray[0] = amount;
uint256 requestId = unsteth.requestWithdrawals(amountArray, address(this))[0]; ///<------- @audit
unsteth.safeTransferFrom(address(this), to, requestId);
}

According to the "Request" part in the documentation of the Lido, the minimal withdrawal amount is 100 wei and the maximum withdrawal amount is 1000 eth when a user send a withdrawal request to Lido like this:

To request a withdrawal, one needs to approve the amount of stETH or wstETH to this contract or sign the ERC-2612 Permit, and then call the appropriate requestWithdrawals* method.

The minimal amount for a request is 100 wei, and the maximum is 1000 eth. More significant amounts should be split into several requests, which allows us to avoid clogging the queue with an extra large request.

However, within the BridgeSteth#unstake(), there is no input validation to check whether or not a given amount of unstaking would be more than the minimal withdrawal amount(100 wei) for a withdrawal request of Lido and less than the maximum withdrawal amount (1000 ETH) for a withdrawal request of Lido.

Therefore, if a user the BridgeSteth#unstake() via the BridgeRouterFacet#unstakeEth() with less than 100 wei or more than 1000 ether, the transaction will be reverted.

Impact

If a user the BridgeSteth#unstake() via the BridgeRouterFacet#unstakeEth() with less than 100 wei or more than 1000 ether, the transaction will be reverted.

Tools Used

  • Manual review

Recommendations

Within the BridgeSteth#unstake(), consider adding an input validation to check whether or not the amount assigned would be more than the minimal withdrawal amount(100 wei) for a withdrawal request of Lido and less than the maximum withdrawal amount (1000 ETH) for a withdrawal request of Lido like this:

function unstake(address to, uint256 amount) external onlyDiamond {
+ require(amount >= 100, "The amount for a withdrawal request must be more than the minimal amount (100 wei)");
+ require(1000 * 1e18 <= amount, "The amount for a withdrawal request must be less than the maximum amount (1000 ETH)");
uint256[] memory amountArray = new uint256[](1);
amountArray[0] = amount;
uint256 requestId = unsteth.requestWithdrawals(amountArray, address(this))[0];
unsteth.safeTransferFrom(address(this), to, requestId);
}
Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

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