# ePBS / Gloas: Beacon Root Gaps in EIP-4788
## Status quo
In EIP-4788, the beacon root contract is updated during execution of an execution payload.
Under normal (pre-ePBS) conditions:
- Every slot has both:
- a beacon block `B`
- an execution payload `E`
- Each payload inserts the **previous beacon root**
- As a result, **all beacon roots appear on chain with a 1-slot delay**
### Example (normal operation)
```
Slot: 0 1 2 3 4 5
Beacon: B0 B1 B2 - B4 B5
Execution: E0 E1 E2 - E4 E5
Inserted: B0 B1 - B2 B4
```
So effectively:
- continuous coverage (no gaps)
---
## What changes with ePBS / Gloas
With ePBS, some slots may **not include an execution payload**.
When that happens:
- no contract update occurs in that slot
- the chain of insertions is broken
### Example
```
Slot: 0 1 2 3 4 5
Beacon: B0 B1 B2 B3 B4 B5
Execution: E0 E1 - - E4 E5
Inserted: B0 - - B3 B4
Roots available on chain: B0, B3, B4, ...
Missing: B1, B2
```
Insertions:
- `E1` inserts `B0` root
- no `E2` → `B1` not inserted
- no `E3` → `B2` not inserted
- `E4` inserts `B3`
- `E5` inserts `B4`
More generally:
> Any missed payload creates a gap in the on-chain beacon root history.
---
## Why this matters
Applications using EIP-4788 implicitly rely on:
- continuous beacon root availability
- ability to proove any operation within beacon blocks (withdrawals, slashings, etc.)
With ePBS:
- some roots never appear on chain
- proofs involving those blocks require:
- additional parent-root traversal (+3 hashes per parent block, or +22 hases static by proving through the state/parent_roots list)
- larger witnesses
This mainly affects:
- protocols verifying operations included in beacon block (withdrawals, deposits, slashings, ...)
- any contract assuming dense root availability
---
## Options forward
### 1. Do nothing
Accept gaps and shift responsibility to applications.
- Missing roots are reconstructed via parent traversal
- Proofs become larger (extra hashes per missing slot, or large static overhead)
---
### 2. Insert root of last block with payload instead of direct parent
When execution resumes after skipped slots, insert the root of the last block with a payload.
Example:
```
Slot: 0 1 2 3 4 5
Beacon: B0 B1 B2 B3 B4 B5
Execution: E0 E1 - - E4 E5
Inserted: B0 - - B1 B4
```
- All beacon blocks with execution payloads are available on-chain
- Still leaves gaps for empty beacon blocks
---
### 3. Backfill all missed roots
When execution resumes, insert all missing roots:
```
Slot: 0 1 2 3 4 5
Beacon: B0 B1 B2 B3 B4 B5
Execution: E0 E1 - - E4 E5
Inserted: B0 - - B1-3 B4
```
- Requires passing multiple `(timestamp, root)` pairs
- Requires multiple execution frames with the block timestamps of missed payloads for inserting the missed roots (system contract limitation)
---
### 4. Backfill all missed roots & batch insert to a new system contract
Modify the system contract to accept a list of roots instead of only a single one:
```
[(ts0, R0), (ts1, R1), (ts2, R2)]
```
- Simplifies insertion logic
- Breaks existing contract interface assumptions (new contract address)
---
## Core issue
The key question is:
> Should EIP-4788 guarantee continuous, gap-free beacon root availability on chain, or is partial availability acceptable with reconstruction pushed to the application layer?