DittoETH

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

Users are able to deposit stEth and withdraw rETH and vice versa.

Summary

The ability to deposit one of the two LST's (stEth and rETH) and withdraw the other leads to various problems which can affect user’s funds and user’s experience while using the protocol.

Vulnerability Details

This issue generates the following possibilities:

A. Accidental (or not) withdrawals of a different LST will cause "ERC20: transfer amount exceeds balance" errors for people who want to withdraw the same asset they deposited.

In the example below, Chandler deposited stEth, Ross deposited rETH, Chandler mistakenly withdrew rETH forcing Ross to either withdraw stEth or getting an error when he tries to withdraw rETH.

POC

function test_DepositSTETHWithdrawRETH() public {
address chandler = address(0xabc);
address ross = address(0xef1);
deal(_reth, ross, 5 ether);
deal(_steth, chandler, 5 ether);
uint88 amount = 2.5 ether;
vm.startPrank(ross);
IRocketTokenRETH(_reth).approve(_bridgeReth, type(uint88).max);
diamond.deposit(_bridgeReth, amount);
vm.stopPrank();
vm.startPrank(chandler);
ISTETH(_steth).approve(_bridgeSteth, type(uint88).max);
diamond.deposit(_bridgeSteth, amount);
diamond.withdraw(_bridgeReth, amount);
vm.stopPrank();
console.log("Chandler's rETH balance is %s", IRocketTokenRETH(_reth).balanceOf(chandler));
//Ross attempts to withdraw his initial rETH deposit
vm.startPrank(ross);
vm.expectRevert("ERC20: transfer amount exceeds balance");
diamond.withdraw(_bridgeReth, amount);
vm.stopPrank();
}

A more intricate case of this happens when Chandler withdraws a mix of LST's. In this case when Ross would try to withdraw he’d need to withdraw the exact proportion of rETH/stETH available. For example if Chandler withdraws 25% rETH and 75% stETH then Ross needs to withdraw 75% rETH and 25% stETH or he’ll get the "ERC20: transfer amount exceeds balance" error. Same thing applies if Chandler withdraws only a partial amount, using the token different than the one he deposited;

B. The issue could be exploited by a malicious actor through sandwiching any deposit of rETH/stETH depending on the arbitrage possibility between the two tokens (obviously taking into account the Withdrawal Fees in the profitability calculation).

Impact

  1. Users confusion due to failing withdraws (low occurrence, it could happen at the beginning of the protocol or in case everyone withdraws everything in later stages);
  2. Users loss of $ value due to sandwiching (high occurrence as long as it’s profitable);
  3. Slightly diminished yield rates. This can happen when participants decide to only withdraw the LST with the higher yield, leaving the protocol holding only the lower yield token (high occurrence as long as there’s a difference between stETH yield and rETH yield.
  4. In case one of the two projects fails, some users will instantly withdraw the good token leaving the other users + protocol holding the failed token.

Tools Used

Forge testing

Recommendations

Fixing this issue requires some extreme measures:

  1. Limit the number of LST used to 1, either stETH or rETH, and if someone wants to use the token that’s not directly accepted by the protocol facilitate the conversion by interacting with curve making a big disclaimer that everything gets converted to stETH (if this is the accepted LST) and only that can be withdrawn. This is not ideal because it limits the users flexibility.

  2. Keep a record of who deposited what LST. This would imply a major refactoring of the codebase, introducing a lot of complexity especially around yield tracking.

Updates

Lead Judging Commences

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

finding-579

Support

FAQs

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