Closed code423n4 closed 1 year ago
It looks like it's stored in withdrawalRootPending[withdrawalRoot]
after calculateWithdrawalRoot(queuedWithdrawal);
0xSorryNotSorry marked the issue as primary issue
Indexing the events emitted in the withdrawal flow is sufficient to recreate the struct
Sidu28 marked the issue as sponsor disputed
Because this is on mainnet, indexing could also be used (theGraph supports function tracing on mainnet)
GalloDaSballo marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-04-eigenlayer/blob/main/src/contracts/core/StrategyManager.sol#L387 https://github.com/code-423n4/2023-04-eigenlayer/blob/main/src/contracts/core/StrategyManager.sol#L536
Vulnerability details
Impact
In
StrategyManager
a user can queue up withdrawal and wait for a minimum delay lag in blocktime in other to complete the withdrawal. HoweverQueuedWithdrawal
struct which is initialized inqueuedWithdrawal function
is stored in memory which is not persistent after the transaction, and it is not stored anywhere within the contract.Meanwhile this struct is used to recompute the withdrawalRoot hash in
slashQueueWithdrawal
function, which means that a slasher cannot retrieve the QueueWithdrawal struct provided by the user. In a scenerio where a malicious user who have queued up for a withdraw is to be slashed the queueWithdrawal struct cannot be retrieved which means that a queued withdrawal cannot be slashed.Proof of Concept
1) Alice stakes on Eigenlayer. 2) Alice behaved maliciously and immediately queueWithdrawal. 3) The owner/slasher attempts to slash alice queued withdrawal but cannot find the QueuedWithdrawal struct to process the slashing. 4) After the delay period alice completes her withdrawal if the entire system is not paused.
Tools Used
Manuel Review
Recommended Mitigation Steps
Add a mapping that maps a user to the
queuedWithdrawal
struct to be retrieved by a slasher by passing the user address as a key to the mapping.