| Client | Branch | Commit | Spec commit (master) |
|---|---|---|---|
| Nimbus | stable | [`0abc0dd0fc0750a8875c49089d074f7d7197b62c`](https://github.com/status-im/nimbus-eth2/tree/0abc0dd0fc0750a8875c49089d074f7d7197b62c) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |
| Nimbus | unstable | [`5babd698516450d8b8e60c2af610a5853baaa9a9`](https://github.com/status-im/nimbus-eth2/tree/5babd698516450d8b8e60c2af610a5853baaa9a9) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |
| Lodestar | unstable | [`e4b4f615e68c1a4ea7c57632e6ed8d824624573f`](https://github.com/ChainSafe/lodestar/tree/e4b4f615e68c1a4ea7c57632e6ed8d824624573f) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |
| Grandine | develop | [`52cd677117b5d93bf477fe4843148070b0303444`](https://github.com/grandinetech/grandine/tree/52cd677117b5d93bf477fe4843148070b0303444) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |
| Prysm (comparison) | develop | [`eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a`](https://github.com/OffchainLabs/prysm/tree/eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |
| Teku (comparison) | master | [`2c35574b3373cbe8ad121a768d98f066aec05b73`](https://github.com/Consensys/teku/tree/2c35574b3373cbe8ad121a768d98f066aec05b73) | `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` |

# Gloas consensus review merge 2 — cl-misc

Merged only from supplied item-nimbus, item-lodestar and item-grandine, dated 27 October 2026. No new source review or findings. Seven detailed candidates retain all six parts and known-checks; two Nimbus live-code entries remain withheld. Scope is EIPs 8282, 7688, 8045 and 8061, not the whole goal’s client matrix. All results are static; no runtime reproduction.

**Scheduled set.** The pinned meta EIP lists exactly **2780, 7688, 7708, 7732, 7778, 7843, 7928, 7954, 7976, 7981, 7997, 8024, 8037, 8038, 8045, 8061, 8246, 8282** under “Scheduled for Inclusion”. Networking 7975/8070/8136/8159/8189 and informational 7904/8261 are listed separately. Source: [eip-7773.md#L21-L55](https://github.com/ethereum/EIPs/blob/d4c575521d99ec881a444ab3af604e684b5f0743/EIPS/eip-7773.md#L21-L55). The Amsterdam implementation lists its fourteen EL EIPs, including 8282, at [__init__.py#L7-L20](https://github.com/ethereum/execution-specs/blob/7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b/src/ethereum/forks/amsterdam/__init__.py#L7-L20). The Gloas introduction identifies the CL features and the precise EIP revisions it targets: [beacon-chain.md#L165-L186](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L165-L186). Other EIPs/clients are outside this item.

The EIPs pin identifies the current document snapshot; Gloas explicitly targets these EIP revisions (EIPs have no semantic-version number):

| EIP | Current public EIP / status | EIP revision explicitly referenced by Gloas master |
|---|---|---|
| 8282 | [Builder Execution Requests](https://eips.ethereum.org/EIPS/eip-8282), Last Call | `de4c6f02c7bec4686762c55f8ab6abcf97a77d7d` |
| 7688 | [Forward Compatible Consensus Data Structures](https://eips.ethereum.org/EIPS/eip-7688), Review | `f2e6d7fb01194d590e16fcdcae8061d06cf1a7f1` |
| 8045 | [Exclude Slashed Validators from Proposing](https://eips.ethereum.org/EIPS/eip-8045), Last Call | `414a8404198c5afaa3cfed10a385a9aae1dfaae3` |
| 8061 | [Increase Exit and Consolidation Churn](https://eips.ethereum.org/EIPS/eip-8061), Last Call | `01f15c37c64114c478cb1136e0a6966084e4db14` |

Compared with beta.4, validator, p2p-interface and weak-subjectivity are byte-identical; beacon-chain only corrects the docstring “EIP-7521” to “EIP-7251” at [beacon-chain.md#L1479-L1486](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1479-L1486). The normative difference is fork onboarding in [spec PR #5736](https://github.com/ethereum/consensus-specs/pull/5736), merged 2026-10-26. Only fork.md changes behavior.

Nimbus uses **v1.7.0-beta.4 reference vectors** by default: [download_test_vectors.sh#L11-L16](https://github.com/status-im/nim-eth2-scenarios/blob/621865385551fc9776a216c34ec2dc364f579e3a/download_test_vectors.sh#L11-L16), at the scenario gitlink in both Nimbus trees. [Nimbus PR #9246](https://github.com/status-im/nimbus-eth2/pull/9246) merged that vector update on October 9. Onboarding matches beta.4; reviewed post-fork builder handlers match both versions.


Additional pins: consensus-specs beta.4 `aa16bb4c156184e9548a997d53efaf2a228a6304`; Grandine EL comparison uses execution-specs forks/amsterdam `16898000911c1e3caa57be08509536c10ae92d3e`. All three reviews target beta.4 test vectors; master’s behavioral delta is spec PR #5736.

Citation convention:
- `LS:path#La-Lb` means `https://github.com/ChainSafe/lodestar/blob/e4b4f615e68c1a4ea7c57632e6ed8d824624573f/path#La-Lb`.
- `CS:file#La-Lb` means `https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/file#La-Lb`.
- `TK:path#La-Lb` means `https://github.com/Consensys/teku/blob/2c35574b3373cbe8ad121a768d98f066aec05b73/path#La-Lb`.


## Candidates

## Candidate Nimbus-1 — EIP-8282 fork onboarding: spec-version lag

### 1. Specification, verbatim

At [fork.md#L65-L69](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L65-L69):

> A valid builder registration can use a validator's public key.

At [fork.md#L84-L88](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L84-L88):

```python
if not is_builder_withdrawal_credential(deposit.withdrawal_credentials):
    pending_deposits.append(deposit)
    continue
```

The subsequent registration and top-up paths are at [fork.md#L95-L119](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L95-L119). The gate precedes builder lookup; valid builder registrations are independent of the validator registry. Invalid registration signatures preserve eligible validator top-ups.

### 2. Nimbus implementation, pinned and quoted

[beaconstate.nim#L2360-L2384](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L2360-L2384) checks existing validators first and defers a registration if it finds an earlier valid pending validator:

```nim
if is_pending_validator(deposit.pubkey):
  pending_deposits.add(deposit)
  continue
```

[beaconstate.nim#L2395-L2402](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L2395-L2402) credits an existing builder without rechecking the credential prefix:

```nim
state.builders.mitem(opt_builder_index.get).balance += deposit.amount
```

The fork invokes this function at [beaconstate.nim#L3090-L3105](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L3090-L3105). Same code at the unstable pin cited above.

### 3. Conditions and differing results, in words

All cases occur during the one-time Fulu-to-Gloas upgrade, with the deposits still in the pending queue.

- A valid builder registration is followed by a non-builder-credential deposit for the same previously unregistered key. Nimbus credits both to the builder and removes both from the queue; master leaves the latter queued for validator processing.
- A valid builder-credential deposit uses an existing validator's key. Nimbus keeps it in the validator queue; master registers or tops up the independent builder.
- An earlier valid validator deposit is queued for a new key, followed by a valid builder registration for that key. Nimbus defers the latter; master creates the builder and preserves the validator deposit.

The resulting builder registry, balances, queue and state root differ. These cases share one version-lag cause.

### 4. Prysm comparison

Prysm agrees with Nimbus/beta.4, not master: [setters_gloas.go#L808-L839](https://github.com/OffchainLabs/prysm/blob/eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a/beacon-chain/state/state-native/setters_gloas.go#L808-L839). It checks the validator registry first, credits an existing builder before the credential test, and suppresses registration when the pending-validator check succeeds. Representative quoted branch:

```go
if isExistingBuilder {
    if err := b.increaseBuilderBalance(builderIdx, deposit.Amount); err != nil {
```

The real fork path calls it: [upgrade.go#L120-L135](https://github.com/OffchainLabs/prysm/blob/eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a/beacon-chain/core/gloas/upgrade.go#L120-L135). Prysm agreement does not establish master conformance.

### 5. Confidence and attempted disproof

**High** for static divergence; no executable reproduction.

- Compared the actual beta.4 algorithm at [fork.md#L75-L119](https://github.com/ethereum/consensus-specs/blob/aa16bb4c156184e9548a997d53efaf2a228a6304/specs/gloas/fork.md#L75-L119): Nimbus's routing matches that older baseline. This disproves labeling it a beta.4 implementation defect.
- Caller/caching checks did not reverse the result. Nimbus's [onboarding test#L68-L86](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/tests/consensus_spec/test_fixture_gloas_builder_onboarding.nim#L68-L86) explicitly expects beta.4 routing.
- Read master's regression cases: existing-validator key registration at [test_gloas_fork_onboard_builders.py#L390-L417](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/tests/core/pyspec/eth_consensus_specs/test/gloas/fork/test_gloas_fork_onboard_builders.py#L390-L417), and keeping a later non-builder deposit queued at [test_gloas_fork_onboard_builders.py#L460-L507](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/tests/core/pyspec/eth_consensus_specs/test/gloas/fork/test_gloas_fork_onboard_builders.py#L460-L507). These were read, not run.
- Checked unstable and Prysm; neither has the new routing. Deployment impact depends on the network's agreed spec revision and the pending deposits at activation.

### 6. Severity and known-check

**Severity: consensus split** if master and beta.4 implementations upgrade the same affected pre-state. No actual split was observed. Gloas activation is unscheduled on mainnet in [fork.md#L27-L30](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L27-L30).

**Known upstream:** [consensus-specs issue #5735](https://github.com/ethereum/consensus-specs/issues/5735), **closed**, and [PR #5736](https://github.com/ethereum/consensus-specs/pull/5736), **closed/merged**. The pinned Nimbus branches retain the publicly superseded routing.

**Nimbus-specific issue/PR: not found**; queries and Hive/EEST limitations are below.


### Lodestar-1: spec-version lag. Builder onboarding at the Gloas fork follows beta.4, not master (PR #5736)

**(1) Spec, master** (`CS:fork.md#L65-L121`, https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md):

> During this pass:
> - Only deposits with builder withdrawal credentials can fund builders.
> - Other deposits stay queued, even if a builder uses the same public key.
> - A valid builder registration can use a validator's public key.

```python
    for deposit in state.pending_deposits:
        # Only builder-credential deposits can fund builders at the fork.
        if not is_builder_withdrawal_credential(deposit.withdrawal_credentials):
            pending_deposits.append(deposit)
            continue
        builder_pubkeys = [builder.pubkey for builder in state.builders]
        if deposit.pubkey not in builder_pubkeys:
            if not is_valid_deposit_signature(...):
                # Preserve validator top-ups when no builder can receive them.
                if deposit.pubkey in validator_pubkeys or is_pending_validator(
                    pending_deposits, deposit.pubkey
                ):
                    pending_deposits.append(deposit)
                continue
            add_builder_to_registry(...)
        else:
            ...state.builders[builder_index].balance += deposit.amount
```

beta.4 (`https://raw.githubusercontent.com/ethereum/consensus-specs/v1.7.0-beta.4/specs/gloas/fork.md`, lines 70-119) is different in three ways:
- It first keeps every deposit whose pubkey is an existing validator: `if deposit.pubkey in validator_pubkeys: pending_deposits.append(deposit); continue`.
- It checks `is_builder_withdrawal_credential` only when the pubkey is not yet a builder.
- It keeps a deposit when `is_pending_validator(...)` holds, and checks that before the signature.

**(2) Lodestar** (`LS:packages/state-transition/src/slot/upgradeStateToGloas.ts#L208-L246`):

```ts
    // Deposits for existing validators stay in the pending queue
    if (isValidatorKnown(state, validatorIndex)) {
      pendingDeposits.push(deposit);
      ...
      continue;
    }
    const builderIndex = builderIndexByPubkey.get(pubkeyHex);
    if (builderIndex !== undefined) {
      // Top up an already-onboarded builder
      state.builders.get(builderIndex).balance += deposit.amount;
      ...
      continue;
    }
    if (!isBuilderWithdrawalCredential(deposit.withdrawalCredentials)) {
      pendingDeposits.push(deposit); ... continue;
    }
    if (
      pendingDepositsLookup.hasPendingValidator(state.config, pubkeyHex, state.epochCtx.builderDepositSignatureCache)
    ) {
      pendingDeposits.push(deposit); ... continue;
    }
```

The invalid-signature case then drops the deposit (`#L267-L271`: `if (!isValid) { dropped++; continue; }`).

**(3) When the results differ.** These cases apply to the state produced by the fork upgrade at the first slot of `GLOAS_FORK_EPOCH`, judged against master:
- **(a)** A pending deposit has builder (0xB0) credentials and a valid proof-of-possession, and its pubkey already belongs to a validator.
  - Master registers a new builder and removes the deposit from the queue.
  - Lodestar leaves it queued, so it later tops up the validator.
- **(b)** A pending deposit has non-builder credentials (0x00/0x01/0x02) and its pubkey was onboarded as a builder by an earlier deposit in the same queue.
  - Master leaves it queued; it later creates or tops up a validator.
  - Lodestar adds its amount to the builder's balance and removes it from the queue.
- **(c)** A builder-credential deposit has a valid signature, its pubkey is not yet a builder, and an earlier pending deposit for the same pubkey is a valid validator deposit (`is_pending_validator`).
  - Master registers the builder.
  - Lodestar keeps the deposit queued.

In all three cases `builders`, `pending_deposits` and the state root after the upgrade differ from a master-conformant client. Case (b) also moves validator stake into a builder balance. Any of these can be set up by sending deposits through the deposit contract before the fork.

**(4) Teku** (`TK:ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/gloas/forktransition/GloasStateUpgrade.java#L222-L268`): Teku has the same beta.4 structure as Lodestar, so it **agrees with Lodestar, not with master**.
- `#L224-L227`: "Deposits for existing validators stay in the pending queue". It runs `if (validatorsUtil.getValidatorIndex(state, pubkey).isPresent()) { pendingDeposits.add(deposit); continue; }`.
- `#L230-L237`: `getBuilderIndex(state, pubkey).ifPresentOrElse(builderIndex -> ... copyWithNewBalance(builder.getBalance().plus(deposit.getAmount()))`. This is the top-up, and it runs before the credential check.
- `#L246`: the credential check.
- `#L251`: `pendingValidators.isPendingValidator(pubkey)`, checked before the signature (`#L255`).

**(5) Confidence: high** that the code differs from master; I read both spec versions and the code. **Disproof attempted:**
- I confirmed that no other Lodestar path onboards builders. The only call is `#L123`, `onboardBuildersFromPendingDeposits(stateGloas, metrics)`.
- I confirmed that the brief's statement holds: master and beta.4 differ only in this function, apart from one docstring typo.
- What remains open: whether this "disagrees with the spec" depends on whether the reference is master or the latest release. PR #5736 is merged on master (1 day old) but not in any tag I checked.

**(6) Severity: consensus split** at the fork-transition state root between clients on beta.4 (Lodestar, Teku) and clients on master. The trigger needs pending deposits shaped like (a), (b) or (c) at the fork. Because PR #5736 is one day old, this is a spec-version-lag item rather than a bug in its own right.

**Known-check: known.**
- https://github.com/ChainSafe/lodestar/pull/10428, "fix: route pending deposits by withdrawal credentials at the gloas fork", **open**. Its description covers case (b): "once a builder is registered for a key every later deposit for that key tops up the builder regardless of its withdrawal credentials".
- Related, closed: #9395 (onboard 20k builders), #9861 / #9840 (perf).

---

### Lodestar-2: EIP-8061 Gloas `compute_min_epochs_for_block_requests` not implemented (p2p retention)

**(1) Spec** (`CS:p2p-interface.md#L246-L262`):

```python
def compute_min_epochs_for_block_requests() -> Epoch:
    # [Modified in Gloas:EIP8061]
    numerator = 3 * CHURN_LIMIT_QUOTIENT_GLOAS * CONSOLIDATION_CHURN_LIMIT_QUOTIENT
    denominator = 2 * CONSOLIDATION_CHURN_LIMIT_QUOTIENT + 3 * CHURN_LIMIT_QUOTIENT_GLOAS
    return MIN_VALIDATOR_WITHDRAWABILITY_DELAY + (numerator // denominator) // 2
```

Computed values:
- Mainnet: 3·32768·65536 // (131072 + 98304) = 28086, then // 2 = 14043, + 256 = **14,299 epochs**.
- Minimal: **262 epochs**.

**(2) Lodestar.** No function computes this. Every fork uses the static config value:
- `LS:packages/config/src/chainConfig/configs/mainnet.ts#L153`: `MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024,`. This is the phase0 value; minimal is 272.
- It is used as the serving lower bound at `LS:packages/beacon-node/src/network/reqresp/handlers/beaconBlocksByHead.ts#L26` (`chain.clock.currentEpoch - chain.config.MIN_EPOCHS_FOR_BLOCK_REQUESTS`).
- It is used as the pruning cutoff at `LS:packages/beacon-node/src/chain/archiveStore/utils/pruneHistory.ts#L20` (`Math.max(currentEpoch - config.MIN_EPOCHS_FOR_BLOCK_REQUESTS, 0)`).
- I found no `computeMinEpochsForBlockRequests` anywhere under `packages/`.

**(3) When the results differ.** After Gloas, Lodestar keeps and serves blocks and envelopes for 33,024 epochs instead of the 14,299 the spec requires. Serving more than the minimum stays compliant.

The observable difference: Lodestar's notion of the "must-serve" window is about 18,700 epochs larger than a spec client's. As a result:
- It does not get the smaller retention.
- It may treat a peer's `ResourceUnavailable` for epochs between 14,299 and 33,024 back as unexpected.

No block, state or gossip verdict changes.

**(4) Teku agrees with Lodestar, not the spec.** `TK:ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java#L1101-L1104` returns `minValidatorWithdrawabilityDelay + churnLimitQuotient / 2`, the phase0 formula, and I found no Gloas override. The search for `getChurnLimitQuotientGloas|getConsolidationChurnLimitQuotient` in main code found only config getters and churn accessors.

**(5) Confidence: high.**
- Disproof attempted: I grepped all of Lodestar `packages/` for the function and for any Gloas-specific value, and found neither.
- Data-column serving uses the separate `MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS`, which EIP-8061 does not change.

**(6) Severity: cosmetic** (p2p retention only; no consensus effect).

**Known-check: known.** https://github.com/ChainSafe/lodestar/pull/10120, "feat: reduce `MIN_EPOCHS_FOR_BLOCK_REQUESTS` for gloas", **open**. Related, open: #9965 (pruning policy for envelopes).

---


### Grandine-1 — EIP-8282: builder onboarding spec-version lag

1. **Spec quote:** “Only deposits with builder withdrawal credentials can fund builders.” “Other deposits stay queued, even if a builder uses the same public key.” “A valid builder registration can use a validator's public key.” [specs/gloas/fork.md#L65-L119](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L65-L119).
2. **Grandine quote:** [helper_functions/src/fork.rs#L1051-L1094](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/fork.rs#L1051-L1094) tops up under `if let Some(builder_index) = builder_indices.get(&pubkey)`, before its credential gate. It preserves deposits under `if is_for_validator[index]` and `if pending_validator_pubkeys.contains(&pubkey)`. The upgrade calls this path at [helper_functions/src/fork.rs#L928-L945](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/fork.rs#L928-L945).
3. **Condition/result:** A valid pending B0 registration at the fork uses an existing validator's key, or follows a valid pending validator deposit with that key: master creates a builder, Grandine keeps the registration pending. Alternatively, a valid registration followed by a non-B0 deposit with the same key: Grandine credits the builder, master keeps that later deposit queued. Registry/balances/queue and upgrade state root differ.
4. **Nimbus:** [beacon_chain/spec/beaconstate.nim#L2360-L2405](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L2360-L2405) agrees with **Grandine/beta.4**: `if is_pending_validator(deposit.pubkey):` retains the deposit; the existing-builder branch unconditionally adds its amount.
5. **Confidence/disproof:** **High against master; no defect against beta.4.** Diffed both specifications, checked the initially empty builder registry and updated key map, and separated one-time onboarding from post-fork request processing. Caching cannot change the routing. Nimbus's agreement is shared lag.
6. **Severity:** **Consensus split** if participants apply different upgrade specifications; no deployed split demonstrated.

**Known:** specification change [#5736 closed/merged](https://github.com/ethereum/consensus-specs/pull/5736); exact Grandine lag **not found** (queries in K1 below). [#860 closed](https://github.com/grandinetech/grandine/issues/860) concerns caching/testing, not adoption of the new routing.

### Grandine-2 — EIPs 7688/8282: excessive builder requests pass envelope gossip

1. **Spec quote:** `if len(execution_requests.builder_exits) > MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD:` then `raise GossipReject("too many builder exit requests")`; analogous builder-deposit limit: [specs/gloas/p2p-interface.md#L509-L528](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/p2p-interface.md#L509-L528). Envelope validation calls `verify_execution_requests_limits(envelope.execution_requests)`: [specs/gloas/p2p-interface.md#L866-L879](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/p2p-interface.md#L866-L879).
2. **Grandine quote:** [fork_choice_store/src/store.rs#L4174-L4256](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/fork_choice_store/src/store.rs#L4174-L4256) checks root/metadata/signature, calls `execution_engine.notify_new_payload(beacon_block_root, payload, params, None)?;`, then returns `Ok(ExecutionPayloadEnvelopeAction::Accept(envelope))`, with no request-count check. The real engine only queues work and returns `Ok(())`: [eth1_api/src/eth1_execution_engine.rs#L76-L92](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/eth1_api/src/eth1_execution_engine.rs#L76-L92). The mutator sends `P2pMessage::Accept(gossip_id)`: [fork_choice_control/src/mutator.rs#L2307-L2318](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/fork_choice_control/src/mutator.rs#L2307-L2318).
3. **Condition/result:** A known valid beacon block commits to an otherwise matching, correctly signed envelope with **17 builder exits** or **65 builder deposits**, within byte bounds. Required state/data are available and all other metadata/expected-withdrawal checks pass. Spec: gossip Reject. Grandine: Accept. 
4. **Nimbus:** [beacon_chain/gossip_processing/gossip_validation.nim#L909-L917](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/gossip_processing/gossip_validation.nim#L909-L917) agrees with spec: `if reqs.builder_exits.lenu64 > MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD:` returns `dag.checkedReject("ExecutionPayload: too many builder exit requests")`.
5. **Confidence/disproof:** **High, static only.** Progressive request lists ([types/src/gloas/containers.rs#L297-L308](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/types/src/gloas/containers.rs#L297-L308)) and their decoder do not enforce 64/16. Traced the async engine boundary. However, [transition_functions/src/gloas/block_processing.rs#L759-L787](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L759-L787) enforces counts when applying parent requests: this **disproves invalid-state acceptance** from this omission. Later Engine handling does not supply the required prior gossip verdict.
6. **Severity:** **Invalid block accepted**, limited to **envelope gossip acceptance**; no consensus import or lasting fork-choice divergence established.

**Not found** for the exact path (K2). Broad unlimited-container risk is **known**, [#918 open](https://github.com/grandinetech/grandine/issues/918). [#997 closed/merged](https://github.com/grandinetech/grandine/pull/997) adds network byte bounds, not these small per-list counts.

### Grandine-3 — EIP-7688: API gossip-only validation omits block counts

1. **Spec quote:** `if len(body.payload_attestations) > MAX_PAYLOAD_ATTESTATIONS:` then `raise GossipReject("too many payload attestations")`, [specs/gloas/p2p-interface.md#L470-L501](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/p2p-interface.md#L470-L501). Both body/parent-request limits are required at [specs/gloas/p2p-interface.md#L597-L603](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/p2p-interface.md#L597-L603). The Beacon API says failed selected validation “MUST NOT be broadcast to the network”: [apis/beacon/blocks/blocks.v2.yaml#L19-L37](https://github.com/ethereum/beacon-APIs/blob/bc3384f9cb1f02169d4fcb81e7da4da329b857ee/apis/beacon/blocks/blocks.v2.yaml#L19-L37).
2. **Grandine quote:** [transition_functions/src/gloas/block_processing.rs#L116-L136](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L116-L136) calls `unphased::process_block_header_for_gossip(config, state, &block.message)?;`, verifies the proposer signature, then `Ok(())`; no counts. [fork_choice_control/src/block_processor.rs#L192-L225](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/fork_choice_control/src/block_processor.rs#L192-L225) uses this path. [http_api/src/standard.rs#L5083-L5101](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/http_api/src/standard.rs#L5083-L5101) handles `Ok(Some(ValidationOutcome::Accept))` by publishing; [http_api/src/standard.rs#L5273-L5288](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/http_api/src/standard.rs#L5273-L5288) places this before full validation.
   Gloas dispatch: [http_api/src/standard.rs#L2043-L2058](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/http_api/src/standard.rs#L2043-L2058).
3. **Condition/result:** API publication with gossip validation of a small, current-slot Gloas block, known parent, correct unslashed proposer and valid proposer signature, but **five payload attestations** (limit four). Grandine publishes; the specified gossip/API rules require rejection without publication.
4. **Nimbus:** [beacon_chain/gossip_processing/gossip_validation.nim#L608-L641](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/gossip_processing/gossip_validation.nim#L608-L641) agrees with spec: `if blck.body.payload_attestations.lenu64 > MAX_PAYLOAD_ATTESTATIONS:` returns `dag.checkedReject("BeaconBlock: too many payload attestations")`.
5. **Confidence/disproof:** **High, static only.** Traced the dedicated API gossip path, not ordinary peer block import. Progressive decoding admits the count. Full processing later rejects it at [transition_functions/src/gloas/block_processing.rs#L920-L960](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L920-L960), but cannot undo prior publication.
6. **Severity:** **Invalid block accepted**, specifically **gossip publication**, not demonstrated state-transition acceptance.

**Not found** for this exact omission (K3); [#918 open](https://github.com/grandinetech/grandine/issues/918) is related general risk.

### Grandine-4 — EIP-7688: old validator-deposit bound survives in Engine bridge

1. **Spec quote:** `class DepositRequests(ProgressiveList[DepositRequest]):`, [specs/gloas/beacon-chain.md#L272-L280](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L272-L280); encoding emits `request_type + ssz_serialize(request_data)` for nonempty lists, [specs/gloas/beacon-chain.md#L2126-L2141](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L2126-L2141). Runtime limits cover the other four request lists, not validator deposits: [specs/gloas/beacon-chain.md#L1784-L1795](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1784-L1795).
2. **Grandine quote:** [execution_engine/src/types.rs#L1094-L1099](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/execution_engine/src/types.rs#L1094-L1099) stores `ContiguousList<DepositRequest, P::MaxDepositRequestsPerPayload>`; [types/src/preset.rs#L411-L433](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/types/src/preset.rs#L411-L433) defines `type MaxDepositRequestsPerPayload = U8192;`. Gloas calls `narrow_list(deposits)?`: [execution_engine/src/types.rs#L1351-L1374](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/execution_engine/src/types.rs#L1351-L1374), checked by [execution_engine/src/types.rs#L1398-L1404](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/execution_engine/src/types.rs#L1398-L1404). This runs before newPayloadV5 at [eth1_api/src/eth1_api/http_api.rs#L339-L363](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/eth1_api/src/eth1_api/http_api.rs#L339-L363); reverse Engine decoding uses the same bound at [execution_engine/src/types.rs#L1178-L1217](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/execution_engine/src/types.rs#L1178-L1217).
3. **Condition/result:** A legal Gloas payload yields **8,193 validator deposits**, with sufficient legal gas and within transport/block-size bounds. Spec forwards all records; Grandine fails local Engine encoding/decoding. **Conditional witness:** no transaction set proving reachability at a particular devnet's gas schedule was constructed.
4. **Nimbus:** [beacon_chain/el/engine_api_conversions.nim#L312-L331](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/el/engine_api_conversions.nim#L312-L331) emits `SSZ.encode(execution_requests.deposits)`, agreeing with the encoder spec. But [beacon_chain/gossip_processing/gossip_validation.nim#L900-L913](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/gossip_processing/gossip_validation.nim#L900-L913) separately rejects `reqs.deposits.lenu64 > MAX_DEPOSIT_REQUESTS_PER_PAYLOAD`: a shared extra rejection at another boundary, not disproof.
5. **Confidence/disproof:** **Medium overall; high for the narrowing failure.** EL parsing concatenates all matching deposit logs ([src/ethereum/forks/amsterdam/requests.py#L274-L304](https://github.com/ethereum/execution-specs/blob/16898000911c1e3caa57be08509536c10ae92d3e/src/ethereum/forks/amsterdam/requests.py#L274-L304)); the inherited Engine request grammar adds no 8,192 record cap ([src/engine/prague.md#L27-L54](https://github.com/ethereum/execution-apis/blob/3284ee80c3da3e516c53782dde75157cccf1ebdc/src/engine/prague.md#L27-L54)). Legal-payload feasibility under deployed gas/size settings remains unproved. [eth1_api/src/execution_service.rs#L120-L145](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/eth1_api/src/execution_service.rs#L120-L145) logs a local error; this does not prove an EL INVALID verdict.
6. **Severity:** **Valid block rejected**, conditional on that witness, at the **local Engine bridge**. No observed head divergence or split claimed.

**Not found** for this path (K4). [#968 closed/merged](https://github.com/grandinetech/grandine/pull/968) fixes bounded copying at state API endpoints, not the Engine adapter.


## Live-code entries

- Nimbus — EIP-7688 — affects live code, details withheld
- Nimbus — EIP-8061 — affects live code, details withheld

## Cross-client rule table

Cells summarize only the supplied reviews; checked paths and sources are indexed below. Comparison-only Prysm and Teku are covered in the candidates, not additional primary reviews. “Not checked” also covers unresolved or uncertified results.

| Rule | Nimbus | Lodestar | Grandine |
|---|---|---|---|
| 8282 fork onboarding | differs (see Nimbus-1) | differs (see Lodestar-1) | differs (see Grandine-1) |
| 8282 post-fork prefix gate | agrees with spec | agrees with spec | agrees with spec |
| 8282 signature/domain | agrees with spec | agrees with spec | agrees with spec |
| 8282 builder version/address/deposit epoch | agrees with spec | agrees with spec | agrees with spec |
| 8282 exited-builder zero-balance top-up | agrees with spec | agrees with spec | agrees with spec |
| 8282 reusable index and lookup | agrees with spec | agrees with spec | agrees with spec |
| 8282 exit authorization/pending balances | agrees with spec | agrees with spec | agrees with spec |
| 8282 exit delay | not checked | agrees with spec | agrees with spec |
| 8282 typed encoding/order/empty lists | agrees with spec | agrees with spec | agrees with spec |
| Engine request decoding: valid types/order/nonempty | not checked | agrees with spec | agrees with spec |
| EL request hash distinct from CL SSZ root | agrees with spec | agrees with spec | agrees with spec |
| Parent EMPTY/FULL request commitment | not checked | agrees with spec | agrees with spec |
| Parent payload payment/request processing order | not checked | agrees with spec | not checked |
| 7688 block operation counts/zero legacy deposits | agrees with spec | agrees with spec | agrees with spec |
| 7688 parent execution request count limits | agrees with spec | agrees with spec | agrees with spec |
| 7688 envelope gossip builder request limits | agrees with spec | agrees with spec | differs (see Grandine-2) |
| 7688 API gossip-only block body limits | not checked | not checked | differs (see Grandine-3) |
| 7688 peer gossip block body limits | agrees with spec | agrees with spec | not checked |
| 7688 validator-deposit Engine encoding capacity | agrees with spec | not checked | differs (see Grandine-4) |
| 7688 validator-deposit envelope gossip capacity (conflicting Nimbus evidence) | not checked | not checked | not checked |
| 7688 progressive field order/active bitmap | agrees with spec | agrees with spec | agrees with spec |
| 7688 progressive container legality/decoding offsets | agrees with spec | not checked | agrees with spec |
| 7688 progressive Merkle roots/subtree boundaries | agrees with spec | not checked | agrees with spec |
| 7688 network byte-size bounds | agrees with spec | agrees with spec | agrees with spec |
| 7688 indexed-attestation count cap | not checked | agrees with spec | not checked |
| 7688 Fulu-to-Gloas progressive list migration | not checked | agrees with spec | not checked |
| 7688 decoder-before-IGNORE ordering permitted | not checked | agrees with spec | not checked |
| 8045 slashed-validator exclusion | agrees with spec | agrees with spec | agrees with spec |
| 8045 weighted sampler reference arithmetic | not checked | agrees with spec | agrees with spec |
| 8045 fork preserves proposer lookahead | agrees with spec | agrees with spec | agrees with spec |
| 8045 proposer consumers use lookahead/cache | not checked | agrees with spec | not checked |
| 8061 activation churn cap/rounding | agrees with spec | agrees with spec | agrees with spec |
| 8061 uncapped exit churn | agrees with spec | agrees with spec | agrees with spec |
| 8061 independent consolidation churn/no floor | agrees with spec | agrees with spec | agrees with spec |
| 8061 exit allowance/exact-fit/spillover | agrees with spec | agrees with spec | agrees with spec |
| 8061 pending deposits consume activation churn | agrees with spec | agrees with spec | agrees with spec |
| 8061 mainnet/minimal constants | agrees with spec | agrees with spec | not checked |
| 8061 p2p minimum block-serving horizon | agrees with spec | differs (see Lodestar-2) | agrees with spec |
| 8061 churn slot-duration scaling | not checked | agrees with spec | not checked |
| 8061 weak-subjectivity weights | not checked | agrees with spec | not checked |

Nimbus disagreement retained: its own envelope-count row says validator deposits remain unbounded; Grandine-4 cites a Nimbus 8,192 gossip rejection. The cell is uncertified rather than inventing a resolution or a new candidate. Nimbus over-retention is recorded as compliant with a minimum; Lodestar-2 retains the originating item’s “differs” classification but explicitly says serving extra history remains compliant and rates it cosmetic. Merkle agreement for Lodestar is not certified because the SSZ library was absent. Grandine weak subjectivity was not located.

## Checked-rule source index

Each numbered entry condenses an original checked-rule row. Agreement means only that the supplied static review found no discrepancy on that path. Lodestar library/runtime limitations remain in its known-check section.

### Nimbus evidence

1. 8282 credential gate, first registration and top-up: [state_transition_block.nim#L1122-L1144](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1122-L1144).
2. 8282 signature and domain: [signatures.nim#L222-L242](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/signatures.nim#L222-L242).
3. 8282 exited-builder top-up: [state_transition_block.nim#L1146-L1154](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1146-L1154).
4. 8282 reusable indices / cache: [beaconstate.nim#L2264-L2274](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L2264-L2274).
5. 8282 exits: [state_transition_block.nim#L1157-L1175](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1157-L1175).
6. 8282 execution encoding: [engine_api_conversions.nim#L310-L331](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/el/engine_api_conversions.nim#L310-L331).
7. EL requests hash versus CL requests root: [helpers.nim#L449-L476](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/helpers.nim#L449-L476).
8. 7688 block operation counts: [state_transition_block.nim#L754-L794](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L754-L794).
9. 7688/8282 request counts: [state_transition_block.nim#L1390-L1409](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1390-L1409).
10. 7688 envelope gossip counts: [gossip_validation.nim#L901-L917](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/gossip_processing/gossip_validation.nim#L901-L917).
11. 7688 progressive type layout: [gloas.nim#L121-L182](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/datatypes/gloas.nim#L121-L182).
12. 7688 container bounds / decoding: [types.nim#L47-L59](https://github.com/status-im/nim-ssz-serialization/blob/253a6e7e4516afafd4d8a5979fb8edd0bf5dc837/ssz_serialization/types.nim#L47-L59).
13. 7688 Merkle structure: [merkleization.nim#L1000-L1040](https://github.com/status-im/nim-ssz-serialization/blob/253a6e7e4516afafd4d8a5979fb8edd0bf5dc837/ssz_serialization/merkleization.nim#L1000-L1040).
14. 7688 network bounds: [eth2_network.nim#L873-L927](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/networking/eth2_network.nim#L873-L927).
15. 8045 selection: [validator.nim#L565-L583](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/validator.nim#L565-L583).
16. 8045 transition lookahead: [beaconstate.nim#L3090-L3096](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L3090-L3096).
17. 8061 separate churn: [beaconstate.nim#L308-L352](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L308-L352).
18. 8061 exit accounting: [beaconstate.nim#L356-L389](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L356-L389).
19. 8061 activation consumption: [state_transition_epoch.nim#L1228-L1234](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_epoch.nim#L1228-L1234).
20. 8061 block-serving horizon: [presets.nim#L389-L393](https://github.com/status-im/nimbus-eth2/blob/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/presets.nim#L389-L393).

### Lodestar evidence


### Grandine evidence

1. 8282: prefix, registration, top-up: [transition_functions/src/gloas/execution_payload_processing.rs#L54-L145](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/execution_payload_processing.rs#L54-L145).
2. 8282: signature and exit authorization: [helper_functions/src/predicates.rs#L610-L632](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/predicates.rs#L610-L632).
3. 8282: reuse and delay: [helper_functions/src/gloas.rs#L123-L190](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/gloas.rs#L123-L190).
4. 8282: encoding: [execution_engine/src/types.rs#L75-L95](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/execution_engine/src/types.rs#L75-L95).
5. 8282/7688: requests root: [transition_functions/src/gloas/block_processing.rs#L728-L756](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L728-L756).
6. 7688: state-transition limits: Grandine-2/Grandine-3 state-transition excerpts enforce request/body counts, including zero legacy deposits and four payload attestations; validator deposit requests have no cap. Gossip exceptions are Grandine-2/Grandine-3..
7. 7688: progressive containers: [types/src/gloas/beacon_state.rs#L30-L134](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/types/src/gloas/beacon_state.rs#L30-L134).
8. 7688: Merkle rules: [ssz/src/merkle_tree.rs#L327-L405](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/ssz/src/merkle_tree.rs#L327-L405).
9. 8045: selection: [helper_functions/src/accessors.rs#L1093-L1112](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/accessors.rs#L1093-L1112).
10. 8045: pre-fork lookahead: [helper_functions/src/fork.rs#L919-L945](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/fork.rs#L919-L945).
11. 8061: separate churn: [helper_functions/src/accessors.rs#L1022-L1054](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/accessors.rs#L1022-L1054).
12. 8061: exit accounting / retention: [helper_functions/src/mutators.rs#L168-L209](https://github.com/grandinetech/grandine/blob/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/mutators.rs#L168-L209).

### Lodestar disproofs retained

### Not raised as candidates (checked, and the result is the same as the spec's)

- **N1. Gossip verdict order for over-limit blocks.** Lodestar enforces the EIP-7688 operation and request-count limits when it decodes the SSZ, before any IGNORE check.
  - Code: decode at `LS:packages/beacon-node/src/network/processor/gossipHandlers.ts#L765`, which maps to REJECT in `LS:packages/beacon-node/src/network/gossip/topic.ts#L171-L178`.
  - The spec instead lists the finalized-slot IGNORE before `verify_block_body_operation_limits` (`CS:p2p-interface.md#L590-L603`).
  - So a block that is over a limit **and** at or below the finalized slot gets REJECT from Lodestar and IGNORE in the spec's order.
  - Not raised because the spec explicitly allows this: "*Note*: These checks MAY be performed when deserializing `BeaconBlockBody`." (`CS:p2p-interface.md#L467`), and the same for `ExecutionRequests` (`#L506`).
  - Teku does the same through its schema limits.
- **N2. `apply_parent_execution_payload` length asserts.** The four `assert len(requests.X) <= MAX_*` lines (`CS:beacon-chain.md#L1792-L1795`) are not written out in `LS:packages/state-transition/src/block/processParentExecutionPayload.ts#L50-L102`.
  - The same limits are on the SSZ types (`LS:packages/types/src/gloas/sszTypes.ts#L181-L189`, `#L201-L204`, `#L214-L217`, each with `limit: MAX_*_REQUESTS_PER_PAYLOAD`). Those limits are enforced on decode: PR #10042 (merged) and the test `LS:packages/types/test/unit/gloas/eip7688.test.ts#L106-L177`.
  - Results would differ only for an object built in memory that was never deserialized. That cannot come from peers or from the EL, whose parser uses the same types.
  - Teku does the same, through schema limits (`TK:.../spec/schemas/registry/SchemaRegistryBuilder.java#L492-L497`).
  - The `@chainsafe/ssz` library code was not in the clone. My evidence for decode-time enforcement is Lodestar's tests and PR #10042.
- **N3. Churn slot-duration scaling.** The Gloas churn helpers scale by `getSlotDurationMsAtEpoch(epoch)/getSlotDurationMsAtEpoch(GENESIS)` (`LS:packages/state-transition/src/util/validator.ts#L97-L147`). That scaling is not in Gloas; it comes from a later feature, EIP-8198.
  - The ratio is exactly 1 unless a Heze fork with a different `SLOT_DURATION_MS_HEZE` is scheduled. The reader's check of the configs found `SLOT_DURATION_MS_HEZE` equal to `SLOT_DURATION_MS` on mainnet, minimal and gnosis.
  - So there is no Gloas difference.

### Logic shared with the live Fulu fork

No candidate was found in code shared with Electra/Fulu. That code includes the proposer sampling (`computeProposerIndices`), the lookahead shift, and the pre-Gloas branches of the churn helpers.


### Grandine limits of review

No weak-subjectivity implementation was located; absence was not treated as a defect. Progressive deserialization delegates to the generic list; removed capacities were not assumed to survive. See Grandine-4 for the retained Engine bound.

## Known-check summary

### Nimbus

Queries used `repo:status-im/nimbus-eth2`, including open/closed issues and PRs. Unrelated PR-number matches were excluded.

| Nimbus-1 search terms / results | Assessment |
|---|---|
| `8282` (2 results), `gloas` (247 results, all three pages), `epbs` (32 results), `onboard_builders_from_pending_deposits` (1), `process_builder_deposit_request` (0) | No matching Nimbus report for the new master routing found. [API search example](https://api.github.com/search/issues?q=repo%3Astatus-im%2Fnimbus-eth2%20onboard_builders_from_pending_deposits&per_page=100). |
| `"builder" "credential"` (2), `"onboarding"` (4), `5736` (1 unrelated PR) | No matching Nimbus issue/PR found. [Credential query](https://api.github.com/search/issues?q=repo%3Astatus-im%2Fnimbus-eth2%20%22builder%22%20%22credential%22&per_page=100). |
| [Nimbus #8965](https://github.com/status-im/nimbus-eth2/pull/8965), closed/merged; [#9137](https://github.com/status-im/nimbus-eth2/pull/9137), closed | Patches fix lookup/complexity, not #5736 routing. |
| [Spec #5735](https://github.com/ethereum/consensus-specs/issues/5735), closed; [spec #5736](https://github.com/ethereum/consensus-specs/pull/5736), closed/merged | **Known upstream**, with the cause and changed rules documented publicly. |

Additional rule searches: `7688` (9), `8045` (2), `8061` (2), `progressive` (9), `process_builder_exit_request` (0), `get_beacon_proposer_indices` (2), `"churn"` (36), `"compute_min_epochs_for_block_requests"` (1). Extra Nimbus-1 queries: `is_pending_validator` (2), `"gloas" "builder" "validator"` (15); no matching Nimbus report found. The `"v1.7.0-beta.4"` query (3) found #9246 above.

**Hive:** [ethdevops results](https://hive-results.ethdevops.io/) could not be read: the web tool returned an access error, and direct retrieval was blocked by the environment's address policy. [EthPandaOps Hive](https://hive.ethpandaops.io/) returned no readable listing through the web tool and HTTP 403 through direct retrieval. Public searches for Nimbus/Glamsterdam/Hive did not produce a result attributable to Nimbus-1. Therefore the Hive known-check is **incomplete**, not a pass and not proof of novelty.

**Execution-spec-tests:** reviewed public releases [devnet v8.1.4](https://github.com/ethereum/execution-specs/releases/tag/tests-glamsterdam-devnet%40v8.1.4), [v21.0.0](https://github.com/ethereum/execution-specs/releases/tag/tests%40v21.0.0) and [v21.0.2](https://github.com/ethereum/execution-specs/releases/tag/tests%40v21.0.2). They describe Amsterdam fixtures, coverage and Hive tooling; no Nimbus Nimbus-1 result was found. EL fixture availability does not establish CL fork-upgrade conformance. The relevant CL regression tests are cited under Nimbus-1 and were not run. **Outcome: no matching public result found, not a pass.**


### Lodestar

Searched with `api.github.com/search/issues?q=repo:ChainSafe/lodestar <query>`. Queries: `onboard builders`, `min_epochs_for_block_requests`, `MIN_EPOCHS_FOR_BLOCK_REQUESTS gloas`, `8061`, `8282`, `8045`, `7688`, `builder deposit request`, `builder exit request`, `gloas operation limits gossip`, `proposer lookahead slashed`, `epbs execution requests`, `1.7.0-beta.4`.

| Item | Status |
|---|---|
| Lodestar-1 onboarding lag | **known**: https://github.com/ChainSafe/lodestar/pull/10428 (open), "route pending deposits by withdrawal credentials at the gloas fork" |
| Lodestar-2 min epochs for block requests | **known**: https://github.com/ChainSafe/lodestar/pull/10120 (open); see also #9965 (open) |
| N1 / N2 progressive list limits | related: #10042 "enforce progressive list limits on deserialization" (merged 2026-09-10); #10121 "align gloas progressive list limits with the spec" (open; it says it adopts consensus-specs#5642, which I did not verify); #10080 (merged, legacy deposits rejected on decode) |
| Already indexed (from the brief) | #9337 weak subjectivity for EIP-8061, closed by #9625 (merged); #10042 merged; #9656 closed (progressive list RangeError at fork on glamsterdam-devnet-7) |
| Other related, for context | #9422 EIP-8045 (merged); #9730 next-epoch proposer from lookahead (closed); #9305 EIP-8061 churn (merged); #9390 EIP-7688 (merged); #10180 settle payment before requests (closed); #9558 "Clean up post EIP-8282" (closed); #9626 churn helper naming (open) |

## 5. Not verified

- The `@chainsafe/ssz` progressive merkleization and the decode-time limit enforcement. The library is not in the repo; I relied on Lodestar's tests and PRs.
- The native `@chainsafe/lodestar-z` proposer sampler. I checked only the TypeScript reference `naiveComputeProposerIndex`, at `LS:packages/state-transition/src/util/seed.ts#L69-L86`.
- Public hive or execution-spec-tests results for Glamsterdam devnets. I did not check them for this item.


### Grandine

GitHub issues API searches used `repo:grandinetech/grandine TERM`, **without state/type filters**: open/closed issues and PRs. Common queries for every candidate: its EIP number(s), `gloas`, `epbs`. [Reproducible API example](https://api.github.com/search/issues?q=repo%3Agrandinetech%2Fgrandine+gloas&per_page=100&page=1); substitute the literal terms below. Both `gloas` pages were read. Search counts: 8282=1, 7688=1, 8045=2, 8061=0, gloas=118, epbs=19, progressive=3.

| Check | Additional literal terms / disposition |
|---|---|
| K1 / Grandine-1 | `onboard_builders`, `onboard_builders_from_pending_deposits`, `5736`, `onboarding`: exact lag not found; known spec PR and related #860 identified above. |
| K2 / Grandine-2 | `verify_execution_requests_limits`, `builder_deposits`, `"gossip" "limit"`, `oversized`: exact omission not found; related #918/#997 above. |
| K3 / Grandine-3 | `verify_block_body_operation_limits`, `process_block_for_gossip`, `"broadcast_validation"`: zero exact-rule hits; related #918. |
| K4 / Grandine-4 | `RawExecutionRequests`, `MAX_DEPOSIT_REQUESTS_PER_PAYLOAD`, `"deposit" "limit"`: no matching Gloas Engine report; #968 addresses another boundary. |
| Other rules | `process_builder_deposit_request`, `process_builder_exit_request`, `get_beacon_proposer_indices`, `get_exit_churn_limit`, `weak_subjectivity`: zero hits. `min_epochs_for_block_requests` finds [#984 closed/merged](https://github.com/grandinetech/grandine/pull/984), fixed at this pin. |

Additional `8192` and `"payload" "count"` queries returned **HTTP 403 rate limit exceeded**, not negative results. 

**Grandine-1–Grandine-4 public-test cross-check: no matching current-pin result located.**

- [Hive discovery](https://hive.ethpandaops.io/discovery.json) lists `glamsterdam-quick`; its [listing](https://hive.ethpandaops.io/glamsterdam-quick/listing.jsonl) and the [older listing](https://hive.ethpandaops.io/glamsterdam/listing.jsonl) returned **HTTP 403**, preventing per-test inspection. [Run 40548729228](https://github.com/ethpandaops/hive-tests/actions/runs/40548729228) reports workflow success on 27 October, but tests Erigon/EELS, not Grandine. [.github/workflows/hive-glamsterdam-quick.yaml#L16-L29](https://github.com/ethpandaops/hive-tests/blob/13e902308ee426168240e24103162d63eaa873fa/.github/workflows/hive-glamsterdam-quick.yaml#L16-L29) lists EL clients/consumers. Workflow success is not interpreted as every test passing.
- EEST/EELS [devnet v8.1.4](https://github.com/ethereum/execution-specs/releases/tag/tests-glamsterdam-devnet%40v8.1.4), [tests v21.0.0](https://github.com/ethereum/execution-specs/releases/tag/tests%40v21.0.0), [v21.0.1](https://github.com/ethereum/execution-specs/releases/tag/tests%40v21.0.1) are EL fixture/coverage records, not evidence of these CL cases passing.
- [Devnet-11 status](https://notes.ethereum.org/@ethpandaops/glamsterdam-devnet-11) uses older CL/EELS versions. The [devnet-8 deposit observation](https://gist.github.com/nflaig/c02c00714d07df076bed23200805d2d6) observed old onboarding semantics, not master #5736. 
- [Hoodi postponement](https://blog.ethereum.org/2026/10/22/glamsterdam-hoodi-delay) supersedes its earlier schedule and sets no mainnet activation date.

