flashbots / flashbots/mev-boost

uint64 underflow in getHeader msIntoSlot: request arriving before slot start silently skips all relays

Open
#902 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.