Skip to content

feat(script): author the follow-up authoriser swap for still-V3 vaults - #269

Merged
thedavidmeister merged 5 commits into
mainfrom
feat/20260722-swap-remaining-authorisers
Jul 23, 2026
Merged

feat(script): author the follow-up authoriser swap for still-V3 vaults#269
thedavidmeister merged 5 commits into
mainfrom
feat/20260722-swap-remaining-authorisers

Conversation

@hardyjosh

@hardyjosh hardyjosh commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The executed 20260623 batch covered every vault in the table at signing
time; the six tokens deployed after it (MU/AMD/AVGO/AMAT/LRCX/TTWO) came up
on the V3 authoriser and red-line the strict uniform-authoriser invariants
until swapped. Add 20260722-swap-remaining-vault-authorisers, a run-script
Safe Tx Builder authoring that is deliberately SELF-SCOPING: it reads every
production vault's live authorizer() and targets exactly the still-V3
ones — a later un-swapped vault is picked up by re-dispatch, an unknown
authoriser aborts the authoring (UnexpectedVaultAuthoriser), and an
all-swapped table refuses to author an empty bundle (NoVaultsLeftToSwap).

Pre-flight pins the clone (codehash + full grant map incl. the seven
auto-granted admins on the Safe); post-state asserts STRICT authoriser
uniformity across the whole table plus uniform Safe ownership.

Notable finding, proven by the n+1 walk: the swap is ONE-WAY. The V4 vault
impl validates the incoming authoriser and reverts
AuthorizerMissingCorporateActionAdmin for V3, so rollback is structurally
impossible; recovery is forward-only (the Safe re-points at any
V4-compatible authoriser). The n+1 leg proves that class clears the live
threshold instead of simulating an impossible V3 rollback.

Registered in run-script.yaml (append-only). Fork suite: happy path checks
the authored bundle matches the live-derived target set tx-for-tx; inverted
guards cover the empty-set and unknown-authoriser aborts.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01VPs1hCTxusmaSeFKvoc4Kr

Summary by CodeRabbit

  • New Features

    • Added a controlled process to update remaining production receipt vaults to the approved V4 authorizer.
    • Added safeguards that validate configuration, detect unexpected authorizers, and verify the resulting state.
    • Added Safe transaction artifact generation for review and execution.
    • Added the process to the manual workflow dispatcher.
  • Tests

    • Added coverage for completed migrations and unexpected authorizer configurations.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 636d1b60-4609-4bb4-befb-b3f39cab9321

📥 Commits

Reviewing files that changed from the base of the PR and between 4dd480d and 9a941bd.

📒 Files selected for processing (3)
  • .github/workflows/run-script.yaml
  • script/20260722-swap-remaining-vault-authorisers.s.sol
  • test/script/20260722-swap-remaining-vault-authorisers.t.sol

📝 Walkthrough

Walkthrough

Adds a Solidity script that authorizes Safe transactions to migrate remaining production receipt vaults from the V3 to the pinned V4 authoriser clone, with validation, simulation, artifact emission, and forked failure-path tests. The workflow dispatcher exposes the script.

Changes

Vault authoriser migration

Layer / File(s) Summary
Authoriser validation and Safe bundle
script/20260722-swap-remaining-vault-authorisers.s.sol
Validates the V4 clone, selects V3-authorised vaults, builds Safe setAuthorizer calls, simulates them, checks post-state invariants, and emits a transaction artifact.
Forked failure-path coverage
test/script/20260722-swap-remaining-vault-authorisers.t.sol
Tests the no-target and unexpected-authoriser revert paths on a live fork.
Workflow dispatch registration
.github/workflows/run-script.yaml
Adds the new script to the workflow dispatch selection list.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dispatcher
  participant SwapRemainingVaultAuthorisers
  participant Safe
  participant ReceiptVaults
  Dispatcher->>SwapRemainingVaultAuthorisers: invoke run()
  SwapRemainingVaultAuthorisers->>ReceiptVaults: inspect authorizer()
  SwapRemainingVaultAuthorisers->>Safe: simulate setAuthorizer(V4 clone)
  Safe-->>SwapRemainingVaultAuthorisers: return simulation results
  SwapRemainingVaultAuthorisers->>ReceiptVaults: verify V4 clone authorisers
Loading

Possibly related PRs

Poem

I’m a bunny with a bundle so neat,
V3 hops out as V4 takes its seat.
Safe calls line up, checks guard the way,
Fork tests catch wrong hops astray.
The dispatcher now knows where to play!

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/20260722-swap-remaining-authorisers

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
.github/workflows/run-script.yaml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'


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.

hardyjosh commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@hardyjosh
hardyjosh marked this pull request as ready for review July 22, 2026 10:38
@hardyjosh
hardyjosh changed the base branch from feat/base-tokens-batch2 to graphite-base/269 July 22, 2026 13:35
@hardyjosh
hardyjosh force-pushed the feat/20260722-swap-remaining-authorisers branch from 836b556 to b147647 Compare July 22, 2026 13:36
@hardyjosh
hardyjosh changed the base branch from graphite-base/269 to feat/rklb-production-token July 22, 2026 13:36
@hardyjosh
hardyjosh force-pushed the feat/20260722-swap-remaining-authorisers branch 2 times, most recently from 04f4cb5 to 529b402 Compare July 22, 2026 13:48
@hardyjosh
hardyjosh changed the base branch from feat/rklb-production-token to graphite-base/269 July 22, 2026 13:50
@hardyjosh
hardyjosh changed the base branch from graphite-base/269 to pin/ethereum-token-table July 22, 2026 13:50
@hardyjosh
hardyjosh changed the base branch from pin/ethereum-token-table to graphite-base/269 July 22, 2026 13:54
@hardyjosh
hardyjosh force-pushed the graphite-base/269 branch from da20cf9 to 0aae222 Compare July 22, 2026 13:54
@hardyjosh
hardyjosh force-pushed the feat/20260722-swap-remaining-authorisers branch from 529b402 to c272bde Compare July 22, 2026 13:54
@hardyjosh
hardyjosh changed the base branch from graphite-base/269 to ops/rklb-catchup-scripts July 22, 2026 13:54
The executed 20260623 batch covered every vault in the table at signing
time; the six tokens deployed after it (MU/AMD/AVGO/AMAT/LRCX/TTWO) came up
on the V3 authoriser and red-line the strict uniform-authoriser invariants
until swapped. Add `20260722-swap-remaining-vault-authorisers`, a run-script
Safe Tx Builder authoring that is deliberately SELF-SCOPING: it reads every
production vault's live `authorizer()` and targets exactly the still-V3
ones — a later un-swapped vault is picked up by re-dispatch, an unknown
authoriser aborts the authoring (`UnexpectedVaultAuthoriser`), and an
all-swapped table refuses to author an empty bundle (`NoVaultsLeftToSwap`).

Pre-flight pins the clone (codehash + full grant map incl. the seven
auto-granted admins on the Safe); post-state asserts STRICT authoriser
uniformity across the whole table plus uniform Safe ownership.

Notable finding, proven by the n+1 walk: the swap is ONE-WAY. The V4 vault
impl validates the incoming authoriser and reverts
`AuthorizerMissingCorporateActionAdmin` for V3, so rollback is structurally
impossible; recovery is forward-only (the Safe re-points at any
V4-compatible authoriser). The n+1 leg proves that class clears the live
threshold instead of simulating an impossible V3 rollback.

Registered in run-script.yaml (append-only). Fork suite: happy path checks
the authored bundle matches the live-derived target set tx-for-tx; inverted
guards cover the empty-set and unknown-authoriser aborts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPs1hCTxusmaSeFKvoc4Kr
@hardyjosh
hardyjosh force-pushed the feat/20260722-swap-remaining-authorisers branch from c272bde to 3c5ac54 Compare July 22, 2026 21:35
@hardyjosh
hardyjosh force-pushed the ops/rklb-catchup-scripts branch from 0aae222 to 2e2ae2c Compare July 22, 2026 21:35
thedavidmeister and others added 3 commits July 23, 2026 07:32
Every production vault is on the V4 authoriser: MU, AMD, AVGO, AMAT, LRCX and
TTWO all report authorizer() == STOX_PROD_AUTHORISER_V4_CLONE on Base as of
2026-07-23, so nothing remains on V3 and the bundle this script authors has
been signed and executed. The header still said PENDING.

Dated by verification rather than by the Safe tx -- the execution block is not
recorded here, and stamping a date I have not established is the same defect
as the stale marker.

The happy path authored against a live-derived target set, so it went red the
moment the set emptied; its own comment called for retiring it at exactly this
point. The empty-set refusal and the unknown-authoriser abort remain, and
those are the two that still carry weight for a script kept for re-dispatch.

Kept rather than retired: it reads every vault's live authorizer() and targets
whatever is still on V3, so re-dispatch is how a future vault that comes up on
the wrong authoriser gets swapped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
Contributor

Reviewed f3951fd: approve

Verified against the actual branch tip f3951fd (the main merge), not the PR object's head.sha, which is stale at 98b8ad2git ls-remote and the git-ref API both report f3951fd.

CI on f3951fd:

  • rainix-sol / test — one failure, testDeployTag (0_1_8 != 0_1_27), the known soldeer autopublish drift: each release bumps foundry.toml while the test compares a pinned 0_1_8.
  • git-clean — "Assert committed artifacts match freshly built".

Both are inherited: main at 592d002 is red on the same two jobs. This branch adds no new failure.

The four run-once guard failures visible on the older 98b8ad2 (testRunOnceGatePassesOnTheShippedTable, testRunOnceGateInspectsEveryLeg, testRunOnceGateFiresOnAHydratedTable, testRunRevertsWhenCoreNotDeployed) are resolved by the main merge, which brings in #279's local virginTable(...) fixture. Those tests no longer read the live hydrated productionTokensEthereum() table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@thedavidmeister

Copy link
Copy Markdown
Contributor

Reviewed 9a941bd: approve

Tip is 9a941bd, an empty resync commit on f3951fd — content identical to the tree verified above. Reds remain testDeployTag + git-clean, both inherited from main (592d002). Merging at the user's explicit direction despite the PR-object head desync.

@thedavidmeister
thedavidmeister merged commit 3b6fca4 into main Jul 23, 2026
1 of 2 checks passed
hardyjosh pushed a commit that referenced this pull request Jul 23, 2026
Per review: the wallet is first-class state, not a drive-by grant.

- LibAuthoriserInvariants.GRANTEE_SERVICE_MINTER_3D0C pinned +
  expectedGrants grows to 13 (DEPOSIT + WITHDRAW for the minter EOA; the
  address is chain-shared, the grants per-chain). Every existing consumer
  of the map now ENFORCES the provisioning: the per-chain clone-grant
  assertions (StoxProdV4PostSwap on Base, the Ethereum pin test) and the
  cross-chain parity authoriser leg (assertExpectedGrants per chain) go
  RED on each chain until its 20260723 bundle executes — the forcing
  function, exactly like every other migration in this repo.
- 20260619 clone-deploy MIRROR_COUNT 6 -> 8 (slice guard + suite updated):
  future chain bootstraps (HyperEVM) auto-provision the minter wallet at
  authoriser-deploy time, no Safe signing needed there.
- The 20260723 authoring script now references the canonical pin and its
  drift guard skips the wallet's own (deliberately not-yet-true) rows.
- Stale hardcoded grant counts in docs made count-agnostic.

Sequencing note: the pending authoriser-swap authorings (#269/#271) carry
full-map drift guards, so re-dispatching them AFTER this merges and BEFORE
the minter bundles execute reverts on the minter rows — dispatch order:
execute the already-signed swap bundles and the minter bundles in any
order on-chain, but author from the matching refs.

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