EIP-8148 Validator-customized sweep threshold (Custom sweep threshold for validators)
Hegota Considered for Inclusion · Consensus & staking · EIP status Draft · created 2026-02-05
Lets validators using compounding withdrawal credentials (0x02) set for themselves, between 32 ETH and 2,048 ETH, the balance above which rewards are automatically swept to the withdrawal address.
Why it is needed
Today, a compounding (0x02) validator has its excess moved automatically to the withdrawal address only once its balance exceeds 2,048 ETH. The source explains that many validators find this threshold too high, so the share converting to 0x02 is very low. The alternative, partial withdrawals, requires the user to send a transaction themselves and shares the regular exit queue, so the time from request to processing is hard to predict. The source cites the surge in the exit queue in October 2025. For example, a 128 ETH validator earns about 0.07 ETH in rewards per week, and sending a partial withdrawal transaction every time to collect this small amount is impractical. There is also the burden of watching the balance and making the request manually. This proposal lets a validator set its desired threshold once, after which rewards accumulated above it are withdrawn automatically on the sweep cycle. Default behavior is unchanged, and it is an opt-in feature for validators who want it.
What changes
Today
- A 0x02 validator's rewards are not withdrawn automatically until the balance exceeds 2,048 ETH.
- To take out rewards before that, it must send a partial withdrawal transaction itself and wait in the exit queue.
- Bytes 1 to 11 of the withdrawal credentials are unused and empty.
- To have automatic withdrawals at 32 ETH, a validator must keep 0x01 credentials.
After EIP-8148
- A validator can set the automatic withdrawal threshold between 32 ETH and 2,048 ETH in 1 ETH steps.
- After one request is sent from the withdrawal address, the amount above the threshold is withdrawn automatically on every sweep cycle.
- The threshold is stored in bytes 1 to 2 of the withdrawal credentials, so no new field is added to the beacon state.
- Setting the threshold to 32 ETH makes it behave like a 0x01 validator, so 0x02 credentials cover every case.
Who is affected
- Validators and solo stakers: A validator can switch to 0x02 and receive rewards automatically at its chosen balance without waiting for 2,048 ETH. The threshold cannot be set lower than the current balance.
- Staking protocols and node operators: Operations that repeatedly sent partial withdrawal transactions can be replaced with a single request. If the withdrawal address is a contract, only that contract can change the threshold.
- Client teams: The execution layer must implement a new system contract and the 0x05 request type. The consensus layer must implement a new list in ExecutionRequests and the threshold handling logic.
- Apps that inspect withdrawal credentials: EIP-4788 proof verifiers and others that compare the full 32 bytes must be changed to compare only the prefix and the execution address.
In depth
Execution layer request format and contract input
This EIP adds the EIP-7685 request type SWEEP_THRESHOLD_REQUEST_TYPE(0x05). A request has three fields: source_address(Bytes20), validator_pubkey(Bytes48), and threshold(uint64, in Gwei). When exactly 56 bytes are sent to the dedicated contract SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, bytes 0:48 are read as the validator public key and bytes 48:56 as a big-endian uint64 threshold. The contract checks that msg.value is at least get_fee() and increments the block request count by 1. Three queue slots store msg.sender, the first 32 bytes of the public key, and the last 16 bytes of the public key together with the threshold. It then emits the 76 bytes source_address(20) ++ validator_pubkey(48) ++ threshold(8) with LOG0. Watch the endianness. The threshold in the input and in the log is big-endian, but the value returned by the system call and the EIP-7685 encoding are little-endian.
Fees and per-block processing limit
The request fee is determined the same way as in EIP-7002. MIN_SET_SWEEP_THRESHOLD_REQUEST_FEE is 1, TARGET_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK is 2, and SET_SWEEP_THRESHOLD_REQUEST_FEE_UPDATE_FRACTION is 17. The fee is computed by passing the cumulative excess into fake_exponential. When a block's request count exceeds the target of 2, the excess accumulates and the fee rises. When it falls below the target, the fee drops. The number of requests dequeued in one block is capped at MAX_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK, which is 16. If the input length is 0, the call is handled as a query that returns the current fee. If ETH is sent along with it, the call reverts to prevent loss of funds. Before the first system call, the excess slot holds EXCESS_INHIBITOR(2**256-1), so get_fee() fails.
End-of-block system call rules
From FORK_BLOCK, after transaction processing finishes in every block, SYSTEM_ADDRESS(0xfffffffffffffffffffffffffffffffffffffffe) calls the contract with empty calldata. The contract dequeues requests from the queue (dequeue_set_sweep_threshold_requests), updates the excess (update_excess_set_sweep_threshold_requests), and resets the block request count to 0. The dequeued requests are serialized with SSZ and returned as concatenated bytes, and they must appear in the EIP-7685 request list in that order. This call receives its own SYSTEM_TRANSACTION_GAS of 30_000_000 gas and is not subject to the transaction gas cap of EIP-7825. The gas used does not count toward the block gas usage, and there is no EIP-1559 burn. If the contract address has no code or the call fails, the block is invalid. Clients that serve EIP-7910 eth_config must list this contract in systemContracts under the key SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS.
Storing the threshold in withdrawal credentials
The consensus layer stores the threshold inside the 0x02 withdrawal credentials without adding a field to BeaconState or Validator. Byte 0 is COMPOUNDING_WITHDRAWAL_PREFIX(0x02), bytes 1 to 2 are the threshold as a little-endian uint16 in units of EFFECTIVE_BALANCE_INCREMENT, bytes 3 to 11 are reserved, and bytes 12 to 31 are the execution address. The constant SWEEP_THRESHOLD_CREDENTIAL_OFFSET is 1 and SWEEP_THRESHOLD_CREDENTIAL_LENGTH is 2. If the threshold equals MAX_EFFECTIVE_BALANCE_ELECTRA, it is stored as 0, and an out-of-range value is read as the default. For example, 0x02e803... is 1,000 ETH. Every place in the sweep and effective balance calculations that used get_max_effective_balance now uses this threshold. The threshold is therefore both the automatic withdrawal threshold and the effective balance cap. The rationale section explains that adding an 8-byte list per validator to BeaconState would grow it by as much as balances, while the credentials already have 11 free bytes and switch_to_compounding_validator already has a path that rewrites the credentials, so the threshold was placed there. Storing the maximum as 0 gives every threshold a single encoding, and a validator can also revert to the original credentials.
Request acceptance conditions and processing time
A threshold change request is accepted only when all of the following conditions hold. source_address must be the validator's execution address, and the target must be a compounding withdrawal validator that is not exiting. The threshold must be a multiple of EFFECTIVE_BALANCE_INCREMENT, at least MIN_ACTIVATION_BALANCE and at most MAX_EFFECTIVE_BALANCE_ELECTRA, and it must not be lower than the validator's current balance. The reason for not allowing a threshold below the current balance is to prevent this feature from triggering an immediate withdrawal. To get a lower threshold, first reduce the balance with a partial withdrawal and then submit the request. A new 0x02 validator takes the threshold from the credentials of the deposit that created it (clearing it if out of range), and its initial effective balance is capped at that threshold. switch_to_compounding_validator and the fork transition clear bytes 1 to 2, so existing validators and converted validators start from the default. Unlike a partial withdrawal, a request is processed as soon as it is dequeued from the execution layer, without a consensus layer queue. A list of SetSweepThresholdRequest is added to ExecutionRequests, with at most MAX_SET_SWEEP_THRESHOLD_REQUESTS_PER_PAYLOAD (16) per payload.
Compatibility, queue halt mechanism, security
The original text states that this is not backward compatible because the block structure and validation rules change, but that user activity and experience are unaffected. Because a new type is added to ExecutionRequests, clients must align execution_requests_root validation at the fork. Changing the threshold alters bytes 1 to 2 of the credentials, so apps such as EIP-4788 proof verifiers that compare all 32 bytes must compare only the prefix and the execution address. The change can only be requested by the withdrawal address, so it is optional. Deposits made with tools from before this EIP have those bytes set to 0, so they receive the default. If a system call arrives with anything other than empty calldata, EXCESS_INHIBITOR is placed in the excess slot to halt the queue. In this EIP every system call has empty calldata, so this path is unreachable. It is a safeguard so that, when the contract is retired later, requests and fees do not keep piling up in a queue that never drains after the protocol stops calling it. The security considerations, such as fee overpayment, system call failure, and empty code, are stated to be the same as in EIP-7002.
Current status and fork decision
This EIP is in Draft status and may still change. The contract address SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS and the deployment transaction are left as TBD in the original text, and the full consensus layer specification is separate in specs/_features/eip8148/beacon-chain.md. In the core developer calls, it was discussed at 09.03 ACDC #186 with no decision, and at 10.29 ACDC #190 it was set to CFI for the Hegotá fork. CFI stands for Considered for Inclusion, meaning it is being considered as a candidate for inclusion in the fork.