-
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
hash - Predefined amount parameter can challange allocation to Obol validators #260
Comments
ratiosX96Value
is rounded down
The protocol team fixed this issue in the following PRs/commits: |
Escalate. this is low / info finding. we are calling this function from SimpleDVTStakingStrategy.sol function convertAndDeposit(
uint256 amount,
uint256 blockNumber,
bytes32 blockHash,
bytes32 depositRoot,
uint256 nonce,
bytes calldata depositCalldata,
IDepositSecurityModule.Signature[] calldata sortedGuardianSignatures
) external returns (bool success) {
(success, ) = vault.delegateCall(
address(stakingModule),
abi.encodeWithSelector(
IStakingModule.convertAndDeposit.selector,
amount,
blockNumber,
blockHash,
depositRoot,
nonce,
depositCalldata,
sortedGuardianSignatures
)
);
emit ConvertAndDeposit(success, msg.sender);
}
the parameter sortedGuardianSignatures ensure that this function cannot be called permissionlessly. then this is issue is only called by admin and admin is consider trusted. |
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. |
@10xhash do you have any counterarguments? |
Yes
|
https://docs.lido.fi/contracts/deposit-security-module/ LIDO guaridan set up rigorous measure to prevent deposit related frontrunning
user cannot spoof the stakingModuleId as well, which is used to identify the staking module party. also I think the amount parameter just convert WETH to wstETH and not related to deposit request. also look at the recommendation from original report
I mean we should assume the LIDO behave correctly, otherwise, we can say all staked ETH are lost... |
This comment clearly lacks in understanding the mentioned issue and my earlier comment The front-running that is in discussion here is the ability of an user to front run the I agree and I have not mentioned this ever
The entire deposit request and allocation to obol validators is dependent on this amount ie. how much
LIDO is never assumed to behave incorrectly in the report. The only thing mentioned as a limitation on the lido side is regarding the staking module containing both ssv and obol. The main issue mentioned is the incorrectness in the depositing amount which would have to be calculated on-chain inside the function call to be correct and not calculated offchain
|
@10xhash as I understand the problem here is the following:
Is the scenario above correct? |
No. The eth:steth ratio doesn't change. stETH is always considered 1:1 with eth for deposits (steth balance and not the shares amount) The issue revolves around how the deposits to beacon chain from lido work. With an example: |
I agree with the comment above and believe the issue should remain as it is. Planning to reject the escalation. |
This answer has nothing valid with how Lido and stETH is working. Each deposit to beacon chain is when 32 eth are collected (deposited) from numerous deposits to Lido for this staking module and then will be deposited to the beacon chain. There is no thing like "if there are 2 eth and you deposit 31 eth, 1 eth will be lost" - No, 32 eth will be deposited to beacon chain and the rest 1 eth will stay for the next stack of 32 for this particular Staking Module. Each beacon chain deposit is when 32 eth have been collected (deposited) from multiple Lido deposits for this staking module and will then be deposited into the beacon chain. There is no such thing as "if there are 2 eth and you deposit 31 eth, 1 eth will be lost" - No, 32 eth will be deposited into the beacon chain and the remaining 1 eth will be left for the next stack of 32 for that particular Staking Module.
The idea is to deposit whatever value for this staking module that is associated with the stakingModuleId and when the deposit value stacks up to 32 to deposit it into the beacon chain, if you deposit 35 eth it will deposit once (32 eth ) in the beacon chain and the remaining 3 will remain for the next round. Here is the code where the actual deposit happens, there is no chance of losing eth or someone to allocate on your behalf. here if the stake is less than 32 eth the number of deposits is 0 and no chain beacon deposit will be made The only thing @10xhash has texting is that if 32 eth are not collected in Lido, no Obol deposit will happen, which is true, but that's how it should work. Lido deposits are not strict always deposit 32 eth to them and then to Obol, the values just accumulate. |
I don't see where @10xhash said anything like
Again I disagree with what you believe hash said. I believe the meaning is that the ETH deposited to Lido won't be deposited and will be waiting for other deposits to stack to 32 ETH OR can be used to payout the withdrawals. The second is the problem, the protocol wants to deposit the funds to Obol validators, while this report shows how it can be used for withdrawals instead of going to Obol validators (e.g. if there are 0 ETH and you deposit 31 ETH, all that 31 ETH can be used for withdrawals, or if there are 2 ETH and you deposit 31 ETH, 1 will be left over for the next 32 ETH stack or will be used for withdrawals). So I believe Hash described everything correctly but not in the best way. But the report shows how the deposits from Mellow into Lido may not go to Obol validators in that deposit and can be used for withdrawals, i.e. not allocated to Obol validators. But @10xhash I've got a question for you. Let's take an example of 2 ETH being in the stack and Mellow depositing 31 ETH. 1 ETH will be leftover waiting for the next round. In the meantime, there's a 1 ETH withdrawal, so that 1 ETH from Mellow will be used for withdrawals. In that case, it doesn't mean that Mellow lost that 1 ETH and they will be able to withdraw 31 ETH if they want and technically Obol validators do get this 1 ETH, cause basically the withdrawer received their 1 ETH (leftover from the deposit) from the buffer, but their 1 stETH was kept for Obol validators. Is it correct? Because, otherwise, if this 1 ETH was sent to the withdrawer and their 1 stETH was unstaked, then Mellow would basically lose that 1 ETH and wouldn't be able to retrieve it. |
Yes, you are right. That's exactly what I'm explaining.
They will be queued for this StakingModule due to the
This is incorrect, again because of the You can read this conversation with me and the Lido team, they express exactly that. - https://discord.com/channels/761182643269795850/773584934619185154/1265770650417500317 |
I am not sure what is meant by
User's only receive ETH if they forego the stETH. Nobody (including mellow) (in general sense) would be loosing their eth by depositing because for every eth deposit made, they will be receiving 1:1 steth which can be redeemed for the underlying amount of eth at any later point of time. The user is able to withdraw ETH now because he holds steth (obtained by making ETH deposit some time back). But here the 1 ETH (which could've been allocated to obol) can end up being used for withdrawals as you have correctly mentioned |
And that is until, new 32 eth are collected to go to Obol, thus, you also confirm that there is no issue with this, not the least bit of an impact. |
Thank you for the clarification. Additionally thinking about this issue, we can see that Mellow will not lose tokens, and will not encounter a lock of funds. The impact here is that Mellow might allocate funds to other validators and not Obol. I believe it doesn't qualify for medium severity and indeed should be low. Additionally, this intention is not mentioned in the README. Hence, planning to accept the escalation and invalidate the report, since allocating funds to other validators is not sufficient for M. |
/**
* @notice Converts and deposits into specific staking module.
* @param amount The amount of tokens to convert and deposit.
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)
revert InvalidWithdrawalQueueState();
function processWithdrawals(
address[] memory users,
uint256 amountForStake
) external returns (bool[] memory statuses) {
.....
statuses = vault.processWithdrawals(users);
address wsteth = stakingModule.wsteth();
uint256 balance = IERC20(wsteth).balanceOf(address(vault));
if (balance > maxAllowedRemainder) revert LimitOverflow();
} |
I consider the design and the intention of the protocol. I didn't say in any way that you're incorrect or the protocol intention is not what you describe.
Again, I agree that the intention is clear and the protocol wants to deposit to specific validators. And for points 3 and 4 again, I don't mean to say it's not the intention to allocate deposits to obol validators. What I mean is that I don't see this issue qualifying for Medium severity, it doesn't cause loss of funds to Mellow protocol and users and doesn't break core contract functionality, rendering the contract useless:
Of course, if my assumption is incorrect, please let me know. But the current decision remains the same, planning to accept the escalation and invalidate the issue. |
then the action should be planning to accept the escalation and invalidate the report.. not sure why even with the comments above, the decision changes to
|
That would be a typo and the intention of his message is to not have this as a valid med |
It breaks the core contract functionality. The whole point of the entire staking module is to allocate specifically to obol validators and this breaks it. The ability of the user to change the amount to whatever he wants can make the strategy useless |
As you quoted in the previous comment, the documentation of the That is why I believe the contract is not useless. Of course, you can correct me. But, for now, the decision remains the same, planning to accept the escalation and invalidate the report. |
It doesn't deposit the amount into the specific staking module. If your understanding is based on some of the above comments like |
Then I admit a mistake on my side and misunderstanding.
I understand it's incorrect and it wasn't what I thought. I misunderstood what you mean by the staking module. To finally clarify, Mellow has The problem is in the first since it doesn't ensure enough of the funds are indeed deposited into that specific staking module and funds can be sent to another staking module. The issue is that the |
Yes. Not just pre-calculated before, a user has the ability to front-run and change the amount to whatever they want. And apart from deposits, withdrawals can also change the correctness of the |
In that sense, I again want to admin my mistake and misunderstanding. Hash is correct, indeed this vulnerability leads to the entire strategy, hence, the
Planning to reject the escalation and leave the issue as it is. |
I think you're missing the fact that
|
Please see the earlier message here #260 (comment) and also verify that the |
Yep, even if it's pre-calculated correctly, at the time of the transaction being executed, the Hence, the private transactions won't mitigate this issue. The decision remains the same, planning to reject the escalation and leave the issue as it is. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
Fixed |
The Lead Senior Watson signed off on the fix. |
hash
High
Predefined amount parameter can challange allocation to Obol validators
Summary
Deposits need not be allocated to Obol validators
Vulnerability Detail
In
StakingModule
, the amount to be deposited in Lido is supposed to go to the Obol validators. But the only check kept for this is that thestakingModuleId
is set toSimpleDVT
module id in Lido andunfinalizedstETH <= bufferedETH
link
There is no enforcement/checks kept on the
amount
param. It is possible to pass in any value for theamount
param or the buffered ETH amount in lido to change from the value using which the amount was calculated before the call due to other deposits . This allows for scenarios where theamount
is not deposited into validators at all (not in multiples of 32 eth), could be shared with other staking modules or could result in reverts due to the max limit restriction in the lido side. There is also no enforcement that the deposits made would be allocated to Obol validators itself since the simpleDVT staking module in Lido also contains SSV operatorsImpact
The amount to be staked for obol validators can be assigned to other operators
Code Snippet
Tool used
Manual Review
Recommendation
Consult with lido team to make it possible to deposit specifically to a certain set of operators and calculate the maximum amount depositable to that set at the instant of the call rather than a predefined value
The text was updated successfully, but these errors were encountered: