# Beacon chain withdrawals that occur at lastwithdrawaltimestamp will be lost

EigenPod's activateRestaking sets mostRecentWithdrawalTimestamp to block.timestamp, so a beacon-chain withdrawal landing in that same block becomes permanently unprovable and lost.

- Payout: Contest reward
- Severity: high
- Program: Eigenlayer
- Credited: hash
- Disclosed: 2024-04-05
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_eigenlayer_mar2024.pdf#3.1.1
- Library page: https://bugbountylibrary.com/r/cantina%3Aeigenlayer_mar2024%3A3.1.1
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** EigenPod.sol restaking activation and withdrawal proof verification
**Root cause:** activateRestaking sets mostRecentWithdrawalTimestamp = block.timestamp while EIP-4895 beacon withdrawals execute after user transactions, and verifyAndProcessWithdrawals requires timestamp > mostRecentWithdrawalTimestamp, so a withdrawal at exactly that timestamp can never be proven.
**Steps:**
1. Have a 32 ETH beacon chain withdrawal scheduled at time t.
2. Call `activateRestaking()` in the same block/timestamp t; `_processWithdrawalBeforeRestaking` sets `mostRecentWithdrawalTimestamp = uint32(block.timestamp)` and sends only current `address(this).balance`.
3. Beacon withdrawal executes after user txs per EIP-4895, so the 32 ETH arrives after the balance snapshot.
4. Call `verifyAndProcessWithdrawals` with the withdrawal proof for timestamp t; it reverts on `timestamp > mostRecentWithdrawalTimestamp`.
5. ETH is stranded in the pod with no valid proof path.
**How found:** Code reading of the timestamp invariant: noticed `_processWithdrawalBeforeRestaking` snapshots block.timestamp and the strict `>` check in proofIsForValidTimestamp, then reasoned about EIP-4895 ordering where beacon withdrawals settle after user transactions in the same block.
**Exploitation:** Not an attacker-driven exploit; a user self-triggers loss by calling activateRestaking in the same block their beacon withdrawal executes, permanently stranding the withdrawn ETH in the pod.
**Insight:** When a contract snapshots block.timestamp as a watermark and later requires strictly greater timestamps for proofs, check same-block ordering assumptions (EIP-4895 withdrawals, oracle updates, rebases) that can land exactly on the watermark and become unprovable.
