EIP-7002 Fee Mechanism Analysis for RPIP-44¶
Overview¶
EIP-7002 (Execution Layer Triggerable Withdrawals) introduces a system contract that allows the execution layer to trigger validator exits. The contract uses an EIP-1559-style exponential fee mechanism to rate-limit withdrawal requests. This document analyses the fee dynamics and their ramifications for Rocket Pool's RPIP-44 (EL Triggerable Exits).
How the fee mechanism works¶
The system contract¶
EIP-7002 deploys a system contract at 0x00000961Ef480Eb55e80D19ad83579A64c007002. The contract accepts withdrawal requests from any caller — it does not validate withdrawal credentials on the execution layer. Instead, the consensus layer validates that the source_address (recorded as msg.sender) matches the validator's 0x01 withdrawal credential. Requests that fail this check are silently dropped.
For Rocket Pool, the megapool contract holds the withdrawal credentials and must therefore be the msg.sender.
The contract exposes two operations:
fee()— returns the current fee in wei (triggered by zero-length calldata)addWithdrawalRequest(pubkey, amount)— submits a withdrawal request (56-byte calldata), requiresmsg.value >= fee()
Fee formula¶
The fee is computed using fake_exponential, a Taylor series integer approximation of the natural exponential:
Where:
excessis a running counter of how much withdrawal request volume exceeds the target rate17is theWITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION— controls how aggressively fees respond to demand
Excess accumulation¶
The excess counter is updated once per block via a system call at block end:
The target rate is 2 requests per block. When usage exceeds 2, excess grows. When usage drops below 2, excess shrinks. The maximum number of requests dequeued per block is 16, but there is no cap on the number of requests that can be submitted in a single block — the gas limit is the only constraint.
Anti-griefing design¶
The system contract does not validate withdrawal credentials — anyone can submit requests for any pubkey, and the count (which feeds excess) increments regardless. Invalid requests are filtered later by the consensus layer but still contribute to the fee.
EIP-7002 deliberately chose this design over credential validation (which would have required cross-layer proof via EIP-4788). Instead, the exponential fee mechanism itself serves as the anti-griefing measure: an attacker who spams the queue must pay the same escalating fees as everyone else. Sustained griefing becomes exponentially expensive, making the mechanism self-correcting.
Critical property: all requests in the same block pay the same fee¶
The fee is based on excess, which only updates at block boundaries. All withdrawal requests submitted within a single block read the same excess value and therefore pay the same fee. There is no within-block fee escalation.
Fee escalation occurs between blocks as excess accumulates.
Requests required to reach fee levels¶
The excess needed for a given fee level is excess = 17 × ln(fee_in_wei). The minimum number of requests to reach that excess depends on how they are distributed over time, since 2 requests per block are absorbed by the target rate.
| Fee level | Excess needed | Min requests (1 block) | Over 10 blocks (2 min) | Over 100 blocks (20 min) | Over 1 hour (300 blocks) |
|---|---|---|---|---|---|
| 0.001 ETH | 588 | 590 | 608 | 788 | 1,188 |
| 0.01 ETH | 627 | 629 | 647 | 827 | 1,227 |
| 0.1 ETH | 666 | 668 | 686 | 866 | 1,266 |
| 0.2 ETH | 678 | 680 | 698 | 878 | 1,278 |
| 1 ETH | 705 | 707 | 725 | 905 | 1,305 |
| 10 ETH | 744 | 746 | 764 | 944 | 1,344 |
A single block can hold approximately 780 requests (via individual EOA transactions at ~46K gas each) or ~1,285 requests (via a batching contract at ~28K gas each), given a 36M gas block limit. A burst of ~680 requests in a single block would spike the fee to 0.2 ETH in the following block — but the attacker pays only 1 wei per request (the pre-spike fee) plus ~1 ETH in gas costs.
However, this spike is self-correcting: with no further above-target submissions, excess decays at 2 per block and the fee drops below 0.01 ETH within ~7 minutes. Validator exits operate on epoch timescales (6.4 minutes), so a brief fee spike can be waited out. The fee mechanism is designed to make sustained elevation expensive, not to prevent momentary spikes.
Fee dynamics under sustained load¶
Sustained max throughput (16 requests/block)¶
Starting from excess = 0 (no prior congestion), with every block containing 16 withdrawal requests:
| Block | Excess (start) | Fee per request | Block cost (16 requests) | Cumulative cost |
|---|---|---|---|---|
| 1 | 0 | 1 wei | 16 wei | 16 wei |
| 2 | 14 | 2 wei | 32 wei | 48 wei |
| 5 | 56 | 26 wei | 416 wei | 720 wei |
| 10 | 126 | 1,649 wei | 26,384 wei | 46,880 wei |
| 20 | 266 | 6.2M wei | 99.9M wei | 178M wei |
| 30 | 406 | 23.6 Gwei | 376.8 Gwei | 671.4 Gwei |
| 40 | 546 | 88.8 mETH | 0.0014 ETH | 0.0025 ETH |
| 45 | 616 | 0.0055 ETH | 0.087 ETH | 0.156 ETH |
| 50 | 686 | 0.335 ETH | 5.36 ETH | 9.55 ETH |
| 55 | 756 | 20.57 ETH | 329.18 ETH | 586.65 ETH |
| 60 | 826 | 1,263.52 ETH | 20,216 ETH | 36,029 ETH |
The exponential nature means fees are negligible for ~40 blocks, then rapidly become catastrophic. The transition from 0.01 ETH to 10 ETH per request takes only 9 blocks (~108 seconds).
Time to reach fee milestones at different sustained rates¶
| Requests/block | Net excess/block | 0.001 ETH | 0.01 ETH | 0.1 ETH | 0.2 ETH | 1 ETH | 10 ETH |
|---|---|---|---|---|---|---|---|
| 3 | 1 | 117.8 min | 125.6 min | 133.4 min | 135.8 min | 141.2 min | 149.0 min |
| 4 | 2 | 59.0 min | 63.0 min | 66.8 min | 68.0 min | 70.8 min | 74.6 min |
| 6 | 4 | 29.6 min | 31.6 min | 33.6 min | 34.2 min | 35.6 min | 37.4 min |
| 8 | 6 | 19.8 min | 21.2 min | 22.4 min | 22.8 min | 23.8 min | 25.0 min |
| 10 | 8 | 15.0 min | 16.0 min | 17.0 min | 17.2 min | 18.0 min | 18.8 min |
| 16 | 14 | 8.6 min | 9.2 min | 9.8 min | 10.0 min | 10.4 min | 11.0 min |
At modest sustained rates (3-4 requests/block), it takes over an hour to reach meaningful fee levels. Dangerous fees require sustained high throughput — a genuine market-wide exit event, not a brief spike.
Realistic Rocket Pool scenarios¶
Isolated operation (RP is the only user)¶
Starting from excess = 0, with Rocket Pool as the sole user of the withdrawal request queue:
| Validators to exit | Blocks needed | Time | Total cost | Max fee per request |
|---|---|---|---|---|
| 10 | 1 | 12s | 10 wei | 1 wei |
| 50 | 4 | 48s | 150 wei | 11 wei |
| 100 | 7 | 84s | 2,200 wei | 138 wei |
| 500 | 32 | 6.4 min | 0.002 ETH | 122 Gwei |
Finding: When acting alone from a cold start, fees are economically irrelevant even for large exit batches. Exiting 500 validators costs 0.002 ETH total.
Entering a congested queue¶
The real risk is Rocket Pool needing to trigger exits when other operators have already been saturating the queue. If excess has built up from prior activity:
| Pre-existing excess | Fee per exit | Cost for 10 exits | Fee next block |
|---|---|---|---|
| 0 | 1 wei | 10 wei | 2 wei |
| 300 | 46K wei | 461K wei | 118K wei |
| 500 | 5.9 mETH | 59.3 mETH | 15.2 mETH |
| 600 | 0.002 ETH | 0.021 ETH | 0.005 ETH |
| 625 | 0.009 ETH | 0.093 ETH | 0.024 ETH |
| 650 | 0.040 ETH | 0.403 ETH | 0.103 ETH |
| 675 | 0.175 ETH | 1.754 ETH | 0.450 ETH |
| 700 | 0.763 ETH | 7.633 ETH | 1.956 ETH |
RPIP-44 threshold breach
At excess 675, a single forced exit costs 0.175 ETH — nearly the entire RPIP-44 exit_deficit threshold of 0.2 ETH. At excess 700, it exceeds the threshold by 3.8×.
Fee cooldown¶
After a spike, excess decays by 2 per block (the target rate) when no new requests are submitted:
| Starting excess | Starting fee | Blocks to < 0.01 ETH | Blocks to baseline (1 wei) | Time to baseline |
|---|---|---|---|---|
| 300 | 46K wei | 1 | 150 | 30 min |
| 500 | 5.9 mETH | 1 | 250 | 50 min |
| 600 | 0.002 ETH | 1 | 300 | 60 min |
| 700 | 0.763 ETH | 37 | 350 | 70 min |
| 800 | 273.76 ETH | 87 | 400 | 80 min |
Fee cooldown is slow. From excess 700, it takes 70 minutes to return to baseline and 7.4 minutes to drop below 0.01 ETH. A fee spike is a sustained window, not a momentary blip.
Ramifications for RPIP-44¶
1. Fee payment source is unspecified¶
EIP-7002 requires msg.sender to match the 0x01 withdrawal credential — which is the megapool contract. The megapool must hold or receive ETH to pay the fee. RPIP-44 does not specify:
- Who bears the EIP-7002 fee
- Whether the fee is deducted from the node operator's bond/rewards
- How the fee ETH reaches the megapool at the time of the call
2. The debt mechanism is a natural fit¶
The megapool already tracks a debt variable — a running balance the node operator owes the protocol. Today it covers dissolution penalties, late notification fines, shortfalls, and MEV penalties. Debt has real enforcement:
- Blocks new validator creation (
debt > 0check innewValidator()) - Blocks bond reduction (
debt > 0check inreduceBond()) - Auto-deducted from the node operator's share during
distributeRewards()andnotifyFinalBalance() - Can be explicitly repaid via
repayDebt()
EIP-7002 fees for forced exits could be added to debt, recovered from future rewards or exit proceeds. The open question is who provides the ETH to pay the system contract immediately — debt is a future claim, but the fee must be paid in the transaction.
3. The 0.2 ETH exit deficit threshold may be insufficient¶
RPIP-44 defines exit_deficit = 0.2 ETH as the threshold for permissionless forced exits. During a congested withdrawal request queue (excess >= 675), the EIP-7002 fee alone approaches or exceeds this threshold, making forced exits economically irrational for the caller.
Recommendation: Add a fee ceiling check. If the current EIP-7002 fee exceeds a configurable threshold (e.g., 0.05 ETH), defer the forced exit. This prevents burning value during fee spikes while preserving the mechanism for normal conditions.
4. Batch exits compound cross-block costs¶
Each validator requires a separate EIP-7002 withdrawal request. If Rocket Pool needs to exit multiple validators across several blocks, each block's requests increase excess, raising fees for subsequent blocks. This cross-block escalation is modest when RP acts alone (excess grows by 14 per block at max rate) but compounds with background demand from other protocols.
5. Overpaid fees are not refunded¶
EIP-7002 explicitly states that overpaid fees are not returned. The megapool implementation must read fee() immediately before each addWithdrawalRequest call and send exactly that amount. The EIP provides a reference Solidity pattern:
uint256 fee = IWithdrawalRequest(WITHDRAWAL_REQUEST_ADDRESS).fee();
IWithdrawalRequest(WITHDRAWAL_REQUEST_ADDRESS).addWithdrawalRequest{value: fee}(pubkey);
6. Griefing vector¶
The system contract does not validate withdrawal credentials on the execution layer — any address can submit requests for any pubkey, incrementing the count and thus the excess. An attacker can spike fees with a single block of ~680 junk requests for approximately 1 ETH in gas and negligible EIP-7002 fees (all requests in the same block pay the pre-spike fee).
The EIP-7002 fee mechanism is designed to counter this through self-correction: the exponential fee makes sustained griefing prohibitively expensive (the attacker must keep paying the escalating fee), and brief spikes decay naturally. From excess 680, the fee drops below 0.01 ETH within ~37 blocks (~7.4 minutes) and returns to baseline within ~340 blocks (~68 minutes). Since validator exits operate on epoch timescales, a brief spike can be waited out by delaying the exit transaction.
Recommendations¶
-
Specify fee payment in RPIP-44: For voluntary exits, the node operator funds the fee via
msg.value. For permissionless forced exits, the caller fronts the fee, which is added to the node operator'sdebtand repaid from future rewards/exit proceeds. -
Implement a fee ceiling: The megapool's exit function should read
fee()and revert if it exceeds a configurable maximum (e.g., 0.05 ETH). This prevents economically irrational forced exits during fee spikes. -
Document cross-protocol risk: The primary fee risk to Rocket Pool is not self-inflicted but comes from market-wide exit events. Monitoring the EIP-7002 excess counter should be part of operational awareness.
-
Consider fee-aware deficit accounting: If the EIP-7002 fee is deducted from the node operator's debt, the
exit_deficitthreshold effectively shrinks. RPIP-44 could specify that the deficit threshold is net of expected fees:effective_deficit = deficit - estimated_fee.
Empirical data: mainnet fee history¶
Sampling methodology¶
The EIP-7002 system contract at 0x00000961Ef480Eb55e80D19ad83579A64c007002 was queried at 12-hour intervals (~3,600 block intervals) across the full period from Pectra activation (May 7, 2025) through to March 12, 2026 using an archive node. The fee was read by calling the contract with empty calldata, which triggers the fee() getter.
Results¶
181 samples were taken. Every single sample returned 1 wei (the minimum fee).
The excess counter has never risen above 0 at any sampled point since EIP-7002 went live on mainnet. This means withdrawal request throughput has never sustained above the target rate of 2 requests per block for any period long enough to register at 12-hour granularity.
| Period | Samples | Min fee | Max fee | Above minimum |
|---|---|---|---|---|
| Dec 2025 | 31 | 1 wei | 1 wei | 0 |
| Jan 2026 | 31 | 1 wei | 1 wei | 0 |
| Feb 2026 | 28 | 1 wei | 1 wei | 0 |
| Mar 2026 (partial) | 5 | 1 wei | 1 wei | 0 |
| Total | 181 | 1 wei | 1 wei | 0 |
Interpretation¶
The fee mechanism is functioning exactly as designed — negligible cost under normal conditions. The theoretical fee spikes analysed in this document require sustained above-target demand that has not materialised in the ~10 months since Pectra activation.
This is consistent with the current state of the validator exit queue: there has been no market-wide exit event of the scale needed to saturate the EIP-7002 withdrawal request queue. The fee risk for RPIP-44 remains real but is contingent on future black swan events (mass slashings, market crashes triggering coordinated exits, or a major staking operator winding down).
Sampling limitation
12-hour sampling could miss brief intra-day spikes where excess rose and fell back to 0 within the interval. However, given the cooldown rate of 2 per block, even a modest spike to excess 100 takes 50 blocks (10 minutes) to decay — well within detection range of more frequent monitoring. A spike significant enough to affect RPIP-44 economics (excess > 600) would take over an hour to cool down and would be captured by this sampling.
Methodology¶
Fee calculations use the exact integer fake_exponential function specified in EIP-7002, not floating-point approximations. The integer implementation matches e^(excess/17) to within 0.01% for excess values above 200. Simulations assume no concurrent requests from other protocols unless stated otherwise. Mainnet fee data was collected on March 12, 2026 via archive node RPC queries.