-
Notifications
You must be signed in to change notification settings - Fork 1
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
Queued withdrawals are not treated correctly when a slash occurs, leading to loss of user funds #404
Comments
Very well demonstration including the mitigation. Marking as HQ. |
0xSorryNotSorry marked the issue as high quality report |
0xSorryNotSorry marked the issue as primary issue |
Sidu28 marked the issue as disagree with severity |
We believe this is informational severity, and the suggested mitigation would result in unrecoverable/burnt funds. Agreed the function in question currently only fully slashes QueuedWithdrawals, by design. We could consider adding more complex functionality to this function in the future. |
@Sidu28 Is it realistic for a partial withdrawal to be necessary at this time? |
Based on our intended usage, this is a wholly unnecessary feature at this time. |
Judging the finding boils down to whether it would be reasonable for partial slashing to occur in the currently coded way And whether the Admin Privileges were disclosed beforehand See Docs here: 3. *Services Slash Only Objectively Attributable Behavior*: <br/>
EigenLayer is built to support slashing as a result of an on-chain-checkable, objectively attributable action. An AVS SHOULD slash in EigenLayer only for such provable and attributable behavior. It is expected that operators will be very hesitant to opt-in to services that slash for other types of behavior, and other services may even choose to exclude operators who have opted-into serving one or more AVSs with such “subjective slashing conditions”, as these slashing conditions present a significant challenge for risk modeling, and may be perceived as more dangerous in general. Some examples of on-chain-checkable, objectively attributable behavior:
- double-signing a block in Ethereum, but NOT inactivity leak;
- proofs-of-custody in EigenDA, but NOT a node ceasing to serve data;
- a node in a light-node-bridge AVS signing an invalid block from another chain. In terms of the lack of functionality I will invite the Wardens to send some arguments around why this would break the functionality given the Sponsor provided alternative, this is fairly similar to how GogoPool was judge in that if a FSM is broken it may be worth raising to Med That said, currently, I believe this finding should be downgraded to QA - Low Severity |
GalloDaSballo changed the severity to QA (Quality Assurance) |
@Cyfrin lmk if you have a counter argument to the above |
While we acknowledge that slashing is performed by a trusted actor, it is essential to highlight that no documentation was provided during the auditing process regarding the handling of partial withdrawals. As auditors, we had to consider the possibility of both partial withdrawals and partial slashing, particularly when withdrawals are already queued. The sponsor has proposed fully slashing a queued withdrawal and promptly returning a portion of the slashed funds to achieve the intended objective. However, we have reservations about the feasibility of implementing and managing refunds on a large scale. Given that a substantial part of the process would occur off-chain, there exists a risk of genuine users losing funds. We would like to note that we submitted this as HIGH because it can cause a loss of user funds in a reasonable scenario. |
@hansfriese could you link me to a specific part of documentation that directly mentions partial slashing and how they are supposed to work in relation to queued withdrawals? |
While there are multiple ways to look at the finding, a few things should be considered:
If a partial withdrawal is performed, slashing all of it may be appropriate, additionally, instead of slashing the partial withdrawal, the other shares (not in the queued withdrawal) could be slashed (and they could be slashed partially via This would leave us only with a scenario in which a partial slash had to be performed on a withdrawal that was partial and the slashing would have to be partial. Meaning that while there is a reason to discuss the current design decisions, given the already known reliance on a Trusted Owner, the finding doesn't point to a specific risk For the reasons above, am going to downgrade the finding to QA |
GalloDaSballo marked the issue as grade-a |
We are grateful for your comprehensive response and the clarification provided regarding the final decision. |
Lines of code
https://github.com/code-423n4/2023-04-eigenlayer/blob/5e4872358cd2bda1936c29f460ece2308af4def6/src/contracts/core/StrategyManager.sol#L523
https://github.com/code-423n4/2023-04-eigenlayer/blob/5e4872358cd2bda1936c29f460ece2308af4def6/src/contracts/core/StrategyManager.sol#L567-L573
Vulnerability details
Description
According to the documentation, the EigenLayer protocol allows for partial slashes. If an operator is slashed, all stakers who have delegated to the operator will be subject to the same percentage slash. This means that if a delegate is slashed by$X$ %, all stakers who trusted the operator will also be slashed by $X$ %. However, there is an issue with queued withdrawals during partial slashes. Currently, the implementation reduces the queued withdrawal to 100%, resulting in a loss of funds for the user.
Impact
Despite intending to implement a partial slash, the current issue has resulted in the complete cancellation of queued withdrawals and the loss of funds for the user, therefore we evaluate the impact of this issue as HIGH.
Proof of Concept
The scenario below explains the issue:
Context:
Scenario:
queueWithdrawal
function, which sets her shares in thestakerStrategyShares
mapping to 0.StategyManager::slashShares
function.StategyManager::slashShares
function does not make sense, as thestakerStrategyShares
element in the mapping was previously set to 0. Doing so would cause theStategyManager::slashShares
transaction to revert.StategyManager
owner calls theStategyManager::slashQueuedWithdrawals
function to slash Alice's queued withdrawal. Alice should only be slashed for 30% of her shares in the strategy. BUT, the amount to withdraw from the strategy corresponds to all the shares in thequeuedWithdrawal.share[i]
element, which results in Alice being fully slashed.Recommended Mitigation steps
The issue stems from the failure to account for the percentage of shares of the operator that are cut during a slash.
We propose two options to mitigate this issue:
Option A
Disallow partial slashes and only allow full slashes.
Option B
When an operator is slashed, take into account the percentage that is slashed and slash the queued withdrawals accordingly.
This can be done by including the amount of shares to slash in the function
StrategyManager::slashQueuedWithdrawal
.Assessed type
Other
The text was updated successfully, but these errors were encountered: