Skip to content

feat(multichain): HyperEVM V4 authoriser clone pin plumbing (RAI-1511) - #274

Merged
thedavidmeister merged 2 commits into
mainfrom
feat/hyperevm-authoriser-pin
Aug 10, 2026
Merged

feat(multichain): HyperEVM V4 authoriser clone pin plumbing (RAI-1511)#274
thedavidmeister merged 2 commits into
mainfrom
feat/hyperevm-authoriser-pin

Conversation

@hardyjosh

@hardyjosh hardyjosh commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
  • LibSafeInvariants.HYPEREVM_CHAIN_ID = 999.
  • BuildPointers emits STOX_PROD_AUTHORISER_V4_CLONE_HYPEREVM = address(0)
    into the generated lib — the unhydrated pin, symmetric with the Ethereum
    clone pin's pre-deploy state.
  • 20260619 clone-deploy script's activeChainClonePin() gains the HyperEVM
    branch, so the same broadcast (already dispatchable on hyperevm via
    manual-broadcast) deploys + configures the HyperEVM authoriser once its
    upstream gates land, and refuses re-deploys after the pin hydrates.

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 workflow option to provision an additional service signer on Base or Ethereum.
    • Added safeguards that validate authoriser readiness, Safe permissions, and required grants before provisioning.
    • Added support for generating Safe transaction artifacts and verifying provisioning results.
    • Added HyperEVM support for V4 authoriser deployment and chain configuration.
    • Expanded grant configuration to include the additional service signer.
  • Bug Fixes

    • Updated deployment checks to reflect the expanded set of required grants.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a Safe-based additional service signer provisioning script for Base and Ethereum. It expands canonical grants, adds HyperEVM deployment support, updates workflow network selection, and adds live-fork validation.

Changes

V4 signer provisioning

Layer / File(s) Summary
Canonical grant and chain contracts
src/lib/LibAuthoriserInvariants.sol, src/lib/LibSafeInvariants.sol
The canonical grant map includes three grants for the additional service signer. The signer cannot hold DEFAULT_ADMIN_ROLE.
Clone configuration and deployment pins
script/20260619-deploy-v4-authoriser-clone.s.sol, script/BuildPointers.sol, test/script/20260619-deploy-v4-authoriser-clone.t.sol
V4 clone configuration mirrors nine grants. HyperEVM uses a generated clone pin. The consistency test expects nine mirrored grants.
Safe signer provisioning flow
script/20260723-provision-additional-service-signer.s.sol, test/script/20260723-provision-additional-service-signer.t.sol
The script validates authoriser, grant, Safe, and role state; simulates missing grants; writes a Safe Tx Builder artifact; and checks revoke/re-grant reversibility. Tests cover Base, Ethereum, fully provisioned state, and partial provisioning. Existing swap live-fork test files are removed.
Multi-network workflow dispatch
.github/workflows/run-script.yaml
The workflow registers the new script, accepts base or ethereum, separates concurrency by network, and passes the selected RPC endpoint to forge script.

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

Possibly related PRs

Suggested reviewers: thedavidmeister

Poem

A rabbit checks each grant in line,
Then signs a Safe bundle fine.
Base and Ethereum paths now gleam,
HyperEVM joins the deployment stream.
Revoke, re-grant, the checks all prove:
The signer is ready to approve.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary HyperEVM V4 authoriser clone pin plumbing changes.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/hyperevm-authoriser-pin

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
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from c61c4b9 to 8e010e5 Compare July 23, 2026 14:14
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-plumbing branch 2 times, most recently from 0e9cc06 to 5539d12 Compare July 23, 2026 22:33
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch 2 times, most recently from 9b894c3 to bb342c0 Compare July 23, 2026 23:05
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-plumbing branch from 5539d12 to 1a96c47 Compare July 23, 2026 23:05
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from bb342c0 to 3e90fed Compare July 23, 2026 23:06
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-plumbing branch 2 times, most recently from 02d425b to b65a13f Compare July 24, 2026 11:20
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from 3e90fed to b14ffe4 Compare July 24, 2026 11:20
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-plumbing branch from b65a13f to 943af94 Compare July 24, 2026 12:21
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from b14ffe4 to 54e4482 Compare July 24, 2026 12:21
@thedavidmeister
thedavidmeister changed the base branch from feat/hyperevm-plumbing to graphite-base/274 July 24, 2026 13:45
@thedavidmeister
thedavidmeister force-pushed the feat/hyperevm-authoriser-pin branch from 54e4482 to eaea4fe Compare July 24, 2026 13:45
@graphite-app
graphite-app Bot changed the base branch from graphite-base/274 to main July 24, 2026 13:46
@thedavidmeister
thedavidmeister force-pushed the feat/hyperevm-authoriser-pin branch from eaea4fe to bc35fb2 Compare July 24, 2026 13:46
@hardyjosh
hardyjosh changed the base branch from main to graphite-base/274 July 24, 2026 14:25
@hardyjosh
hardyjosh force-pushed the graphite-base/274 branch from be1999e to d168ee1 Compare July 24, 2026 14:25
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from bc35fb2 to 860e444 Compare July 24, 2026 14:25
@hardyjosh
hardyjosh changed the base branch from graphite-base/274 to ops/minter-service-wallet July 24, 2026 14:25
@hardyjosh
hardyjosh changed the base branch from main to graphite-base/274 August 10, 2026 09:18
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from b4ea3ba to fa517d7 Compare August 10, 2026 09:18
@hardyjosh
hardyjosh changed the base branch from graphite-base/274 to ops/minter-service-wallet August 10, 2026 09:18
@hardyjosh
hardyjosh changed the base branch from ops/minter-service-wallet to graphite-base/274 August 10, 2026 10:03
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from fa517d7 to b4ea3ba Compare August 10, 2026 10:03
@hardyjosh
hardyjosh changed the base branch from graphite-base/274 to main August 10, 2026 10:03
@hardyjosh
hardyjosh changed the base branch from main to ops/minter-service-wallet August 10, 2026 10:03
@hardyjosh
hardyjosh changed the base branch from ops/minter-service-wallet to graphite-base/274 August 10, 2026 10:04
@hardyjosh
hardyjosh changed the base branch from graphite-base/274 to main August 10, 2026 10:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/20260619-deploy-v4-authoriser-clone.s.sol`:
- Line 134: The grant-slice documentation must match the 16-entry map: in
script/20260619-deploy-v4-authoriser-clone.s.sol lines 134-134, update
references from six grants and range 7..12 to nine grants and 7..15, and from 13
entries to 16 entries; in test/script/20260619-deploy-v4-authoriser-clone.t.sol
lines 335-335, update the replica description from six grants and 7..12 to nine
grants and 7..15.

In `@src/lib/LibSafeInvariants.sol`:
- Around line 197-198: Add the correct HyperEVM token-owner Safe address and
include HYPEREVM_CHAIN_ID in safeForChainId alongside the existing BASE_CHAIN_ID
and ETHEREUM_CHAIN_ID mappings. Ensure DeployV4AuthoriserClone.run() can pass
assertActiveChainTokenOwnerSafe(block.chainid) on chain 999, and add a HyperEVM
fork test covering this pre-flight deployment path.

In `@test/script/20260723-provision-additional-service-signer.t.sol`:
- Around line 59-65: Make the provisioning tests deterministic: in
test/script/20260723-provision-additional-service-signer.t.sol lines 59-65, use
fixed pre-provisioning fork blocks for the happy path or assert the
already-provisioned outcome; in lines 88-102, construct a controlled
partial-grant state so DEPOSIT and WITHDRAW are genuinely missing instead of
mocking CERTIFY alone. Update the PENDING and post-execution lifecycle text in
script/20260723-provision-additional-service-signer.s.sol lines 35-71 to match
the chosen test strategy and current deployment state.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d54f26c1-08bc-4925-b030-082ebb88b993

📥 Commits

Reviewing files that changed from the base of the PR and between 985dfdd and b4ea3ba.

⛔ Files ignored due to path filters (1)
  • src/generated/LibProdDeployV4.sol is excluded by !**/generated/**
📒 Files selected for processing (10)
  • .github/workflows/run-script.yaml
  • script/20260619-deploy-v4-authoriser-clone.s.sol
  • script/20260723-provision-additional-service-signer.s.sol
  • script/BuildPointers.sol
  • src/lib/LibAuthoriserInvariants.sol
  • src/lib/LibSafeInvariants.sol
  • test/script/20260619-deploy-v4-authoriser-clone.t.sol
  • test/script/20260722-swap-remaining-vault-authorisers.t.sol
  • test/script/20260722-swap-rklb-authoriser.t.sol
  • test/script/20260723-provision-additional-service-signer.t.sol
💤 Files with no reviewable changes (2)
  • test/script/20260722-swap-remaining-vault-authorisers.t.sol
  • test/script/20260722-swap-rklb-authoriser.t.sol


/// @notice The number of non-admin grants this script mirrors in.
uint256 internal constant MIRROR_COUNT = 6;
uint256 internal constant MIRROR_COUNT = 9;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep grant-slice documentation consistent with the 16-entry map.

  • script/20260619-deploy-v4-authoriser-clone.s.sol#L134-L134: update six-grant, 7..12, and 13-entry descriptions to nine grants, 7..15, and 16 entries.
  • test/script/20260619-deploy-v4-authoriser-clone.t.sol#L335-L335: update the replica description from six grants and 7..12 to nine grants and 7..15.
📍 Affects 2 files
  • script/20260619-deploy-v4-authoriser-clone.s.sol#L134-L134 (this comment)
  • test/script/20260619-deploy-v4-authoriser-clone.t.sol#L335-L335
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/20260619-deploy-v4-authoriser-clone.s.sol` at line 134, The
grant-slice documentation must match the 16-entry map: in
script/20260619-deploy-v4-authoriser-clone.s.sol lines 134-134, update
references from six grants and range 7..12 to nine grants and 7..15, and from 13
entries to 16 entries; in test/script/20260619-deploy-v4-authoriser-clone.t.sol
lines 335-335, update the replica description from six grants and 7..12 to nine
grants and 7..15.

Comment on lines +197 to +198
/// @notice HyperEVM mainnet chain id.
uint256 internal constant HYPEREVM_CHAIN_ID = 999;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Add the HyperEVM Safe mapping before enabling this chain ID.

safeForChainId in this file handles only BASE_CHAIN_ID and ETHEREUM_CHAIN_ID at Lines 473-480. DeployV4AuthoriserClone.run() calls assertActiveChainTokenOwnerSafe(block.chainid) before deployment, so block.chainid == 999 always reverts with UnsupportedChainForTokenOwnerSafe. The new HyperEVM clone branch is therefore unreachable. Add the correct HyperEVM Safe address and mapping, then add a HyperEVM fork test for this pre-flight path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/LibSafeInvariants.sol` around lines 197 - 198, Add the correct
HyperEVM token-owner Safe address and include HYPEREVM_CHAIN_ID in
safeForChainId alongside the existing BASE_CHAIN_ID and ETHEREUM_CHAIN_ID
mappings. Ensure DeployV4AuthoriserClone.run() can pass
assertActiveChainTokenOwnerSafe(block.chainid) on chain 999, and add a HyperEVM
fork test covering this pre-flight deployment path.

Comment thread test/script/20260723-provision-additional-service-signer.t.sol Outdated
@hardyjosh
hardyjosh changed the base branch from main to graphite-base/274 August 10, 2026 10:18
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from b4ea3ba to fa517d7 Compare August 10, 2026 10:18
@hardyjosh
hardyjosh changed the base branch from graphite-base/274 to ops/minter-service-wallet August 10, 2026 10:18
@hardyjosh
hardyjosh changed the base branch from ops/minter-service-wallet to graphite-base/274 August 10, 2026 11:03
- LibSafeInvariants.HYPEREVM_CHAIN_ID = 999.
- BuildPointers emits STOX_PROD_AUTHORISER_V4_CLONE_HYPEREVM = address(0)
  into the generated lib — the unhydrated pin, symmetric with the Ethereum
  clone pin's pre-deploy state.
- 20260619 clone-deploy script's activeChainClonePin() gains the HyperEVM
  branch, so the same broadcast (already dispatchable on `hyperevm` via
  manual-broadcast) deploys + configures the HyperEVM authoriser once its
  upstream gates land, and refuses re-deploys after the pin hydrates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPs1hCTxusmaSeFKvoc4Kr
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from fa517d7 to f6dee27 Compare August 10, 2026 11:04
@graphite-app
graphite-app Bot changed the base branch from graphite-base/274 to main August 10, 2026 11:04
The 20260619 ceremony executed on HyperEVM 2026-07-24 (manual-broadcast
run 30101296528): authoriser deployed at
0x66566cc91dEAf818859bD4b09B7903ac48998157 — the same address as
Ethereum's (same CloneFactory, same first-nonce CREATE) — with the shared
EIP-1167 codehash, the full 16-entry grant map (both service signers,
verified live) landed on the HyperEVM Safe + service EOAs, and the
deployer renounced. Hydrate the pin from the run's logged address.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPs1hCTxusmaSeFKvoc4Kr
@hardyjosh
hardyjosh force-pushed the feat/hyperevm-authoriser-pin branch from f6dee27 to b814c8e Compare August 10, 2026 11:04
@thedavidmeister

Copy link
Copy Markdown
Contributor

Reviewed b814c8e: pass

Root of the five-PR HyperEVM stack (274 → 275 → 276 → 277 → 278), reviewed as a stack root rather than in isolation.

Two findings I raised and then retracted, both verified against the chain rather than the repo.

I first read STOX_PROD_AUTHORISER_V4_CLONE_HYPEREVM = address(0x66566cc9…) as a copy-paste of the Ethereum pin, because the PR body says it emits address(0). It is neither stale nor wrong: the clone was deployed after the body was written, and identical addresses across chains is what Zoltu CREATE2 produces from the same init code and salt. eth_getCode on HyperEVM returns the EIP-1167 proxy 0x363d3d373d3d3d363d73**2ea0d35d0b1f57c42e6130f298930228bcbfde9b**5af43d…, byte-identical to Ethereum at the same address, so the single pinned STOX_PROD_AUTHORISER_V4_CLONE_CODEHASH covers both. The pinned != address(0) guard at line 200 therefore reads as intended — the pin is hydrated because the deploy happened, and re-dispatch is correctly refused.

I then reported that the PR adds a production pin with no prod check behind it: StoxCrossChainParity.t.sol forks Base and Ethereum only, and no test file mentions HyperEVM. True of this PR alone, and wrong about the change. #277 (pin/hyperevm-invariant-surface) adds 101 lines to that exact parity test plus 16 to StoxProdV4.t.sol. The stack sequences the assertions after the things they assert exist — pin the address, pin the Safe, migrate beacon ownership, then assert the surface, then deploy tokens. Judging a stack root as if it were standalone was my error.

What remains is an 11-line pin-plumbing change: the chain id, the generated pin, the generator line that emits it, and one branch in activeChainClonePin(). The generator and the generated file agree, which is what the copy-artifacts gate exists to prove.

Rulings-conformance: checked against this repo's conventions and the standing rulings for this work.

  • Deterministic deploys are CREATE2 and idempotent — an identical address on a second chain is the expected artifact, not a duplication defect.
  • Enumerate authority from the chain, never from repo greps. OBEYED: both retractions came from eth_getCode against live RPCs, not from reading the constant.
  • *.deploy repos are audited code, internally consistent, tag-released. The pin is generated by BuildPointers.sol and committed to src/generated/, matching byte-for-byte.
  • Coverage, not manual verification. The guarantee this stack owes is at 277, and reviewing that is the check that this pin is actually asserted rather than merely present.

CI: all checks pass — rainix-sol / test, static, legal, build-artifact, git-clean, Graphite mergeability, CodeRabbit. Merging with --merge per the standing no-squash rule for Graphite stacks; 275 is based on this head branch and will need retargeting to main.

@thedavidmeister
thedavidmeister merged commit 13d77f3 into main Aug 10, 2026
7 checks passed
thedavidmeister added a commit that referenced this pull request Aug 10, 2026
Brings in #274, #275 and #276. #275's `RPC_URL_HYPEREVM_FORK` forwarding in
`rainix-sol.yaml` is what lets this branch's own push run resolve the HyperEVM
alias from the secret rather than the rainix preflight's public default, so the
unconditional forks this branch introduces are exercised against the secret
path the new comments describe.
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