EIP-8363: Tapered Issuance Burn

Here is a mockup of an EIP based on this idea that Grok threw together, including the changes to the python CL spec:


eip:

title: Staking Cap Deposit Burn
description: Cap the growth of staked ETH by burning an increasing portion of new deposits once total active stake exceeds 50 million ETH.
author: <Your Name (@yourhandle)>
discussions-to:
status: Draft
type: Standards Track
category: Core
created: 2026-08-08
requires: 6110, 7251

Abstract

This EIP introduces a hard economic cap on the growth of staked ETH. Once the total active balance on the beacon chain reaches or exceeds 50 million ETH, an increasing fraction of every subsequent deposit is permanently burned on the consensus layer. The burn fraction scales according to the following anchors:

  • 0 % at ≤ 50 000 000 ETH
  • 10 % at 51 000 000 ETH
  • 90 % at 52 000 000 ETH
  • 99 % at 53 000 000 ETH
  • 99.9999 % at ≥ 54 000 000 ETH

The burned portion is never credited to any validator balance and is therefore removed from the total ETH supply. The change is purely consensus-layer and is activated by a hard fork.

Motivation

Unconstrained growth of the staked supply creates several long-term risks:

  • Diminishing marginal security returns while issuance continues.
  • Increasing centralisation pressure on liquid-staking tokens and large operators.
  • Reduced circulating supply available for DeFi, payments and other economic activity.
  • Potential for a “too-big-to-fail” staking industry.

By imposing a smoothly increasing burn on new deposits above a clear threshold, the protocol creates a market-driven ceiling on stake growth without altering existing validator rewards, penalties or withdrawal mechanics. The chosen curve is intentionally steep so that additional staking becomes economically unattractive well before the absolute technical limits of the protocol are reached.

Specification

Constants

Add the following constants to the consensus-layer preset:

# Gwei values for the staking-cap burn curve
STAKING_CAP_START   = Gwei(50_000_000 * 109)   # 50 M ETH → 0 %
STAKING_CAP_10PCT   = Gwei(51_000_000 * 109)   # 51 M ETH → 10 %
STAKING_CAP_90PCT   = Gwei(52_000_000 * 109)   # 52 M ETH → 90 %
STAKING_CAP_99PCT   = Gwei(53_000_000 * 109)   # 53 M ETH → 99 %
STAKING_CAP_999999  = Gwei(54_000_000 * 10**9)   # 54 M ETH → 99.9999 %

# Maximum burn expressed in parts-per-million
MAX_DEPOSIT_BURN_PPM = uint64(999_999)           # 99.9999 %


#New helpers

def compute_deposit_burn_ppm(total_staked: Gwei) -> uint64:
    """
    Return the fraction of a deposit that must be burned, expressed in
    parts-per-million (0 … 1_000_000).

    The function implements a piecewise-linear curve that exactly matches
    the anchors defined in the EIP.
    """
    if total_staked <= STAKING_CAP_START:
        return uint64(0)

    if total_staked <= STAKING_CAP_10PCT:
        # 0 % → 10 %
        progress = (total_staked - STAKING_CAP_START) * 100_000 // (STAKING_CAP_10PCT - STAKING_CAP_START)
        return progress

    if total_staked <= STAKING_CAP_90PCT:
        # 10 % → 90 %
        progress = (total_staked - STAKING_CAP_10PCT) * 800_000 // (STAKING_CAP_90PCT - STAKING_CAP_10PCT)
        return uint64(100_000 + progress)

    if total_staked <= STAKING_CAP_99PCT:
        # 90 % → 99 %
        progress = (total_staked - STAKING_CAP_90PCT) * 90_000 // (STAKING_CAP_99PCT - STAKING_CAP_90PCT)
        return uint64(900_000 + progress)

    if total_staked <= STAKING_CAP_999999:
        # 99 % → 99.9999 %
        progress = (total_staked - STAKING_CAP_99PCT) * 9_999 // (STAKING_CAP_999999 - STAKING_CAP_99PCT)
        return uint64(990_000 + progress)

    return MAX_DEPOSIT_BURN_PPM


def apply_deposit_burn(state: BeaconState, amount: Gwei) -> Gwei:
    """
    Compute the portion of amount that may be credited after the
    staking-cap burn.  The remainder is permanently removed from supply.
    """
    total_staked = get_total_active_balance(state)
    burn_ppm = compute_deposit_burn_ppm(total_staked)
    burned = amount * burn_ppm // 1_000_000
    return amount - burned


#Modified apply_deposit

def apply_deposit(
    state: BeaconState,
    pubkey: BLSPubkey,
    withdrawal_credentials: Bytes32,
    amount: Gwei,
    signature: BLSSignature,
) -> None:
    # Signature verification continues to use the original deposit amount
    if not is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature):
        return

    # Apply the staking-cap burn
    credited_amount = apply_deposit_burn(state, amount)

    validator_pubkeys = [v.pubkey for v in state.validators]
    if pubkey not in validator_pubkeys:
        # Existing Electra behaviour – create validator with zero balance
        add_validator_to_registry(state, pubkey, withdrawal_credentials, Gwei(0))

    # Queue only the credited amount
    state.pending_deposits.append(
        PendingDeposit(
            pubkey=pubkey,
            withdrawal_credentials=withdrawal_credentials,
            amount=credited_amount,
            signature=signature,
            slot=GENESIS_SLOT,          # or state.slot for deposit-request path
        )
    )

#Modified apply_pending_deposit


def apply_pending_deposit(state: BeaconState, deposit: PendingDeposit) -> None:
    """
    Apply a pending deposit.  deposit.amount has already been reduced
    by the staking-cap burn when the PendingDeposit was created.
    """
    validator_pubkeys = [v.pubkey for v in state.validators]
    if deposit.pubkey not in validator_pubkeys:
        if is_valid_deposit_signature(
            deposit.pubkey,
            deposit.withdrawal_credentials,
            deposit.amount,
            deposit.signature,
        ):
            add_validator_to_registry(
                state,
                deposit.pubkey,
                deposit.withdrawal_credentials,
                deposit.amount,
            )
    else:
        index = ValidatorIndex(validator_pubkeys.index(deposit.pubkey))
        increase_balance(state, index, deposit.amount)


Unchanged functionsprocess_deposit, process_deposit_request and process_pending_deposits continue to call the modified apply_deposit / apply_pending_deposit helpers and require no further changes.RationaleMetric: get_total_active_balance is already the canonical measure of economic security used for rewards, penalties and finality. Using it keeps the burn aligned with the quantity that actually secures the chain.
Burn location: Performing the burn when a deposit is first accepted (inside apply_deposit) guarantees that the pending-deposit queue never contains amounts that will later be partially burned, simplifying accounting.
Signature: The BLS proof-of-possession remains over the original amount supplied by the depositor, preserving the security properties of the deposit contract and EIP-6110 requests.
Curve shape: The piecewise-linear interpolation is simple, fully deterministic and exactly matches the four publicly stated anchors. A future hard fork may replace it with a smoother closed-form function if desired.
No changes to rewards or withdrawals: Existing validators continue to earn and withdraw exactly as before; only the marginal cost of adding new stake is increased.

Backwards Compatibility

This EIP requires a hard fork. After activation:Clients that have not upgraded will reject blocks containing the new deposit-processing logic (or will credit the full amount, causing a consensus split).
All existing validator balances, pending deposits created before the fork, and withdrawal credentials remain valid.
The deposit contract on the execution layer is untouched.

Test CasesReference tests should cover at least the following scenarios (all amounts in ETH for readability):Total active balance
Deposit size
Expected credited
Expected burned
49 999 999
32
32
0
50 500 000
32
28.8
3.2
51 500 000
32
16
16
52 500 000
32
3.2
28.8
53 500 000
32
0.032
31.968
55 000 000
32
0.000032
31.999968
52 000 000
2048
204.8
1843.2

Additional tests must verify:Sequential deposits inside the same block/epoch update the total correctly.
Top-ups to existing validators are burned according to the same curve.
Signature verification still succeeds when the original amount is used.
Genesis and pre-fork pending deposits are unaffected.

Security ConsiderationsConsensus safety: The burn is a pure function of already-finalised state (get_total_active_balance). No new trust assumptions are introduced.
DoS / griefing: Because the burn only reduces the credited amount, an attacker cannot force other depositors to lose more than the curve already mandates. The minimum deposit size remains 1 ETH.
Supply reduction: The burned ETH is permanently removed. This is intentional and strengthens ETH’s monetary properties.
Client diversity: All consensus clients must implement identical integer arithmetic; the piecewise-linear formula is deliberately simple to minimise implementation divergence.
Activation timing: The 50 M ETH threshold is high enough that the burn will not activate immediately after the fork under current staking growth rates, giving the ecosystem time to adapt.

CopyrightCopyright and related rights waived via CC0.