DittoETH

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

Unsafe downcasting can cause users loss

Summary

In BridgeRouterFacet contract users may lose funds due to unsafe downcasting to uint88 when calling deposit functions

Vulnerability Details

In deposit and depositEth function you make a call to Bridge contract and down cast the returned uint256 to uint88, in this case BridgeReth contract in its deposit function calls getEthValue function by passing the deposited amount in rocket ETH Token contract and returns the returned value, this function caculate the amount as follows:

return amount.mul(totalEthBalance).div(rethSupply);

if a user deposit large amount of tokens and the totalEthBalance value is bigger than rethSupply in rocket ETH Token contract the returned value may be greater than uint88 and when downcasting it, it will overflow and user's balance will be updated with 0 insted of the amount they actualy deposited and their funds will be lost

Impact

when downcasting Solidity will not revert but overflow, in this case it cause users loss if they deposit large amount of assets and market conditions has changed in rocket ETH token contract.

in comments it is mentioned this is safe cast but it is not since you don't use safe type casting (you shouldn't rely on luck)

(this vulnerability only exist for deposting assets using BridgeReth contract and not BridgeSeth contract since it returns the same inputed value and there is no external call for calculating the value)

POC

File:2023-09-ditto\contracts\facets\BridgeRouterFacet.sol
46: function deposit(address bridge, uint88 amount)
47: external
48: nonReentrant
49: onlyValidBridge(bridge)
50: {
51: if (amount < Constants.MIN_DEPOSIT) revert Errors.UnderMinimumDeposit();
52: // @dev amount after deposit might be less, if bridge takes a fee
53: -> uint88 zethAmount = uint88(IBridge(bridge).deposit(msg.sender, amount)); // @dev(safe-cast)
54:
...
61:
62: vault.addZeth(zethAmount);
...
67: function depositEth(address bridge)
68: external
69: payable
70: nonReentrant
71: onlyValidBridge(bridge)
72: {
73: if (msg.value < Constants.MIN_DEPOSIT) revert Errors.UnderMinimumDeposit();
74:
...
81:
82: -> uint88 zethAmount = uint88(IBridge(bridge).depositEth{value: msg.value}()); // Assumes 1 ETH = 1 ZETH
83: vault.addZeth(zethAmount);

Tools Used

Manual Review

Recommendations

You can use SafeCast library from Openzeppelin for safe downcasting

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.