-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
scammed - StakingModule::convertAndDeposit wrong buffered and unfinalized check can prevent some deposits #213
Comments
Escalate This issue is valid and clearly shows how in certain scenarios StakingModule will fail to deposit into Lido unfairly, while there will be still some buffer left. The example that we have given explains how the order of operations, first to check for the function convertAndDeposit(
uint256 amount,
uint256 blockNumber,
bytes32 blockHash,
bytes32 depositRoot,
uint256 nonce,
bytes calldata depositCalldata,
IDepositSecurityModule.Signature[] calldata sortedGuardianSignatures
) external onlyDelegateCall {
if (IERC20(weth).balanceOf(address(this)) < amount)
revert NotEnoughWeth();
uint256 unfinalizedStETH = withdrawalQueue.unfinalizedStETH();
uint256 bufferedEther = ISteth(steth).getBufferedEther();
if (bufferedEther < unfinalizedStETH)//1
revert InvalidWithdrawalQueueState();
_wethToWSteth(amount);//2 - this increases the bufferedEther
depositSecurityModule.depositBufferedEther(
blockNumber,
blockHash,
depositRoot,
stakingModuleId,
nonce,
depositCalldata,
sortedGuardianSignatures
);
}
function _wethToWSteth(uint256 amount) private {
IWeth(weth).withdraw(amount);
ISteth(steth).submit{value: amount}(address(0));
IERC20(steth).safeIncreaseAllowance(address(wsteth), amount);
IWSteth(wsteth).wrap(amount);
} |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
Could please elaborate on what is |
|
if it increases stETH -> increasing |
This comment was marked as off-topic.
This comment was marked as off-topic.
The intention here is to not make a deposit just so that it will pass without any reverts in the lido side. The protocol wants to allocate their deposits specifically to Obol validators. If the currently buffered ETH is less than unfinalizedStETH, the deposits of mellow will be used to settle the unfinalizedStETH, hence why the check is implemented |
@10xhash as I understand from your comment, if the unfinalizedStETH is bigger than buffered ETH, then the deposit will not go to the Obol Validators. But the goal of the protocol (or idea) is to deposit to them, so they don't want deposits to go through if it doesn't go to Obol Validators. I know it may look silly to clarify this part, but just want to confirm. Could you also share where you've got this info from? btw, I've hidden one comment that was a bit aggressive and disrespectful. |
Yes |
Thank you, but I think there was misunderstanding, excuse me for poor question phrasing, I mean about the info that Mellow protocol wants to deposit only yo Obol validators? @10xhash |
The strategy is named SimpleDVTStakingStrategy, the module is named Obol, deposits are made with moduleId set to the SimpleDVTModule of lido, discord message and the above check itself |
Per my understanding of the Lido there can't be a scenario, which makes this Module's deposit to be allocated to another validator. |
As I understand the problem is not that the funds will be lost. The problem is that the protocol wants to deposit the funds to Obol validators, but if a portion of funds is used to cover the withdrawals from another validator, then the withdrawer will receive that portion of ETH and the Mellow's funds will be partially allocated to another validator, not Obol. This partially answers my question at #260, @10xhash could I flag if this indeed what you meant? |
The whole discussion here was about the same as in #260, not what is actually stated in the report. Please read the report again and express a judging opinion, based on it and this #213 (comment), because the escalation is going in the wrong direction and nothing about the issue was commented. |
Yes, general idea is correct but you may be misunderstanding how withdrawals work. |
Thank you for clarification on that part. Excuse me for the confusion and for reflecting more on the discussion rather than the report and the issue. Firstly, as we see it's intended the protocol wants to allocate their ETH specifically to Obol validators and doesn't want their ETH to be used for finalising withdrawals. Therefore, there's a special check in place to prevent such a scenario from happening, i.e. checking for buffered ETH being larger than unfinalised ETH or revert. As I was informed, the defending side wants to get confirmation from the Lido team, that the scenario expressed in the report is viable. I agree the following scenario is possible and can prevent deposits:
Indeed, in that case, the deposit would revert. But it works as intended, in this case, 5 ETH from the deposit would be allocated to settling withdrawals, which is not the goal. Moreover, this DOS, and I believe it would be the denial of service on deposits, doesn't lead to loss of funds, lock of funds for >= 7 days or fails the time-sensitive functions. Hence, I believe this report should remain invalid since it's a design decision and the impact doesn't qualify for M impact. If any of my assumptions are incorrect or you have additional information, please correct me and provide the info. If not, then I'm planning to reject the escalation and leave the issue as it is. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
scammed
Medium
StakingModule::convertAndDeposit wrong buffered and unfinalized check can prevent some deposits
Summary
The unnecessary check performed in
StakingModule::convertAndDeposit
will prevent new deposits in Lido whenWithdrawalQueue::unfinalizedStETH
is bigger thanLido::getBufferedEther
.Vulnerability Detail
In order to understand the issue with this superfluous check we should take a look at
stETH::submit
:As we can see it increases the
bufferedEther
when newETH
is being staked.Indeed the exact same check is performed inside
depositSecurityModule::depositBufferedEther
, as it ends up calling the following functions fromstETH
:Now, knowing that
stETH::submit
increasesbufferedEther
let’s consider the following scenario:bufferedEther
= 95 ETHunfinalizedStETH
= 100 ETHStakingModule::convertAndDeposit
with 10ETH
:In this configuration all Lido functions should have passed successfully, since first
ETH
is submitted and thendepositBufferedEther
is called that will use the most recentbufferedEther
which will become 105ETH
and 100unfinalizedStETH
.Instead the tx will revert unfairly preventing Vault from depositing into Lido, as the
bufferedEther
will be before staking and will remain at 95 and theunfinalizedStETH
= 100.Impact
StakingModule
from depositing into LidoCode Snippet
https://github.com/mellow-finance/mellow-lrt/blob/dev-symbiotic-deploy/src/modules/obol/StakingModule.sol#L48-L82
Tool used
Manual Review
Recommendation
Remove the check completely or perform it after
_wethToWSteth
is executed and thebufferedEther
is being updatedThe text was updated successfully, but these errors were encountered: