DittoETH

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

Missing deposit availability checks

Summary

The users will not be able to stake their funds and there will be loss of reputation

Vulnerability Details

The BridgeRouterFacet.depositEth() function allows users to deposit ETH into a specified bridge contract, converting it into an equivalent amount of zETH tokens.
Inside the function, depositEth() may call the stEth.submit() function.Below is for stEth contract's submit() function to adapt to Lido staking.

function submit(address _referral) external payable returns (uint256) {
return _submit(_referral);
}
function _submit(address _referral) internal returns (uint256) {
require(msg.value != 0, "ZERO_DEPOSIT");
StakeLimitState.Data memory stakeLimitData = STAKING_STATE_POSITION.getStorageStakeLimitStruct();
// There is an invariant that protocol pause also implies staking pause.
// Thus, no need to check protocol pause explicitly.
require(!stakeLimitData.isStakingPaused(), "STAKING_PAUSED");
if (stakeLimitData.isStakingLimitSet()) {
uint256 currentStakeLimit = stakeLimitData.calculateCurrentStakeLimit();
require(msg.value <= currentStakeLimit, "STAKE_LIMIT");
STAKING_STATE_POSITION.setStorageStakeLimitStruct(stakeLimitData.updatePrevStakeLimit(currentStakeLimit - msg.value));
}
uint256 sharesAmount = getSharesByPooledEth(msg.value);
_mintShares(msg.sender, sharesAmount);
_setBufferedEther(_getBufferedEther().add(msg.value));
emit Submitted(msg.sender, msg.value, _referral);
_emitTransferAfterMintingShares(msg.sender, sharesAmount);
return sharesAmount;
}

The Lido protocol implements a daily staking limit both for stETH and WstETH as per their docs
Accordingly the daily rate is 150000 ETH and the deposit() function will revert if the limit is hit. From the docs:

Staking rate limits
In order to handle the staking surge in case of some unforeseen market conditions, the Lido protocol implemented staking rate limits aimed at reducing the surge's impact on the staking queue & Lido’s socialized rewards distribution model. There is a sliding window limit that is parametrized with _maxStakingLimit and _stakeLimitIncreasePerBlock. This means it is only possible to submit this much ether to the Lido staking contracts within a 24 hours timeframe. Currently, the daily staking limit is set at 150,000 ether.
You can picture this as a health globe from Diablo 2 with a maximum of _maxStakingLimit and regenerating with a constant speed per block. When you deposit ether to the protocol, the level of health is reduced by its amount and the current limit becomes smaller and smaller. When it hits the ground, transaction gets reverted.
To avoid that, you should check if getCurrentStakeLimit() >= amountToStake, and if it's not you can go with an alternative route. The staking rate limits are denominated in ether, thus, it makes no difference if the stake is being deposited for stETH or using the wstETH shortcut, the limits apply in both cases.

However this check was not done either in the protocol. So if the function reverts, the deposit function will revert and it will not be possible to deposit to the derivatives as well.

Impact

The users will not be able to stake their funds and there will be loss of reputation

Tools Used

Vscode

Recommendations

For stETH contract, checking the daily limit via getCurrentStakeLimit() >= amountToStake

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.