Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions .github/workflows/manual-broadcast.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ on:
- 'hyperevm'
# Dispatches an operational broadcast script from `script/` and sends the
# resulting transactions from the CI deploy key (`secrets.PRIVATE_KEY`,
# the same secret `manual-sol-artifacts.yaml` uses for Zoltu impl deploys).
# the same secret `manual-sol-artifacts-0-1-1.yaml` uses for Zoltu impl deploys).
#
# When to use this dispatcher vs. run-script.yaml:
# - `run-script.yaml` is for scripts that emit off-chain artifacts
# (Safe Tx Builder JSON) for a Safe multisig to sign later. Runs
# without `--broadcast`.
# - THIS workflow is for scripts that broadcast on-chain directly from
# the deploy key — same key that runs `manual-sol-artifacts.yaml` for
# the deploy key — same key that runs `manual-sol-artifacts-0-1-1.yaml` for
# impl deploys. Runs with `--broadcast`.
#
# The `slow` flag makes forge wait for each tx to confirm before sending
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
SCRIPT: ${{ inputs.script }}
NETWORK: ${{ inputs.network }}
# PRIVATE_KEY is only available inside this step — matching
# `manual-sol-artifacts.yaml`. The workflow file itself does not
# `manual-sol-artifacts-0-1-1.yaml`. The workflow file itself does not
# persist it anywhere else.
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
run: |
Expand Down
60 changes: 0 additions & 60 deletions .github/workflows/manual-sol-artifacts.yaml

This file was deleted.

54 changes: 31 additions & 23 deletions .github/workflows/package-release.yaml
Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
name: Package Release
on:
push:
branches:
- main
tags:
- sol-v*
jobs:
release:
# rainix-autopublish's job requests contents: write (to push the version-
# bump commit + tag) and id-token: write. This repo's default workflow-token
# permission is read-only, so without granting these here the reusable's
# request exceeds the caller and the run fails at startup. Grant exactly the
# scopes the reusable needs, per workflow, rather than flipping the whole
# repo default to write.
# rainix-tag-release verifies the tag, publishes to soldeer, freezes the
# candidate snapshot into a numbered release dir, and commits it back — so it
# needs contents: write (push the release commit). This repo's default
# workflow-token permission is read-only, so grant that scope here or the
# reusable's request exceeds the caller and the run fails at startup. No
# id-token: nothing in the reusable uses OIDC (Soldeer publishes via
# SOLDEER_API_TOKEN).
permissions:
contents: write
id-token: write
uses: rainlanguage/rainix/.github/workflows/rainix-autopublish.yaml@main
# A DEPLOY repo is on the tag-release lifecycle, not autopublish. A release
# is cut by pushing a `sol-vX.Y.Z` tag (never on merge); deployment is a
# separate manual step. `[package].version` is the LAST released version and
# moves only at release, in lockstep with the frozen snapshot the tag cuts.
# This is the counterpart to library repos, which use rainix-autopublish and
# bump a next-version slot on every merge. Mirrors the rain.factory.deploy
# caller. `cut-release.sh` freezes `src/generated/candidate/` into
# `src/generated/<version>/` (see the script) then regenerates the libs.
uses: rainlanguage/rainix/.github/workflows/rainix-tag-release.yaml@main
with:
# `foundry.toml` version is the NEXT (in-development) release (see #244). On
# merge, publish that version and bump to the next — the bump no longer
# generates artifacts (rainix#267). A version's deploy-pin snapshot is built
# by the PR that changes the bytecode: run
# `forge script ./script/BuildPointers.sol` (after `forge soldeer install`)
# and commit the new `src/generated/<tag>/` snapshot + regenerated deploy
# libs. The LibProdDeploy fork/deploy tests fail if a snapshot is stale, and
# the rainix append-only check (rainix#268) rejects any change to a snapshot
# already on main, so snapshots stay frozen once merged.
soldeer-package: st0x-deploy
# Secrets are passed explicitly (not `inherit`), mirroring this repo's other
# cross-org rainix callers (e.g. rainix-sol.yaml). Only SOLDEER_API_TOKEN is
# required for the publish; the rest are optional and fall back cleanly when
# empty (bot git identity; GITHUB_TOKEN push, since main is unprotected).
tag-prefix: sol-v
snapshot-generate-cmd: bash script/cut-release.sh
# Secrets passed explicitly (not `inherit`), mirroring this repo's other
# cross-org rainix callers — exactly the set rainix-tag-release declares. The
# RPC_URL_*_FORK secrets are what its verify step forks with; omitting them
# reintroduces the "env var not found" verify failure.
secrets:
SOLDEER_API_TOKEN: ${{ secrets.SOLDEER_API_TOKEN }}
PUBLISH_PRIVATE_KEY: ${{ secrets.PUBLISH_PRIVATE_KEY }}
CI_GIT_EMAIL: ${{ secrets.CI_GIT_EMAIL }}
CI_GIT_USER: ${{ secrets.CI_GIT_USER }}
RPC_URL_ARBITRUM_FORK: ${{ secrets.RPC_URL_ARBITRUM_FORK }}
RPC_URL_BASE_FORK: ${{ secrets.RPC_URL_BASE_FORK }}
RPC_URL_BASE_SEPOLIA_FORK: ${{ secrets.RPC_URL_BASE_SEPOLIA_FORK }}
RPC_URL_ETHEREUM_FORK: ${{ secrets.RPC_URL_ETHEREUM_FORK }}
RPC_URL_FLARE_FORK: ${{ secrets.RPC_URL_FLARE_FORK }}
RPC_URL_POLYGON_FORK: ${{ secrets.RPC_URL_POLYGON_FORK }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
52 changes: 22 additions & 30 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,36 +283,28 @@ library. When making changes to contract source:

## Deployment

`script/Deploy.sol` dispatches based on `DEPLOYMENT_SUITE` env var. One contract
per suite to avoid Zoltu factory nonce issues. Every suite targets the
`LibProdDeployV4` (rain.vats 0.1.6) pins and broadcasts to every network in
`LibStoxDeployNetworks.supportedNetworks()` (Base + Ethereum mainnet) — the
Zoltu deploy is idempotent per network, so a suite run skips networks that
already carry the artifact and deploys the identical bytecode to the ones that
don't. The frozen V1/V2 deployments in `LibProdDeployV1` / `LibProdDeployV2` are
an audit trail and are not redeployable from the current source.

- `stox-receipt-v4` — deploys StoxReceipt
- `stox-receipt-vault-v4` — deploys StoxReceiptVault
- `stox-wrapped-token-vault-v4` — deploys StoxWrappedTokenVault
- `stox-wrapped-token-vault-beacon-v4` — deploys StoxWrappedTokenVaultBeacon
(depends on StoxWrappedTokenVault)
- `stox-wrapped-token-vault-beacon-set-deployer-v4` — deploys
StoxWrappedTokenVaultBeaconSetDeployer (depends on beacon)
- `stox-offchain-asset-receipt-vault-beacon-set-deployer-v4` — deploys
StoxOffchainAssetReceiptVaultBeaconSetDeployer (depends on StoxReceipt,
StoxReceiptVault)
- `stox-unified-deployer-v4` — deploys StoxUnifiedDeployer (depends on both
beacon-set deployers)
- `stox-offchain-asset-receipt-vault-authorizer-v1-v4` — deploys
StoxOffchainAssetReceiptVaultAuthorizerV1
- `stox-offchain-asset-receipt-vault-payment-mint-authorizer-v1-v4` — deploys
StoxOffchainAssetReceiptVaultPaymentMintAuthorizerV1
- `stox-corporate-actions-facet-v4` — deploys StoxCorporateActionsFacet

Manual deployment runs via the GitHub Actions workflow
(`manual-sol-artifacts.yaml`), which broadcasts each suite to every supported
network in one run.
Production deploys run the audited, version-specific script
`script/DeployProdV4_0_1_1.sol` — never the current source. It ships the stored
audited-0.1.1 creation bytecode (`LibProdDeployV4.*_CREATION_CODE_0_1_1`, the
exact bytes the 0.1.1 audit covers) and asserts each contract against its
`_0_1_1` address/codehash pin, so the on-chain result is the audited deployment
regardless of what the current source compiles to. Each dispatch deploys one
contract suite (`DEPLOYMENT_SUITE`, one contract per suite to avoid Zoltu
factory nonce issues) to a single bootstrap network (`DEPLOYMENT_NETWORK` —
Ethereum or HyperEVM), via the `manual-sol-artifacts-0-1-1.yaml` GitHub Actions
workflow; the Zoltu deploy is idempotent per network. Suites are deployed in the
workflow's listed order — later suites reference earlier ones via dependency
pointers, so an out-of-order run trips the dep-codehash check. The orchestrator
(introduced at 0.1.2) is not part of the audited 0.1.1 set.

The rolling `candidate` snapshot (`src/generated/candidate/`) is NEVER a deploy
target — it exists only so tests exercise the current source and
`testCandidateSelfConsistent` pins source↔snapshot integrity. When a later
version is audited it gets its own frozen numbered snapshot (cut from
`candidate` by a `sol-vX.Y.Z` release tag; see `script/cut-release.sh`) and its
own `script/DeployProdV4_0_1_N.sol`. The frozen V1/V2 deployments in
`LibProdDeployV1` / `LibProdDeployV2` are an audit trail and are not
redeployable from the current source.

## Naming Conventions

Expand Down
2 changes: 1 addition & 1 deletion script/20260619-deploy-v4-authoriser-clone.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ error GrantsSliceOutOfRange(uint256 startIndex, uint256 sliceLength, uint256 gra
/// key executes them in sequence in one `forge script --broadcast`
/// invocation. Dispatched via `.github/workflows/manual-broadcast.yaml`,
/// which broadcasts as `secrets.PRIVATE_KEY` — the same CI-held deploy
/// key `manual-sol-artifacts.yaml` uses for Zoltu impl deploys. The Safe
/// key `manual-sol-artifacts-0-1-1.yaml` uses for Zoltu impl deploys. The Safe
/// never signs anything for this deploy: the whole clone-configuration
/// ceremony collapses into a workflow-dispatch broadcast matching the
/// impl-deploy pattern the ops flow already uses.
Expand Down
Loading
Loading