# Prysm: Gloas state and fork-transition review

2026-10-27 UTC. **Two candidates:** master-versus-beta.4 onboarding lag (high confidence), and bid-gossip cache timing (medium). Public-source/static review only; no client run or Ethereum network/node contacted.

## Pins and specification baseline

Newest heads returned by the named APIs at review start:


| Source | Branch/tag and full commit | Pin endpoint |
|---|---|---|
| OffchainLabs/prysm | `develop` → `eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a` | [commit API](https://api.github.com/repos/OffchainLabs/prysm/commits/develop) |
| ethereum/consensus-specs | `master` → `8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2` | [commit API](https://api.github.com/repos/ethereum/consensus-specs/commits/master) |
| sigp/lighthouse | `stable` → `a376defa30470923556d91bdeb15a802e297f31f` | [commit API](https://api.github.com/repos/sigp/lighthouse/commits/stable) |
| ethereum/consensus-specs | `v1.7.0-beta.4` → `aa16bb4c156184e9548a997d53efaf2a228a6304` | [commit API](https://api.github.com/repos/ethereum/consensus-specs/commits/v1.7.0-beta.4) |
| ethereum/EIPs | `master` → `d4c575521d99ec881a444ab3af604e684b5f0743` | [commit API](https://api.github.com/repos/ethereum/EIPs/commits/master) |
| ethereum/execution-specs | `forks/amsterdam` → `16898000911c1e3caa57be08509536c10ae92d3e` | [commit API](https://api.github.com/repos/ethereum/execution-specs/commits/forks/amsterdam) |

Prysm explicitly targets **v1.7.0-beta.4**: `P:WORKSPACE#L283-L312`; [PR 17664](https://github.com/OffchainLabs/prysm/pull/17664) is closed/merged (2026-10-13). Lighthouse also follows beta.4 onboarding behavior (C1).

The requested references are `S:specs/gloas/beacon-chain.md#L164-L186`, `S:specs/gloas/fork.md#L1-L130`, and `S:specs/gloas/builder.md#L38-L95`. Textual comparison against beta.4 found builder.md identical, fork.md changed in onboarding by [consensus-specs PR 5736](https://github.com/ethereum/consensus-specs/pull/5736) (closed/merged 2026-10-26), and beacon-chain.md changed only by the non-normative typo `EIP-7521` → `EIP-7251` in a churn-helper docstring. Only fork.md changes normative behavior. Beta baseline: `B:specs/gloas/fork.md#L72-L127`, `B:specs/gloas/beacon-chain.md#L1478-L1485`.

EIP text read: [EIP-7732](https://eips.ethereum.org/EIPS/eip-7732), [EIP-8282](https://eips.ethereum.org/EIPS/eip-8282). Both say Last Call in the pinned EIPs snapshot: `E:EIPS/eip-7732.md#L1-L12`, `E:EIPS/eip-8282.md#L1-L12`. EIP-7732's specification links target consensus-specs `d9663f85be248c4fd0ae95806da6070e17c2442b`, rather than current master: `E:EIPS/eip-7732.md#L45-L54`. Judgments below use master, distinguishing the EIP-linked revision and beta.4.

### Fork scope and versions

The exact **Scheduled for Inclusion** set in the pinned meta EIP is: **2780, 7688, 7708, 7732, 7778, 7843, 7928, 7954, 7976, 7981, 7997, 8024, 8037, 8038, 8045, 8061, 8246, 8282**. Networking EIPs **7975, 8070, 8136, 8159, 8189** and informational/optional **7904, 8261** are separately listed under Other EIPs, not added to that scheduled set. Source: `E:EIPS/eip-7773.md#L24-L62`.

The pins above define current EIP, EL and CL spec snapshots for the scheduled set. The EL Amsterdam change inventory contains 2780, 7708, 7778, 7843, 7928, 7954, 7976, 7981, 7997, 8024, 8037, 8038, 8246, 8282: `A:src/ethereum/forks/amsterdam/__init__.py#L1-L23`. The CL inventory names 7688, 7732, 7843, 8070, 8045, 8061, 8261, 8282 and explicitly pins historical EIP revisions: `S:specs/gloas/beacon-chain.md#L164-L186`. Other clients/EIPs were not reviewed.

The meta EIP leaves Gloas mainnet activation blank: `E:EIPS/eip-7773.md#L69-L79`. Candidates are Gloas-specific.

## C1 — spec-version lag: fork onboarding still uses beta.4 registry/queue separation

**1. Spec, verbatim.** Master says “Only deposits with builder withdrawal credentials can fund builders” and “A valid builder registration can use a validator's public key.” Code:

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

For a builder-credential deposit whose pubkey is not yet a builder, master tests the deposit signature before registration; existing-validator or pending-validator membership only preserves the deposit when that signature is invalid. Source: `S:specs/gloas/fork.md#L65-L127`. Changed by [PR 5736](https://github.com/ethereum/consensus-specs/pull/5736).

**2. Prysm, verbatim at P.** `P:beacon-chain/state/state-native/setters_gloas.go#L808-L843` instead first executes:

```go
if _, ok := b.validatorIndexByPubkey(pubkey); ok {
    newPendingDeposits = append(newPendingDeposits, deposit)
    pendingIdx.Add(deposit)
    continue
}
```

It next looks up the builder and executes `b.increaseBuilderBalance(builderIdx, deposit.Amount)` with a `continue` **before** the withdrawal-prefix test. Finally, `if isPending {` retains a builder-credential deposit before its own signature is checked. Registration follows in `P:beacon-chain/state/state-native/setters_gloas.go#L852-L876`. Fork caller: `P:beacon-chain/core/gloas/upgrade.go#L120-L136`.

**3. Differing conditions.** Three pending-queue shapes distinguish this version lag:

- A valid builder-credential deposit uses an existing validator's key. Master registers a builder and consumes the deposit; Prysm retains it for validator processing and leaves the builder absent.
- A valid ordinary-validator deposit precedes a valid builder-credential deposit with the same new key. Master leaves the first deposit pending and registers the builder from the second; Prysm leaves both pending.
- A valid builder registration is followed by an ordinary-credential deposit for that key. Master preserves the latter in the pending queue; Prysm consumes it as a builder top-up, regardless of its credentials.

These queue shapes change the upgrade state root. Public-devnet occurrence is unconfirmed. Pre-fork validator-contract onboarding is permitted: `S:specs/gloas/builder.md#L62-L95`.

**4. Lighthouse at L.** Agrees with Prysm/beta.4. `L:consensus/state_processing/src/upgrade/gloas.rs#L258-L304` first retains existing-validator deposits, next branches on builder membership, checks credentials only for non-builders, and blocks a builder registration when `valid_pending_validator_pubkeys.contains(&deposit.pubkey)`. Its existing-builder arm unconditionally executes `builder.balance.safe_add_assign(deposit.amount)?;`. Both clients lag master.

**5. Confidence and attempted disproof.** **High**, as version lag. Compared both complete spec functions, the actual fork caller, pending-validator signature handling, registration validation and Lighthouse. Registration examples require valid signatures. The early top-up cannot reach the later prefix check. Both clients conform to beta.4 here; a network uniformly targeting beta.4 does not split.

**6. Severity.** **Consensus split**, if some participants implement master/PR 5736 while others retain this onboarding behavior and a distinguishing queue exists at activation. 

**Known-check:** **not found as this Prysm bug**, with the queries recorded below. Spec change **known**, [PR 5736](https://github.com/ethereum/consensus-specs/pull/5736), merged. Prysm [17387](https://github.com/OffchainLabs/prysm/pull/17387), merged, addresses quadratic signature work, not these new semantics; [17447](https://github.com/OffchainLabs/prysm/issues/17447), closed, addresses older bid-field initialization, not this queue rule. No matching Hive/EST result found (limits below).

## C2 — bid seen-cache written before all gossip checks succeed

**1. Spec, verbatim.** The gossip rule checks gas-limit compatibility and other conditions before writing:

```python
seen.execution_payload_bids.add(bid_key)
seen.best_execution_payload_bid[best_bid_key] = bid.value
```

Gas-limit failure raises `GossipIgnore`. Sources: `S:specs/gloas/p2p-interface.md#L968-L983`, `S:specs/gloas/p2p-interface.md#L1033-L1090`.

**2. Prysm, verbatim at P.** `P:beacon-chain/sync/validate_execution_payload_bid.go#L115-L165` executes:

```go
if err := v.VerifySignature(st); err != nil {
    return pubsub.ValidationReject, err
}
s.setSeenExecutionPayloadBid(bid.Slot(), tupleKey)
```

Later checks include coverage, exit, execution parent, gas limit, branch and descendant slot:

```go
if err := v.VerifyGasLimitTargetCompatible(parentGasLimit, pref.TargetGasLimit); err != nil {
    return pubsub.ValidationIgnore, err
}
```

The key omits gas limit/value; matching tuples are ignored: `P:beacon-chain/sync/validate_execution_payload_bid.go#L69-L74`, `P:beacon-chain/sync/validate_execution_payload_bid.go#L189-L206`. No rollback follows.

**3. Differing condition, in words.** An active funded builder sends a correctly signed bid passing early checks but failing gas-limit compatibility. Prysm ignores it and marks the tuple seen. A newly signed correction with compatible gas limit and the same slot, parent hash/root and builder index is then ignored as seen; the spec can accept it because its first attempt never updated the cache. Assume available parent/state/preferences, no higher bid, blacklist or exit, and compatible head. 

**4. Lighthouse at L.** Agrees with the spec on cache-write timing. Gas-limit checks precede success; state coverage, exit checks and signature verification precede `observe_bid`: `L:beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs#L416-L479`. Its cache records the seen tuple in `observe_bid`: `L:beacon_node/beacon_chain/src/payload_bid_verification/payload_bid_cache.rs#L83-L115`.

**5. Confidence and attempted disproof.** **Medium** for conformance, high for ordering. Traced subscriber, key construction and error returns: the highest-bid cache updates only after acceptance and cannot undo the separate seen-cache write. BLS-before-write disproves unauthenticated poisoning; a builder must sign both attempts. The spec allows anti-spam measures: irrevocable signed-tuple dedup may be intentional policy, although it differs from the executable rules. Requires maintainer/spec clarification.

**6. Severity.** **Cosmetic**: gossip **ACCEPT→IGNORE** and bounded propagation/liveness loss. No invalid block acceptance, consensus split, or fork-choice divergence established.

**Known-check:** **not found as this exact bug**. Related known changes: [16832](https://github.com/OffchainLabs/prysm/pull/16832), merged, moves the dedup *read* early; [16539](https://github.com/OffchainLabs/prysm/pull/16539), merged, introduces bid gossip/dedup; [17237](https://github.com/OffchainLabs/prysm/pull/17237), closed/unmerged, discusses tuple changes; [17405](https://github.com/OffchainLabs/prysm/pull/17405), merged, fixes which parent's gas limit to read. Their descriptions do not identify this write-before-failure issue; no corroborating Hive/EST result found.

## Rules checked without a retained discrepancy

“Matches” means static agreement, not executed tests or proof.

| Rule / boundary checked | Specification | Prysm at P / finding |
|---|---|---|
| Self-build value zero and exact point-at-infinity signature; non-self active builder and payload-builder version | `S:specs/gloas/beacon-chain.md#L2162-L2184` | `P:beacon-chain/core/gloas/bid.go#L76-L131` — matches; self-build bypasses registry lookup. |
| Bid coverage includes pending withdrawals AND payments; below reserve fails, exact reserve plus bid succeeds | `S:specs/gloas/beacon-chain.md#L1168-L1193` | `P:beacon-chain/state/state-native/getters_gloas.go#L152-L207` — matches subtraction order and inclusive comparison. No reachable overflow counterexample established. |
| Bid blob count, current slot, non-genesis slot, parent hash, unequal own hash, parent beacon root, RANDAO | `S:specs/gloas/beacon-chain.md#L2186-L2203` | `P:beacon-chain/core/gloas/bid.go#L133-L198` — matches, inclusive blob maximum. RANDAO follows the bid. |
| Pending-payment slot index, zero initial weight, proposer | `S:specs/gloas/beacon-chain.md#L2205-L2220` | `P:beacon-chain/core/gloas/bid.go#L144-L160` — current-epoch half plus slot modulo epoch. Header processing validates proposer. |
| Weight only for first participation, newly set flag, same-slot attestation, positive payment | `S:specs/gloas/beacon-chain.md#L2436-L2480` | `P:beacon-chain/state/state-native/setters_gloas.go#L518-L604` — matches conditions and current/previous-epoch payment selection. |
| Parent FULL vs EMPTY; EMPTY requires all five request lists empty; FULL root commitment | `S:specs/gloas/beacon-chain.md#L1841-L1857` | `P:beacon-chain/core/gloas/parent_payload.go#L19-L58` — matches; empty-parent branch returns before mutations. |
| Parent settlement before requests; same/previous/older epoch payment; request ordering and limits | `S:specs/gloas/beacon-chain.md#L1784-L1830` | `P:beacon-chain/core/gloas/parent_payload.go#L70-L140`; `P:beacon-chain/state/state-native/setters_gloas.go#L186-L244` — matches: deposits, withdrawals, consolidations, builder deposits, builder exits. Older parent reconstructs positive bid payment. |
| Withdrawal early return and priority; reserve one validator withdrawal slot | `S:specs/gloas/beacon-chain.md#L1861-L1989` | `P:beacon-chain/core/gloas/withdrawals.go#L44-L105`; `P:beacon-chain/state/state-native/getters_gloas.go#L432-L472` — preserves cache on early return; payments → partials → builder sweep → validator sweep; builder cap max−1. |
| Builder sweep nets earlier payments; saturating debit; next builder cursor | `S:specs/gloas/beacon-chain.md#L1895-L1950` | `P:beacon-chain/state/state-native/getters_gloas.go#L575-L634` — matches; nets prior committed withdrawals. |
| Envelope consistency and self-build signer | `S:specs/gloas/fork-choice.md#L683-L730` | `P:beacon-chain/core/gloas/payload.go#L113-L196`; `P:beacon-chain/core/gloas/payload.go#L258-L324` — compares slot, parent beacon root, builder, requests, RANDAO, withdrawals, gas, hash, execution parent, timestamp; signer proposer for self-build, builder otherwise. Caller checks below. |
| Payload-attestation root, previous slot, nonempty sorted indices, duplicates and BLS domain | `S:specs/gloas/beacon-chain.md#L1094-L1111`; `S:specs/gloas/beacon-chain.md#L2488-L2500` | `P:beacon-chain/core/gloas/payload_attestation.go#L47-L107`; `P:beacon-chain/core/gloas/payload_attestation.go#L327-L366` — matches; sorting retains duplicate PTC selections, not a set. Slot addition checked for overflow. |
| PTC selection committee concatenation, repeated passes, seed, 16-bit little-endian sampling, inclusive acceptance | `S:specs/gloas/beacon-chain.md#L1198-L1229`; `S:specs/gloas/beacon-chain.md#L1266-L1283` | `P:beacon-chain/core/gloas/payload_attestation.go#L131-L168`; `P:beacon-chain/core/gloas/payload_attestation.go#L214-L220`; `P:beacon-chain/core/gloas/payload_attestation.go#L259-L304` — matches: counter crosses committees, 16 candidates/hash, weight multiplier 65535. Final iteration increment is unused. Lighthouse: `L:consensus/types/src/state/beacon_state.rs#L3639-L3662`. |
| Payments quorum rounding and rotation | `S:specs/gloas/beacon-chain.md#L1433-L1441`; `S:specs/gloas/beacon-chain.md#L1719-L1731` | `P:beacon-chain/core/gloas/pending_payment.go#L31-L88` — floor active balance/slots first, then multiply 6/divide 10; equality qualifies; previous half processed, current half shifted and cleared. |
| process_ptc_window lookahead and shift; reject pre-fork committee lookup | `S:specs/gloas/beacon-chain.md#L1392-L1405`; `S:specs/gloas/beacon-chain.md#L1737-L1750` | `P:beacon-chain/core/gloas/payload_attestation.go#L383-L404`; `P:beacon-chain/state/state-native/setters_gloas.go#L966-L1003`; `P:beacon-chain/state/state-native/getters_gloas.go#L740-L784` — current epoch + lookahead + one, shift one epoch; explicit Gloas lower bound matches spec. |
| upgrade_to_gloas defaults excluding C1 | `S:specs/gloas/fork.md#L139-L257` | `P:beacon-chain/core/gloas/upgrade.go#L270-L353` — all-one availability; empty builders/withdrawals; two-epoch zero payments; latest hash/full bid from header; self-build sentinel, zero value/payment and empty commitments; previous-epoch PTC zeros/current/lookahead computed at `P:beacon-chain/core/gloas/upgrade.go#L162-L188`. |
| Builder request prefix, dedicated signature domain, reused index, exited zero-balance top-up delay and exit guards | `S:specs/gloas/beacon-chain.md#L2270-L2386` | `P:beacon-chain/core/gloas/builder_deposit_request.go#L88-L144`; `P:beacon-chain/core/gloas/builder_exit.go#L76-L112` — matches sequential application, registration versus top-up, active/address/pending-balance guards; request limits are 64 deposits/16 exits, not the older 256 deposit cap. |
| Constants: self-build uint64 max; builder flag 2^40; 0xB0; domains 0x0B–0x0E; mainnet PTC 512 | `S:specs/gloas/beacon-chain.md#L550-L613` | `P:config/params/mainnet_config.go#L100-L104`; `P:config/params/mainnet_config.go#L202-L206`; `P:consensus-types/primitives/validator.go#L13-L38`; `P:config/fieldparams/mainnet.go#L57-L60` — matches. Minimal PTC is separately 16, not a mainnet discrepancy. |

### Disproofs of apparent discrepancies

- **Missing beacon-root assertion inside envelope helper:** not retained. Regular import selects the post-state by `envelope.BeaconBlockRoot()` only after confirming that root is in fork choice: `P:beacon-chain/blockchain/receive_execution_payload_envelope.go#L269-L288`. Batch import calls verification only when `b.Root() == br`, where `br` is the envelope root: `P:beacon-chain/blockchain/process_block.go#L289-L307`. EL verification runs in the receive path, separately from the CL helper: `P:beacon-chain/blockchain/receive_execution_payload_envelope.go#L63-L91`, `P:beacon-chain/blockchain/receive_execution_payload_envelope.go#L325-L358`. Missing checks in one helper are not enough to establish invalid-envelope acceptance.
- **Apparently different PTC traversal:** not retained. Streaming through committees with a shared counter and then restarting from the first committee is the same sequence as traversing the concatenated committees modulo their combined length. Recomputing a SHA-256 block at a committee boundary does not change its input.
- **Pre-Gloas previous-epoch PTC initialized to zeros:** not a validity loophole. The spec's `get_ptc` explicitly asserts epoch at least Gloas, and Prysm rejects lookup before the fork as shown in the table. A first-Gloas-block attestation claiming the last Fulu slot does not demonstrate a split.
- **Old upgrade initialization failure:** not retained at this pin. The missing parent fields, RANDAO, builder sentinel and bid slot described in closed #17447 are present in the current upgrade initializer. This does not disprove C1, which concerns a different field mutation after initialization.

## SSZ field-order inventory

Compared spec sequences against generated marshal/root routines, not outdated proto comments. Progressive overrides: `P:proto/prysm/v1alpha1/gloas.yaml#L8-L73`. Core generated field sequences also matched by local text comparison. SSZ-library correctness/decoder limits were not exhaustively verified.

| Container(s) | Spec order source | Prysm order source / result |
|---|---|---|
| Builder; BuilderPendingPayment; BuilderPendingWithdrawal | `S:specs/gloas/beacon-chain.md#L660-L686` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L3754-L3780`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L3862-L3880`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L3951-L3971` — pubkey/version/address/balance/deposit epoch/withdrawable epoch; weight/withdrawal/proposer; recipient/amount/builder. |
| BuilderDepositRequest; BuilderExitRequest | `S:specs/gloas/beacon-chain.md#L690-L703` | `P:proto/engine/v1/engine.ssz.go#L511-L537`; `P:proto/engine/v1/engine.ssz.go#L594-L607` — pubkey/credentials/amount/signature; source address/pubkey. |
| PayloadAttestationData; PayloadAttestation; PayloadAttestationMessage | `S:specs/gloas/beacon-chain.md#L708-L734` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L5837-L5860`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L5721-L5736`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L5931-L5948` — root/slot/present/available; bits/data/signature; validator/data/signature. |
| IndexedPayloadAttestation | `S:specs/gloas/beacon-chain.md#L738-L743` | `P:consensus-types/indexed_payload_attestation.go#L9-L13` — indices/data/signature. Internal helper only; no standalone wire encoder found. Its data signature path is checked above. |
| ExecutionPayloadBid; SignedExecutionPayloadBid | `S:specs/gloas/beacon-chain.md#L749-L772` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L5027-L5091`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L6505-L6522` — all 12 bid fields match, ending in commitments then requests root; wrapper message/signature. |
| ExecutionPayloadEnvelope; SignedExecutionPayloadEnvelope | `S:specs/gloas/beacon-chain.md#L777-L793` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L5230-L5252`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L6599-L6616` — payload/requests/builder/beacon root/parent beacon root; wrapper message/signature. No removed state-root field. |
| Attestation; IndexedAttestation; AttesterSlashing | `S:specs/gloas/beacon-chain.md#L801-L822` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L825-L847`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L5369-L5390`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L1147-L1161` — bits/data/signature/committee bits; indices/data/signature; first/second indexed attestations. |
| BeaconBlockBody; BeaconState | `S:specs/gloas/beacon-chain.md#L829-L933` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L1668-L1776`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L3146-L3473` — all 13 and 46 fields respectively match. latest_block_hash is position 24; bid position 43; expected withdrawals 44; PTC window 45. Go initializer literal order is not SSZ order. |
| ExecutionPayload; ExecutionRequests | `S:specs/gloas/beacon-chain.md#L940-L983` | `P:proto/engine/v1/engine.ssz.go#L2265-L2355`; `P:proto/engine/v1/engine.ssz.go#L3844-L3893` — all 19 payload fields match, ending block_access_list/slot_number; five request lists end builder_deposits/builder_exits. |
| BeaconBlock; SignedBeaconBlock (inherited wrappers) | `S:specs/gloas/beacon-chain.md#L1754-L1772` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L2100-L2135`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L6317-L6334` — slot/proposer/parent/state/body; block/signature. Wrapper orders unchanged. |
| DataColumnSidecar; ProposerPreferences; SignedProposerPreferences | `S:specs/gloas/p2p-interface.md#L145-L184` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L4782-L4818`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L6039-L6062`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L6865-L6882` — index/column/proofs/slot/beacon root; proposal slot/proposer/head root/fee recipient/gas target per spec; message/signature. |
| PartialDataColumnSidecar; PartialDataColumnPartsMetadata; PartialDataColumnGroupID | `S:specs/gloas/partial-columns/p2p-interface.md#L50-L74` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L5603-L5636`; `P:proto/prysm/v1alpha1/partial_data_columns.proto#L48-L68` — bitmap/column/proofs; available/requests; beacon root/slot. Metadata declaration order checked; separate Gloas generated metadata codec not found in this source subset. |
| LightClientHeader; Bootstrap; Update; FinalityUpdate; OptimisticUpdate | `S:specs/gloas/light-client/sync-protocol.md#L120-L127`; `S:specs/altair/light-client/sync-protocol.md#L132-L180` | `P:proto/prysm/v1alpha1/gloas.ssz.go#L103-L131`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L225-L250`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L412-L465`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L585-L619`; `P:proto/prysm/v1alpha1/gloas.ssz.go#L700-L717` — modified header beacon/execution hash/branch; inherited wrapper field orders match, with Gloas headers and branch sizes. |

`PayloadTimelinessCommittee` is a vector, not an extra spec container; Prysm's one-field PTCs wrapper serializes its vector: `P:proto/prysm/v1alpha1/gloas.ssz.go#L6076-L6140`. `NewPayloadRequest` is an execution-engine helper, not a beacon wire object; a standalone Prysm Gloas SSZ codec was not found. [PR 17664](https://github.com/OffchainLabs/prysm/pull/17664) explicitly notes skipping its static-SSZ test because it is not a consensus type. API/storage-only containers excluded.

## Known-check and public-results audit

Searched **issues/PRs, open/closed**, without type/state restrictions, using `api.github.com/search/issues`. Exact queries below; “not found” is not proof of novelty. Broad `gloas`: 492 results, latest 100 inspected. Focused queries: fewer than 100 each, all inspected. Numeric searches also match unrelated issue numbers.

| Candidate | Additional exact queries (each prefixed `repo:OffchainLabs/prysm`) | Result |
|---|---|---|
| C1 | `7732`, `8282`, `gloas`, `epbs`, `"onboard"`, `"5736"`, `"pending deposits"`, `"onboard_builders_from_pending_deposits"`, `"OnboardBuildersFromPendingDeposits"`, `"builder" "validator" "fork"` | Exact new onboarding semantics not found. Related 17387 merged, 17440 merged prewarming, 17147 closed state-diff bug, 17447 closed old initialization failure. Master change known via spec PR 5736. |
| C2 | `7732`, `gloas`, `epbs`, `"seenExecutionPayloadBid"`, `"bid" "seen"`, `"bid" "gas limit"`, `"bid" "cache"`, `"bid" "signature"` | Exact cache-write-before-later-failure bug not found; related PRs listed under C2 reviewed. Literal cache-symbol search returned zero. |
| PTC disproof/checks | `"compute_ptc"`, `"process_ptc_window"` | Related 16753 closed/merged optimization and 16797 closed/merged spec bump; no retained PTC arithmetic candidate. |

Search endpoint: [GitHub issue/PR search API](https://api.github.com/search/issues); exact queries are in the table. Bodies and merge states were read through issue/PR APIs.

Indexed items checked:

- [17447](https://github.com/OffchainLabs/prysm/issues/17447): **closed** issue, reports devnet-9 fork state-root failure from alpha.12 versus alpha.14 bid initialization. Current code initializes those fields; not re-reported as a new bug.
- [17387](https://github.com/OffchainLabs/prysm/pull/17387): **merged** 2026-08-20, quadratic onboarding BLS work. Does not implement the subsequently merged spec PR 5736.
- [16706](https://github.com/OffchainLabs/prysm/pull/16706): **closed, unmerged** (`merged_at` null), historical getPayloadV6 slotNumber JSON omission. Does not establish a current bug or eventual fix; no duplicate asserted.

**Public test results:** [Hive discovery](https://hive.ethpandaops.io/discovery.json) lists a `glamsterdam-quick` suite. The [Glamsterdam listing](https://hive.ethpandaops.io/glamsterdam-quick/listing.jsonl) and [generic listing](https://hive.ethpandaops.io/generic/listing.jsonl) both returned **HTTP 403** during this review; no individual run/result could therefore be checked. [Hive CL-spec-runner PR 1537](https://github.com/ethereum/hive/pull/1537) was **open/unmerged** when fetched; it describes native CL fixtures, not a published pass. [Execution-specs tests@v21.0.0 milestone](https://github.com/ethereum/execution-specs/milestone/42) is closed/100% complete, but is a test-production milestone, not evidence that Prysm passes these CL queue/gossip cases. Neither candidate was tied to a public failing run. Status is “not found,” not “tested clean”; #17447 corroborates only the old bug.

## URLs read and verification limits

Issue/PR URLs above were read through the corresponding `/repos/OffchainLabs/prysm/issues/N` and `/pulls/N` APIs; PR 5736 through `/repos/ethereum/consensus-specs/pulls/5736`; Hive 1537 through `/repos/ethereum/hive/pulls/1537`. Also read the EIP pages, meta EIP markdown, [Hive index](https://hive.ethpandaops.io/), its linked JS/discovery, and the EST milestone. Search also surfaced [devnet-9 specification](https://notes.ethereum.org/@ethpandaops/glamsterdam-devnet-9); no network endpoint from it was contacted.

Validation performed: exact commit pins retained; beta/master three-file text diff; manual caller/disproof tracing; core SSZ sequence comparison (17 generated types matched; two helpers lacked codecs); citation ranges and quoted source substrings checked; output byte limit checked. No dynamic acceptance/state-root/cryptographic test or complete fork-choice audit performed.

## Citation notation


Each prefixed `path#Lstart-Lend` citation expands to `https://github.com/OWNER/REPO/blob/FULL_PIN/path#Lstart-Lend`, using the repository and full commit in the pins table (P=Prysm, S=spec master, L=Lighthouse, B=spec beta.4, E=EIPs, A=EL Amsterdam). Equivalent raw.githubusercontent.com URLs were read.

Direct candidate source links: [C1 spec](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L65-L127), [C1 Prysm](https://github.com/OffchainLabs/prysm/blob/eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a/beacon-chain/state/state-native/setters_gloas.go#L795-L876), [C1 Lighthouse](https://github.com/sigp/lighthouse/blob/a376defa30470923556d91bdeb15a802e297f31f/consensus/state_processing/src/upgrade/gloas.rs#L258-L304); [C2 spec](https://github.com/ethereum/consensus-specs/blob/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/p2p-interface.md#L956-L1090), [C2 Prysm](https://github.com/OffchainLabs/prysm/blob/eb681c1d13b57c2d0c5da27a63bb41ac9d071e1a/beacon-chain/sync/validate_execution_payload_bid.go#L75-L165), [C2 Lighthouse](https://github.com/sigp/lighthouse/blob/a376defa30470923556d91bdeb15a802e297f31f/beacon_node/beacon_chain/src/payload_bid_verification/gossip_verified_bid.rs#L416-L479).
