flashbots / flashbots/mev-boost
uint64 underflow in getHeader msIntoSlot: request arriving before slot start silently skips all relays
- Dominant language
- Go
- Stars
- 1.4k
- Forks
- 292
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
`getHeader` computes `msIntoSlot` with unsigned arithmetic ([`server/get_header.go:65`](https://github.com/flashbots/mev-boost/blob/v1.12/server/get_header.go#L65)):
```go
msIntoSlot := uint64(time.Now().UTC().UnixMilli()) - slotStartTimestamp*1000
```
If the CL's getHeader request arrives even 1ms **before** slot start — sub-ms scheduling jitter between a VC and BN is enough — the subtraction underflows to ~2^64. The late-in-slot guard at [line 86](https://github.com/flashbots/mev-boost/blob/v1.12/server/get_header.go#L86) then sees `msIntoSlot >= lateInSlotTimeMs`, concludes the request is hopelessly late, and returns 204 **without querying any relay**. The CL falls back to a locally built block and the proposer silently loses the MEV reward. This happens with timing games disabled — the guard is always active.
## Production occurrence (mainnet, v1.12, Lighthouse v8.1.3)
Slot 14479147, request arrived 94µs before slot start:
```
time="2026-06-04T11:49:46.999Z" level=info msg="getHeader request start - 18446744073709551615 milliseconds into slot 14479147" ... slot=14479147 ua=Lighthouse/v8.1.3-176cce5 version=1.12
time="2026-06-04T11:49:46.999Z" level=warning msg="getHeader request skipped because we are already past the lateInSlotTimeMs deadline" lateInSlotTimeMs=2000 msIntoSlot=18446744073709551615
time="2026-06-04T11:49:46.999Z" level=info msg="no bid received"
```
`18446744073709551615` = 2^64−1, i.e. −1ms wrapped. Lighthouse logged `Builder error when requesting payload ... falling back to local execution client` and proposed a vanilla block. All relays had bids for the slot and the registration was current — the auction was never attempted.
Across our fleet we count ~38 occurrences since deploying v1.12 in early March (the wrapped observation adds exactly 2^64 to `mev_boost_millisec_into_slot_sum`, which makes the signature easy to detect retroactively). All produced locally-built blocks; none missed.
## Suggested fix
Compute with signed ints and clamp negatives to zero ("very early in slot" = full time budget), mirroring how mev-boost-relay handled its analogous underflow after the [2023 disclosure](https://collective.flashbots.net/t/disclosure-underflow-bug-in-mev-boost-relay/3599). #900 fixes a sibling underflow in the timing-games delay path but does not cover this one — with a wrapped `msIntoSlot` the line-86 guard returns before that code is reached.
Also worth noting: `RecordMsIntoSlot` exports the wrapped value into the histogram, so the metric is corrupted by the same bug.
Happy to provide more logs/metrics if useful.
Contributor guide
Assessment
This issue has not been assessed yet.