Skip to content

Add the orchestrator beacon to the governed beacon set - #334

Open
thedavidmeister wants to merge 4 commits into
2026-08-25-upgrade-fleet-to-0-1-30from
2026-08-29-issue-333-orchestrator-beacon-in-governed-set
Open

Add the orchestrator beacon to the governed beacon set#334
thedavidmeister wants to merge 4 commits into
2026-08-25-upgrade-fleet-to-0-1-30from
2026-08-29-issue-333-orchestrator-beacon-in-governed-set

Conversation

@thedavidmeister

Copy link
Copy Markdown
Contributor

Closes #333. Stacked on #325.

The gap

prodBeaconsForChainId returned three beacons. Production has four. The fourth is the orchestrator beacon, and after #324 it holds mint/burn authority over the other three — so the most governance-sensitive beacon in the system was the one surface 20260729-migrate-governance-to-timelock could never reach, because it walks that array.

Nothing failed. GovernanceTimelockMigration.t.sol only checks the enumerated three, so it stayed green while the orchestrator beacon sat outside the migration entirely. Left alone past the 2026-10-01 deadline it is stranded, upgradable by whoever owns it, while every other beacon moves under the timelock.

What changed

  • LibProdBeaconsBase / LibProdBeacons0_1_1: beacons() and implementations() widened to address[4], orchestrator beacon and its impl appended so existing indices hold.
  • LibBeaconInvariants: ORCHESTRATOR_BEACON_INDEX = 3 beside the three constants Fleet upgrade bundle: receipt + receipt-vault beacons to audited 0.1.30 #325 added; prodBeaconsForChainId returns address[4].
  • prodBeaconCodehashesForChainId, new and index-aligned. The set now spans two build generations: the token beacons are the V1 build (858 bytes, 0x8e95867e…), the orchestrator beacon is OZ 5.6.1 at the current optimizer_runs (728 bytes, 0x448cd063…). A single pin reverts on it. Both _assertDeployedPinnedBeacon and _selectBeaconTargets in the timelock migration hardcoded one constant; both now take the per-beacon value.
  • Consumers that iterate are otherwise unchanged — they pick the fourth member up for free.
  • MigrateBeaconOwners deliberately keeps its own three-element list: it is a historical executed script with its own literals, not a consumer of this accessor.

Sequencing — this needs #317 broadcast first

The orchestrator beacon is still owned by the deploy EOA 0x8E4bdeec… on all three chains; #317 transfers it to the chain Safe and has not been run. Until it is, assertProdBeaconsOwnedByChainSafe fails on the new member, because it requires one owner across the set.

That is sequencing, not a code gap, and it is verified rather than assumed. Simulating #317 - a single transferOwnership pranked from the EOA - then asserting the widened set:

[PASS] testBaseAfter317()
[PASS] testEthereumAfter317()
[PASS] testHyperEvmAfter317()

Draft until #317 has been broadcast on Base, Ethereum and HyperEVM.

QA

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 83f00c06-e5b7-4e35-8dcd-9cf23d7428ba

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

baku-ccron and others added 2 commits August 31, 2026 15:34
`prodBeaconsForChainId` returned three beacons while production has four. The
fourth is the orchestrator beacon, which after #324 holds mint/burn authority
over the other three, and the governance-timelock migration walks that array —
so the most governance-sensitive beacon in the system was the one surface the
migration could never reach. Nothing failed: `GovernanceTimelockMigration.t.sol`
only checks the enumerated three, so it stayed green.

Widened to `address[4]` in `LibProdBeaconsBase` / `LibProdBeacons0_1_1` and
`LibBeaconInvariants`, appended so the existing indices hold, with
`ORCHESTRATOR_BEACON_INDEX` beside the three named in #325. Every consumer that
iterates picks the new member up unchanged.

`prodBeaconCodehashesForChainId` is new and index-aligned. The set now spans two
build generations — the token beacons are the V1 build at 858 bytes, the
orchestrator beacon is OZ 5.6.1 at the current optimizer settings and 728 bytes
— so a single pin reverts on it. Both the library's own check and
`_selectBeaconTargets` in the timelock migration took one constant; both now
take the per-beacon value. Without this the widened migration reverts
`MigrationBeaconCodehashMismatch` and no chain migrates at all.

`MigrateBeaconOwners` keeps its own three-element list: it is a historical
executed script with its own literals rather than a consumer of this accessor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The orchestrator beacon joins the governed set mid-lifecycle: its
constructor bakes the deploy EOA as owner and the
20260818-migrate-orchestrator-beacon-owner EOA broadcast moves it to
the chain's Safe. The set's two ownership sweeps
(assertProdBeaconsOwnedBy and assertProdBeaconsOwnershipMigration) now
accept that baked pre-state for the orchestrator index until the
beacon-owner migration deadline - the same window
LibOrchestratorInvariants.assertBeaconSet applies - and hard-require
the expected owner after it.

Live today on all three chains (closure + instance dispatched, beacon
still EOA-owned) the sweeps otherwise red-lined every prod surface;
with the window the fleet prod walk reaches the authoring state and
proves all 41 production tokens state-preserving across the simulated
upgrade per chain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbsbYN4C4YDa8pu9DdudoX
@hardyjosh
hardyjosh force-pushed the 2026-08-29-issue-333-orchestrator-beacon-in-governed-set branch from a94712a to 2f96db0 Compare August 31, 2026 15:54
Third surface of the same mid-lifecycle join: the governance-timelock
migration's beacon selection required every governed beacon Safe-owned
before authoring, so the still-EOA-owned orchestrator beacon tripped
UnexpectedBeaconOwner on every chain. The selection now skips it while
its own EOA -> Safe migration is pending (same deadline window as the
ownership sweeps); a later dispatch picks it up once Safe-owned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbsbYN4C4YDa8pu9DdudoX
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