Skip to content

statetransition: handle Gloas builder deposits in process_deposit_request#743

Merged
pk910 merged 2 commits into
masterfrom
pk910/fix-gloas-state-transition
Jun 17, 2026
Merged

statetransition: handle Gloas builder deposits in process_deposit_request#743
pk910 merged 2 commits into
masterfrom
pk910/fix-gloas-state-transition

Conversation

@pk910

@pk910 pk910 commented Jun 13, 2026

Copy link
Copy Markdown
Member

Problem

The CL indexer's state-transition replay diverged from consensus on Gloas, logging:

replay: state root mismatch at slot 64805 ... falling back to API

applyExecutionRequests (indexer/beacon/statetransition/operations.go) appended every deposit request to PendingDeposits regardless of fork, so it never implemented Gloas's (EIP-7732) modified process_deposit_request. On Gloas a deposit whose pubkey already belongs to a builder — or one carrying the 0x03 builder credential for a brand-new, non-validator pubkey — must be applied immediately to the builder registry via apply_deposit_for_builder and must never enter the pending_deposits queue.

The bug therefore both queued builder deposits that should have been dropped from the queue and never credited the builder's balance, diverging the state root and forcing the indexer to fall back to the beacon API.

Root cause analysis

Reproduced on glamsterdam-devnet-5 at slot 64805 (orphaned by a deep reorg; the state/blocks were fetched from tracoor). Field-level diff vs the consensus post-state:

  • len(PendingDeposits): got=3 expected=2 — one builder deposit wrongly queued
  • Builders[502].balance: got=1507330036 expected=51507330036 — builder short by exactly 50 ETH (the un-applied deposit)

Fix

Implement the Gloas deposit-request handling faithfully per spec:

  • processDepositRequest — builder branch vs. queue
  • apply_deposit_for_builder / add_builder_to_registry / get_index_for_new_builder
  • is_pending_validator / is_builder_withdrawal_credential

Pre-Gloas behaviour is unchanged (the request is still appended to the queue exactly as before).

Verification

Replayed the orphaned range 64799→64862 (3 epoch boundaries) from tracoor — the computed state root now matches consensus at every slot, including 64805. A fresh live replay of 64 blocks near head is also clean. gofmt/go vet clean.

…uest

Gloas (EIP-7732) diverts builder deposits out of the pending_deposits
queue: a deposit request whose pubkey already belongs to a builder, or
one carrying the 0x03 builder credential for a brand-new pubkey, is
applied immediately to the builder registry via apply_deposit_for_builder
and must never enter the queue.

applyExecutionRequests unconditionally appended every deposit request to
PendingDeposits regardless of fork, so on Gloas it both queued builder
deposits that should have been dropped from the queue and never credited
the builder's balance. This diverged the state root from consensus
(observed on glamsterdam-devnet-5 at slot 64805: PendingDeposits length
3 vs 2 and builder 502 short by 50 ETH), forcing the indexer to fall
back to the API.

Implement process_deposit_request, apply_deposit_for_builder,
add_builder_to_registry, get_index_for_new_builder, is_pending_validator
and is_builder_withdrawal_credential per the Gloas spec. Pre-Gloas
behaviour is unchanged.

Verified by replaying the orphaned slot range 64799-64862 from tracoor:
the state root now matches at every slot, including 64805.
@pk910 pk910 enabled auto-merge June 17, 2026 11:58
@pk910 pk910 merged commit ebe7bc1 into master Jun 17, 2026
5 checks passed
@pk910 pk910 deleted the pk910/fix-gloas-state-transition branch June 17, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants