Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
073da89
feat(deploy): V4 authoriser clone-deploy + grants-mirror script
Jun 19, 2026
ee1237c
test(deploy): V4 authoriser clone-mirror via lib-pin + subclass-override
Jun 19, 2026
2b786b8
Merge remote-tracking branch 'origin/main' into feat/rai-793-deploy-v…
thedavidmeister Jun 30, 2026
912703a
chore(deps): point V4 authoriser clone test at rain-deploy 0.1.4
thedavidmeister Jun 30, 2026
a26a66e
test(deploy): exhaustively cover V4 authoriser clone reject paths
thedavidmeister Jun 30, 2026
2df71b2
test(deploy): cover NewClone-extraction reverts + DRY EIP-1167 bytes …
thedavidmeister Jun 30, 2026
02bb9d4
fix(deploy): mirror grant-state pre-flight in verify(); verify agains…
thedavidmeister Jun 30, 2026
ff1b6b5
ci: pin run-script.yaml external actions to SHA; note verify() is loc…
thedavidmeister Jun 30, 2026
7a3cc1c
ci: pin git-clean + multisig-artifact external actions to SHA
thedavidmeister Jun 30, 2026
a6f9ba3
fix(deploy): reject non-CALL ops in Tx Builder JSON; correct grants d…
thedavidmeister Jun 30, 2026
c9a10af
test(deploy): add failing repro for the grants-bundle SafeTxHash model
thedavidmeister Jul 1, 2026
9638dd4
ci: disable credential persistence on read-only checkout steps
thedavidmeister Jul 1, 2026
0c00b17
test(deploy): name grants-bundle SafeTxHash tests for behaviour
thedavidmeister Jul 1, 2026
62bccb2
test(safe-ops): cover multi-transaction Tx Builder emit/parse
thedavidmeister Jul 1, 2026
626746b
fix(deploy): bind the grants-bundle SafeTxHash to its MultiSend execu…
thedavidmeister Jul 1, 2026
efd42fb
test(deploy): cover that the authoriser clone actually authorizes its…
thedavidmeister Jul 1, 2026
280c299
test(deploy): add signed end-to-end deploy + grants coverage
thedavidmeister Jul 1, 2026
c9265bc
fix(safe-ops): reject non-CALL ops in encodeMultiSend, not just at emit
thedavidmeister Jul 1, 2026
d5b5ad6
feat(guards): enforce the NatSpec-claimed invariants with fail-fast g…
thedavidmeister Jul 1, 2026
741b8a2
ci(run-script): job name + concurrency, env-var input hardening, fix …
thedavidmeister Jul 2, 2026
0e1d85b
refactor(safe-ops): extract shared CALL-only guard helper
thedavidmeister Jul 2, 2026
977de71
ci: retrigger checks
thedavidmeister Jul 2, 2026
e056860
ci: retrigger checks after billing unlock
thedavidmeister Jul 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/git-clean.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ jobs:
git-clean:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nixbuild/nix-quick-install-action@v30
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v6
uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/multisig-artifact.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ jobs:
build-artifact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@v17
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: DeterminateSystems/nix-installer-action@21a544727d0c62386e78b4befe52d19ad12692e3 # v17
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install Soldeer dependencies
run: nix develop --command forge soldeer install
- name: Build Tx Builder artifact (dry-run)
Expand All @@ -38,7 +40,7 @@ jobs:
--no-storage-caching
'
- name: Upload Tx Builder JSON
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: safe-threshold-tx-builder-json
path: out/*.json
Expand Down
101 changes: 101 additions & 0 deletions .github/workflows/run-script.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: run-script
on:
workflow_dispatch:
inputs:
script:
description: 'Operational script to dispatch'
required: true
type: choice
options:
# Append-only registry: add new entries at the bottom; never reorder
# or delete. Re-dispatching a historical (executed) script must
# remain possible — a signer/auditor may want to re-derive its
# bundle to verify what landed on-chain.
#
# Each entry is the date-prefixed filename (without `.s.sol`) of a
# script under `script/`. Convention: `YYYYMMDD-<kebab-name>`,
# where the date is the day the script was added to this dropdown.
# Execution status (PENDING / EXECUTED + SafeTxHash) lives in the
# script's file-level NatSpec — this dropdown is a registry of
# *which* scripts exist, not *whether* they've run.
- 20260619-deploy-v4-authoriser-clone
sig:
description: 'Entrypoint to dispatch (default: run())'
required: true
type: choice
default: 'run()'
options:
# Append-only registry of entrypoint signatures. The dispatcher does
# not validate that the selected script implements the selected
# signature — `forge script` will surface a clear revert if not.
#
# `verify(string)` is intentionally NOT listed: it is always a local
# signer-side check run against a downloaded artifact — it takes a
# JSON path argument this dispatcher can't supply and runs off-chain
# on the signer's machine, not in CI.
- 'run()'
- 'mirrorGrants()'
# Manually dispatches an operational script from `script/` and uploads any
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# JSON it writes to `out/` as a build artifact.
#
# Operational scripts produce off-chain artifacts (Safe Tx Builder JSON,
# signer briefs) under `out/`. They run a full on-chain pre-flight, simulate
# the post-state, emit the artifact, and log the canonical hash that signers
# must verify. The dry-run uses an unpinned Base head fork so any drift in
# the underlying contracts trips the pre-flight here before a signer ever
# sees the bundle.
#
# Why a single dispatcher rather than one workflow per script:
# - The Actions sidebar stays tight as more scripts accumulate.
# - Boilerplate (nix install, soldeer install, artifact upload) lives in
# one place.
# - Adding a new script is a single yaml entry + a new file under
# `script/`, no new workflow file.
#
# The `sig` input lets a single script expose multiple entrypoints (e.g.
# `run()` and `mirrorGrants()` on the V4 authoriser deploy) without
# splitting them into separate dispatcher entries. `forge --sig` is the
# canonical way to pick which function `forge script` calls.
jobs:
run:
name: Run operational script
runs-on: ubuntu-latest
Comment thread
thedavidmeister marked this conversation as resolved.
# Serialise dispatches of the same script+sig so overlapping runs don't
# race on the shared out/ artifacts; distinct entrypoints run in parallel.
concurrency:
group: run-script-${{ inputs.script }}-${{ inputs.sig }}
cancel-in-progress: false
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
persist-credentials: false
- uses: DeterminateSystems/nix-installer-action@21a544727d0c62386e78b4befe52d19ad12692e3 # v17
- name: Install Soldeer dependencies
run: nix develop --command forge soldeer install
- name: Run script
env:
BASE_RPC_URL: ${{ secrets.RPC_URL_BASE_FORK }}
# Pass the choice inputs via env rather than template-expanding them
# into the command, so a dispatch (even one crafted via the API) is
# used as a literal argument and cannot inject shell.
SCRIPT: ${{ inputs.script }}
SIG: ${{ inputs.sig }}
run: |
nix develop --command forge script "script/${SCRIPT}.s.sol" \
--sig "${SIG}" \
--rpc-url base \
--no-storage-caching
- name: Upload script output
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
# Artifact name encodes both script + sig so the run() and
# mirrorGrants() outputs of the same script don't clobber each other
# if both are dispatched in the same operational window. The sig is
# used verbatim, parentheses included — GitHub artifact names permit
# them.
name: ${{ inputs.script }}-${{ inputs.sig }}-out
path: out/*.json
# `warn` instead of `error`: some operational scripts may not
# produce a JSON artifact (e.g. a pure verifier or a status
# printer). Falling back to a warning keeps the dispatcher generic.
if-no-files-found: warn
Comment thread
thedavidmeister marked this conversation as resolved.
Loading
Loading