From 002a564d4ab3a92db09850e5ef34ea4fd02cc189 Mon Sep 17 00:00:00 2001 From: Josh Hardy Date: Mon, 6 Jul 2026 21:57:59 +0000 Subject: [PATCH 1/6] feat(deploy): add Ethereum mainnet to the ST0x deploy networks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Ethereum mainnet as the second ST0x production network (RAI-1094 decision, RAI-1095): - LibStoxDeployNetworks gains an ETHEREUM constant (rain-deploy 0.1.4 predates Rain on Ethereum mainnet and has no constant of its own; the Zoltu factory is live there at the canonical address, verified RAI-1211) and supportedNetworks() now returns Base + Ethereum. Every Deploy.sol suite broadcast covers both networks; the per-network idempotence of LibRainDeploy.deployToNetworks keeps re-runs no-ops on already-deployed networks. - foundry.toml wires the ethereum rpc alias (ETHEREUM_RPC_URL) and etherscan key. - StoxProdV4Test gains testProdDeployEthereumV4 pinning the V4 receipt vault impl + corporate-actions facet at their deterministic Zoltu addresses on Ethereum. Red until the suites are broadcast there — the same fails-until-live-execution pattern as the rest of this stack. Ethereum bootstraps directly at V4: no StoxProdV2 entry, the frozen pre-V4 artifacts were never deployed there. CI note: the rainix reusable workflows do not yet map an RPC_URL_ETHEREUM_FORK secret/var to ETHEREUM_RPC_URL; a sibling rainix PR adds that. Until it merges, the Ethereum fork test needs ETHEREUM_RPC_URL supplied locally. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VPs1hCTxusmaSeFKvoc4Kr --- CLAUDE.md | 13 ++++++++---- foundry.toml | 2 ++ src/lib/LibStoxDeployNetworks.sol | 26 ++++++++++++++++++++--- test/src/concrete/deploy/StoxProdV4.t.sol | 11 ++++++++++ test/src/lib/LibStoxDeployNetworks.t.sol | 16 ++++++++++---- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0d91eda1..8abce2d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -285,9 +285,13 @@ library. When making changes to contract source: `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 deploys to Base; the frozen pre-V4 -deployments live in `LibProdDeployV1` / `LibProdDeployV2` as an audit trail and -are not redeployable from the current source. +`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 pre-V4 deployments live in `LibProdDeployV1` / +`LibProdDeployV2` as an audit trail and are not redeployable from the current +source; Ethereum bootstraps directly at V4 with no pre-V4 history. - `stox-receipt-v4` — deploys StoxReceipt - `stox-receipt-vault-v4` — deploys StoxReceiptVault @@ -308,7 +312,8 @@ are not redeployable from the current source. - `stox-corporate-actions-facet-v4` — deploys StoxCorporateActionsFacet Manual deployment runs via the GitHub Actions workflow -(`manual-sol-artifacts.yaml`), which deploys to Base. +(`manual-sol-artifacts.yaml`), which broadcasts each suite to every supported +network in one run. ## Naming Conventions diff --git a/foundry.toml b/foundry.toml index 5b01fe6e..841d3143 100644 --- a/foundry.toml +++ b/foundry.toml @@ -70,6 +70,7 @@ recursive_deps = false arbitrum = "${ARBITRUM_RPC_URL}" base = "${BASE_RPC_URL}" base_sepolia = "${BASE_SEPOLIA_RPC_URL}" +ethereum = "${ETHEREUM_RPC_URL}" flare = "${FLARE_RPC_URL}" polygon = "${POLYGON_RPC_URL}" @@ -77,5 +78,6 @@ polygon = "${POLYGON_RPC_URL}" arbitrum = { key = "${CI_DEPLOY_ARBITRUM_ETHERSCAN_API_KEY}" } base = { key = "${CI_DEPLOY_BASE_ETHERSCAN_API_KEY}" } base_sepolia = { key = "${CI_DEPLOY_BASE_SEPOLIA_ETHERSCAN_API_KEY}" } +ethereum = { key = "${CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY}" } flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}" } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}" } diff --git a/src/lib/LibStoxDeployNetworks.sol b/src/lib/LibStoxDeployNetworks.sol index 7aa036ac..0cba8378 100644 --- a/src/lib/LibStoxDeployNetworks.sol +++ b/src/lib/LibStoxDeployNetworks.sol @@ -8,12 +8,32 @@ import {LibRainDeploy} from "rain-deploy-0.1.4/src/lib/LibRainDeploy.sol"; /// @notice Single source of truth for the networks the ST0x production deploy /// broadcasts to. `script/Deploy.sol` reads this instead of hardcoding the list /// inline, so the supported-network set lives in one place. ST0x deploys to -/// Base only. +/// Base and Ethereum mainnet. +/// +/// `LibRainDeploy.deployToNetworks` is idempotent per network (an +/// already-deployed contract is skipped, its codehash still verified), so +/// re-running a suite after adding a network here is a no-op on the networks +/// that already carry the artifact and a fresh Zoltu deploy on the ones that +/// don't. That per-network idempotence is what keeps every chain in this list +/// bytecode-identical by construction: one suite run covers all of them. library LibStoxDeployNetworks { + /// @notice Ethereum mainnet network name. Matches the `[rpc_endpoints]` + /// alias in `foundry.toml` (resolved from `ETHEREUM_RPC_URL`), the same + /// pattern as every `LibRainDeploy` network constant. + /// @dev Declared here because `rain-deploy-0.1.4`'s `LibRainDeploy` + /// predates Rain deployments on Ethereum mainnet and has no `ETHEREUM` + /// constant. The Zoltu factory IS deployed on Ethereum mainnet at the + /// canonical `LibRainDeploy.ZOLTU_FACTORY` address (verified 2026-07-06, + /// RAI-1211), so deterministic deploys work unchanged. When a future + /// rain-deploy release ships its own `ETHEREUM` constant this one should + /// be replaced with a re-export. + string internal constant ETHEREUM = "ethereum"; + /// @notice The networks each suite in `script/Deploy.sol` is broadcast to. - /// @return networks The list of network names (Base only). + /// @return networks The list of network names (Base + Ethereum mainnet). function supportedNetworks() internal pure returns (string[] memory networks) { - networks = new string[](1); + networks = new string[](2); networks[0] = LibRainDeploy.BASE; + networks[1] = ETHEREUM; } } diff --git a/test/src/concrete/deploy/StoxProdV4.t.sol b/test/src/concrete/deploy/StoxProdV4.t.sol index 24b01f55..2391b9c1 100644 --- a/test/src/concrete/deploy/StoxProdV4.t.sol +++ b/test/src/concrete/deploy/StoxProdV4.t.sol @@ -5,6 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std-1.16.1/src/Test.sol"; import {LibProdDeployV4} from "../../../../src/generated/LibProdDeployV4.sol"; import {LibRainDeploy} from "rain-deploy-0.1.4/src/lib/LibRainDeploy.sol"; +import {LibStoxDeployNetworks} from "../../../../src/lib/LibStoxDeployNetworks.sol"; import {IBeacon} from "@openzeppelin-contracts-5.6.1/proxy/beacon/IBeacon.sol"; import {Ownable} from "@openzeppelin-contracts-5.6.1/access/Ownable.sol"; import {ST0xOrchestratorBeaconSetDeployer} from "../../../../src/concrete/deploy/ST0xOrchestratorBeaconSetDeployer.sol"; @@ -357,4 +358,14 @@ contract StoxProdV4Test is Test { vm.createSelectFork(LibRainDeploy.BASE); checkAllV4OnChain(); } + + /// All V4 contracts MUST be deployed on Ethereum mainnet with the same + /// deterministic Zoltu addresses + codehashes as every other network + /// (RAI-1095). Ethereum bootstraps directly at V4 — there is no pre-V4 + /// history there. Red until the V4 suites are broadcast to Ethereum; the + /// addresses/codehashes are identical to Base by construction. + function testProdDeployEthereumV4() external { + vm.createSelectFork(LibStoxDeployNetworks.ETHEREUM); + checkAllV4OnChain(); + } } diff --git a/test/src/lib/LibStoxDeployNetworks.t.sol b/test/src/lib/LibStoxDeployNetworks.t.sol index 12345efe..80172bd6 100644 --- a/test/src/lib/LibStoxDeployNetworks.t.sol +++ b/test/src/lib/LibStoxDeployNetworks.t.sol @@ -10,10 +10,18 @@ import {LibRainDeploy} from "rain-deploy-0.1.4/src/lib/LibRainDeploy.sol"; /// @notice Pins the ST0x deploy network set so any change to the supported /// networks fails a test. contract LibStoxDeployNetworksTest is Test { - /// ST0x deploys to Base only. - function testSupportedNetworksIsBaseOnly() external pure { + /// ST0x deploys to Base + Ethereum mainnet, in that order (Base first as + /// the reference network carrying the live production state). + function testSupportedNetworksIsBaseAndEthereum() external pure { string[] memory networks = LibStoxDeployNetworks.supportedNetworks(); - assertEq(networks.length, 1, "expected exactly one deploy network"); - assertEq(networks[0], LibRainDeploy.BASE, "expected Base"); + assertEq(networks.length, 2, "expected exactly two deploy networks"); + assertEq(networks[0], LibRainDeploy.BASE, "expected Base first"); + assertEq(networks[1], LibStoxDeployNetworks.ETHEREUM, "expected Ethereum second"); + } + + /// The locally-declared Ethereum network name matches the foundry.toml + /// rpc alias convention used by every LibRainDeploy constant. + function testEthereumNetworkName() external pure { + assertEq(LibStoxDeployNetworks.ETHEREUM, "ethereum", "expected ethereum rpc alias"); } } From 9a810d883c1c5e8aec0da1f0d83a5a33e4221575 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 11:31:22 +0000 Subject: [PATCH 2/6] Trim process/historical faff from the Ethereum-wiring comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comments describe current behavior only. Removed ticket references (RAI-1211, RAI-1095), the "verified " note, history ("predates Rain deployments", "no pre-V4 history", "bootstraps directly at V4"), and temporal status ("Red until the V4 suites are broadcast", "when a future release ships…"). Kept the load-bearing current facts: why ETHEREUM is declared locally, that the Zoltu factory is on Ethereum so deterministic deploys work, and the per-network idempotence invariant. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 5 ++--- src/lib/LibStoxDeployNetworks.sol | 23 +++++++++-------------- test/src/concrete/deploy/StoxProdV4.t.sol | 8 +++----- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8abce2d7..d58a6b50 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -289,9 +289,8 @@ per suite to avoid Zoltu factory nonce issues. Every suite targets the `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 pre-V4 deployments live in `LibProdDeployV1` / -`LibProdDeployV2` as an audit trail and are not redeployable from the current -source; Ethereum bootstraps directly at V4 with no pre-V4 history. +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 diff --git a/src/lib/LibStoxDeployNetworks.sol b/src/lib/LibStoxDeployNetworks.sol index 0cba8378..88640087 100644 --- a/src/lib/LibStoxDeployNetworks.sol +++ b/src/lib/LibStoxDeployNetworks.sol @@ -10,23 +10,18 @@ import {LibRainDeploy} from "rain-deploy-0.1.4/src/lib/LibRainDeploy.sol"; /// inline, so the supported-network set lives in one place. ST0x deploys to /// Base and Ethereum mainnet. /// -/// `LibRainDeploy.deployToNetworks` is idempotent per network (an -/// already-deployed contract is skipped, its codehash still verified), so -/// re-running a suite after adding a network here is a no-op on the networks -/// that already carry the artifact and a fresh Zoltu deploy on the ones that -/// don't. That per-network idempotence is what keeps every chain in this list -/// bytecode-identical by construction: one suite run covers all of them. +/// `LibRainDeploy.deployToNetworks` is idempotent per network — an +/// already-deployed contract is skipped and its codehash re-verified — so a +/// single suite run keeps every network in this list bytecode-identical by +/// construction. library LibStoxDeployNetworks { - /// @notice Ethereum mainnet network name. Matches the `[rpc_endpoints]` + /// @notice Ethereum mainnet network name, matching the `[rpc_endpoints]` /// alias in `foundry.toml` (resolved from `ETHEREUM_RPC_URL`), the same /// pattern as every `LibRainDeploy` network constant. - /// @dev Declared here because `rain-deploy-0.1.4`'s `LibRainDeploy` - /// predates Rain deployments on Ethereum mainnet and has no `ETHEREUM` - /// constant. The Zoltu factory IS deployed on Ethereum mainnet at the - /// canonical `LibRainDeploy.ZOLTU_FACTORY` address (verified 2026-07-06, - /// RAI-1211), so deterministic deploys work unchanged. When a future - /// rain-deploy release ships its own `ETHEREUM` constant this one should - /// be replaced with a re-export. + /// @dev Declared here because `rain-deploy-0.1.4`'s `LibRainDeploy` has no + /// `ETHEREUM` constant. The Zoltu factory is deployed on Ethereum mainnet at + /// the canonical `LibRainDeploy.ZOLTU_FACTORY` address, so deterministic + /// deploys work unchanged. string internal constant ETHEREUM = "ethereum"; /// @notice The networks each suite in `script/Deploy.sol` is broadcast to. diff --git a/test/src/concrete/deploy/StoxProdV4.t.sol b/test/src/concrete/deploy/StoxProdV4.t.sol index 2391b9c1..6a047fb3 100644 --- a/test/src/concrete/deploy/StoxProdV4.t.sol +++ b/test/src/concrete/deploy/StoxProdV4.t.sol @@ -359,11 +359,9 @@ contract StoxProdV4Test is Test { checkAllV4OnChain(); } - /// All V4 contracts MUST be deployed on Ethereum mainnet with the same - /// deterministic Zoltu addresses + codehashes as every other network - /// (RAI-1095). Ethereum bootstraps directly at V4 — there is no pre-V4 - /// history there. Red until the V4 suites are broadcast to Ethereum; the - /// addresses/codehashes are identical to Base by construction. + /// The V4 contracts are deployed on Ethereum mainnet at the same + /// deterministic Zoltu addresses and codehashes as every other network, + /// identical to Base by construction. function testProdDeployEthereumV4() external { vm.createSelectFork(LibStoxDeployNetworks.ETHEREUM); checkAllV4OnChain(); From d4c8e7829d11d2ba40865ff2e980d38b89b94c05 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 12:12:20 +0000 Subject: [PATCH 3/6] Wire RPC_URL_ETHEREUM_FORK into the test and deploy workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Ethereum fork test and the manual deploy both need an Ethereum RPC. Pass RPC_URL_ETHEREUM_FORK through rainix-sol.yaml (test) and manual-sol-artifacts.yaml (deploy), plus the CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY for deploy verification — matching how every other network is passed to the rainix reusables. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/manual-sol-artifacts.yaml | 2 ++ .github/workflows/rainix-sol.yaml | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index aac80b5f..ab2cb8a7 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -53,6 +53,8 @@ jobs: 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 }} CI_DEPLOY_BASE_ETHERSCAN_API_KEY: ${{ secrets.CI_DEPLOY_BASE_ETHERSCAN_API_KEY }} + CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY: ${{ secrets.CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY }} diff --git a/.github/workflows/rainix-sol.yaml b/.github/workflows/rainix-sol.yaml index 7145c4f3..afc74c35 100644 --- a/.github/workflows/rainix-sol.yaml +++ b/.github/workflows/rainix-sol.yaml @@ -7,5 +7,6 @@ jobs: 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 }} From 14a3d4d6f43e33c145c4b028211297d6beb41a69 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 13:15:56 +0000 Subject: [PATCH 4/6] Pin chain id on the ethereum etherscan config for verification foundry does not recognise `ethereum` as a built-in chain alias (its canonical name for chain 1 is `mainnet`), so `forge verify-contract` against the ethereum network failed with "unknown alias `ethereum`". Pinning `chain = 1` on the etherscan entry lets verification resolve the Etherscan API for mainnet. Co-Authored-By: Claude Opus 4.8 --- foundry.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/foundry.toml b/foundry.toml index 841d3143..479efee3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -78,6 +78,9 @@ polygon = "${POLYGON_RPC_URL}" arbitrum = { key = "${CI_DEPLOY_ARBITRUM_ETHERSCAN_API_KEY}" } base = { key = "${CI_DEPLOY_BASE_ETHERSCAN_API_KEY}" } base_sepolia = { key = "${CI_DEPLOY_BASE_SEPOLIA_ETHERSCAN_API_KEY}" } -ethereum = { key = "${CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY}" } +# `ethereum` is not a built-in foundry chain alias (foundry's canonical name for +# chain 1 is `mainnet`), so the chain id is pinned explicitly. Without it, +# verification fails with "unknown alias `ethereum`". +ethereum = { key = "${CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY}", chain = 1 } flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}" } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}" } From 515c8e1f89143b9397cda0cb28a15b38097d6d44 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 14:08:07 +0000 Subject: [PATCH 5/6] Add Ethereum 0.1.1-only prod deploy script; scope Ethereum test to 0.1.1 script/DeployProdV4_0_1_1.sol ships the audited 0.1.1 production set to Ethereum mainnet only. Each suite deploys the stored LibProdDeployV4.*_CREATION_CODE_0_1_1 bytecode (the exact bytes the 0.1.1 audit covers) rather than type(T).creationCode, so it reproduces the audited 0.1.1 deployment regardless of what current source compiles to. The orchestrator (introduced at 0.1.2) is not part of the 0.1.1 set and is omitted. The StoxProdV4 fork test now checks Ethereum against the 0.1.1 set alone (checkProd_0_1_1OnChain), while Base still checks the full accumulated set (checkAllV4OnChain, which now composes the 0.1.1 helper plus the 0.1.2 orchestrator and 0.1.3 rebuilds). script/Deploy.sol and supportedNetworks are unchanged: Base continues to receive current source. Co-Authored-By: Claude Opus 4.8 --- script/DeployProdV4_0_1_1.sol | 212 ++++++++++++++++++++++ test/src/concrete/deploy/StoxProdV4.t.sol | 144 ++++++++------- 2 files changed, 292 insertions(+), 64 deletions(-) create mode 100644 script/DeployProdV4_0_1_1.sol diff --git a/script/DeployProdV4_0_1_1.sol b/script/DeployProdV4_0_1_1.sol new file mode 100644 index 00000000..db497255 --- /dev/null +++ b/script/DeployProdV4_0_1_1.sol @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Script, console2} from "forge-std-1.16.1/src/Script.sol"; + +import {LibRainDeploy} from "rain-deploy-0.1.4/src/lib/LibRainDeploy.sol"; +import {LibProdDeployV4} from "../src/generated/LibProdDeployV4.sol"; +import {LibStoxDeployNetworks} from "../src/lib/LibStoxDeployNetworks.sol"; + +/// @dev Error thrown when the DEPLOYMENT_SUITE env var does not match any known +/// suite. +error UnknownDeploymentSuite(bytes32 suite); + +// One suite per contract to avoid Zoltu factory nonce issues. +// +// This script ships the audited 0.1.1 production set to Ethereum mainnet only. +// Unlike `script/Deploy.sol`, which deploys the CURRENT source (the 0.1.3 pins) +// to `LibStoxDeployNetworks.supportedNetworks()`, each suite here deploys the +// stored `LibProdDeployV4.*_CREATION_CODE_0_1_1` bytecode — the exact bytes the +// 0.1.1 audit covers — and asserts against the `_0_1_1` address/codehash pins. +// Deploying stored creation code (not `type(T).creationCode`) reproduces the +// audited 0.1.1 deployment regardless of what the current source compiles to. +// +// The orchestrator is intentionally absent: `ST0xOrchestrator` and its +// beacon-set deployer were introduced at 0.1.2, so they are not part of the +// 0.1.1 set. + +bytes32 constant DEPLOYMENT_SUITE_STOX_RECEIPT = keccak256("stox-receipt"); +bytes32 constant DEPLOYMENT_SUITE_STOX_RECEIPT_VAULT = keccak256("stox-receipt-vault"); +bytes32 constant DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT = keccak256("stox-wrapped-token-vault"); +bytes32 constant DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT_BEACON = keccak256("stox-wrapped-token-vault-beacon"); +bytes32 constant DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER = + keccak256("stox-wrapped-token-vault-beacon-set-deployer"); +bytes32 constant DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER = + keccak256("stox-offchain-asset-receipt-vault-beacon-set-deployer"); +bytes32 constant DEPLOYMENT_SUITE_STOX_UNIFIED_DEPLOYER = keccak256("stox-unified-deployer"); +bytes32 constant DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_AUTHORIZER_V1 = + keccak256("stox-offchain-asset-receipt-vault-authorizer-v1"); +bytes32 constant DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_PAYMENT_MINT_AUTHORIZER_V1 = + keccak256("stox-offchain-asset-receipt-vault-payment-mint-authorizer-v1"); +bytes32 constant DEPLOYMENT_SUITE_STOX_CORPORATE_ACTIONS_FACET = keccak256("stox-corporate-actions-facet"); + +contract Deploy is Script { + /// @dev Broadcasts a single contract via the Zoltu deterministic deployer on + /// Ethereum mainnet. Reads `DEPLOYMENT_KEY` from the environment, logs + /// diagnostic information (expected address, codehash, dependency state), + /// then delegates to `LibRainDeploy.deployAndBroadcast`. + /// @param creationCode The creation bytecode of the contract to deploy. + /// @param contractPath Fully qualified contract path + /// (e.g. "src/concrete/StoxReceipt.sol:StoxReceipt"). + /// @param expectedAddress The deterministic address the contract must deploy + /// to. + /// @param expectedCodeHash The expected codehash of the deployed runtime + /// bytecode. + /// @param dependencies Addresses of contracts that must already be deployed + /// on Ethereum before this contract is deployed. + function deploySuite( + bytes memory creationCode, + string memory contractPath, + address expectedAddress, + bytes32 expectedCodeHash, + address[] memory dependencies + ) internal { + string[] memory networks = new string[](1); + networks[0] = LibStoxDeployNetworks.ETHEREUM; + uint256 deployerPrivateKey = vm.envUint("DEPLOYMENT_KEY"); + + console2.log("Suite deploying (0.1.1):", contractPath); + console2.log("Expected address:", expectedAddress); + console2.log("Expected codehash:"); + console2.logBytes32(expectedCodeHash); + console2.log("Chain ID:", block.chainid); + console2.log("Block number:", block.number); + console2.log("Dependencies count:", dependencies.length); + for (uint256 i = 0; i < dependencies.length; i++) { + console2.log(" Dep address:", dependencies[i]); + console2.log(" Dep code length:", dependencies[i].code.length); + console2.log(" Dep codehash:"); + console2.logBytes32(dependencies[i].codehash); + } + + LibRainDeploy.deployAndBroadcast( + vm, + networks, + deployerPrivateKey, + creationCode, + contractPath, + expectedAddress, + expectedCodeHash, + dependencies + ); + } + + /// @notice Entry point for the 0.1.1 Ethereum deployment script. + /// @dev Requires env vars: + /// - `DEPLOYMENT_KEY`: private key for the deployer account. + /// - `DEPLOYMENT_SUITE`: which contract to deploy (e.g. "stox-receipt"). + /// One contract per run. + function run() public { + bytes32 suite = keccak256(bytes(vm.envString("DEPLOYMENT_SUITE"))); + address[] memory noDeps = new address[](0); + + if (suite == DEPLOYMENT_SUITE_STOX_RECEIPT) { + deploySuite( + LibProdDeployV4.STOX_RECEIPT_CREATION_CODE_0_1_1, + "src/concrete/StoxReceipt.sol:StoxReceipt", + LibProdDeployV4.STOX_RECEIPT_0_1_1, + LibProdDeployV4.STOX_RECEIPT_CODEHASH_0_1_1, + noDeps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_RECEIPT_VAULT) { + // StoxReceiptVault impl. Its `fallback()` delegatecalls the + // hardcoded corporate-actions facet, and a delegatecall to a + // code-less address silently no-ops — so the facet must already be + // on-chain. Declared as a dependency so LibRainDeploy reverts + // MissingDependency if the facet is not yet deployed on Ethereum. + address[] memory deps = new address[](1); + deps[0] = LibProdDeployV4.STOX_CORPORATE_ACTIONS_FACET_0_1_1; + deploySuite( + LibProdDeployV4.STOX_RECEIPT_VAULT_CREATION_CODE_0_1_1, + "src/concrete/StoxReceiptVault.sol:StoxReceiptVault", + LibProdDeployV4.STOX_RECEIPT_VAULT_0_1_1, + LibProdDeployV4.STOX_RECEIPT_VAULT_CODEHASH_0_1_1, + deps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT) { + deploySuite( + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_CREATION_CODE_0_1_1, + "src/concrete/StoxWrappedTokenVault.sol:StoxWrappedTokenVault", + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_0_1_1, + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_CODEHASH_0_1_1, + noDeps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT_BEACON) { + address[] memory deps = new address[](1); + deps[0] = LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_0_1_1; + deploySuite( + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_CREATION_CODE_0_1_1, + "src/concrete/StoxWrappedTokenVaultBeacon.sol:StoxWrappedTokenVaultBeacon", + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1, + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_CODEHASH_0_1_1, + deps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER) { + address[] memory deps = new address[](1); + deps[0] = LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1; + deploySuite( + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER_CREATION_CODE_0_1_1, + "src/concrete/deploy/StoxWrappedTokenVaultBeaconSetDeployer.sol:StoxWrappedTokenVaultBeaconSetDeployer", + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER_0_1_1, + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER_CODEHASH_0_1_1, + deps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER) { + // Its constructor bakes beacons over the StoxReceipt and + // StoxReceiptVault impls, both of which must already have code. + address[] memory deps = new address[](2); + deps[0] = LibProdDeployV4.STOX_RECEIPT_0_1_1; + deps[1] = LibProdDeployV4.STOX_RECEIPT_VAULT_0_1_1; + deploySuite( + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_CREATION_CODE_0_1_1, + "src/concrete/deploy/StoxOffchainAssetReceiptVaultBeaconSetDeployer.sol:StoxOffchainAssetReceiptVaultBeaconSetDeployer", + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_0_1_1, + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_CODEHASH_0_1_1, + deps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_UNIFIED_DEPLOYER) { + // Embeds the OARV beacon-set deployer and the wrapped-token-vault + // beacon-set deployer it drives; both must already have code. + address[] memory deps = new address[](2); + deps[0] = LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_0_1_1; + deps[1] = LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_SET_DEPLOYER_0_1_1; + deploySuite( + LibProdDeployV4.STOX_UNIFIED_DEPLOYER_CREATION_CODE_0_1_1, + "src/concrete/deploy/StoxUnifiedDeployer.sol:StoxUnifiedDeployer", + LibProdDeployV4.STOX_UNIFIED_DEPLOYER_0_1_1, + LibProdDeployV4.STOX_UNIFIED_DEPLOYER_CODEHASH_0_1_1, + deps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_AUTHORIZER_V1) { + deploySuite( + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_AUTHORIZER_V1_CREATION_CODE_0_1_1, + "src/concrete/authorize/StoxOffchainAssetReceiptVaultAuthorizerV1.sol:StoxOffchainAssetReceiptVaultAuthorizerV1", + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_AUTHORIZER_V1_0_1_1, + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_AUTHORIZER_V1_CODEHASH_0_1_1, + noDeps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_PAYMENT_MINT_AUTHORIZER_V1) { + deploySuite( + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_PAYMENT_MINT_AUTHORIZER_V1_CREATION_CODE_0_1_1, + "src/concrete/authorize/StoxOffchainAssetReceiptVaultPaymentMintAuthorizerV1.sol:StoxOffchainAssetReceiptVaultPaymentMintAuthorizerV1", + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_PAYMENT_MINT_AUTHORIZER_V1_0_1_1, + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_PAYMENT_MINT_AUTHORIZER_V1_CODEHASH_0_1_1, + noDeps + ); + } else if (suite == DEPLOYMENT_SUITE_STOX_CORPORATE_ACTIONS_FACET) { + // StoxCorporateActionsFacet impl. No on-chain dependencies (the + // receipt-vault impl hardcodes its address but does not link to it + // at deploy time). + deploySuite( + LibProdDeployV4.STOX_CORPORATE_ACTIONS_FACET_CREATION_CODE_0_1_1, + "src/concrete/StoxCorporateActionsFacet.sol:StoxCorporateActionsFacet", + LibProdDeployV4.STOX_CORPORATE_ACTIONS_FACET_0_1_1, + LibProdDeployV4.STOX_CORPORATE_ACTIONS_FACET_CODEHASH_0_1_1, + noDeps + ); + } else { + revert UnknownDeploymentSuite(suite); + } + } +} diff --git a/test/src/concrete/deploy/StoxProdV4.t.sol b/test/src/concrete/deploy/StoxProdV4.t.sol index 6a047fb3..a477815f 100644 --- a/test/src/concrete/deploy/StoxProdV4.t.sol +++ b/test/src/concrete/deploy/StoxProdV4.t.sol @@ -14,9 +14,16 @@ import { } from "rain-vats-0.1.6/src/interface/IOffchainAssetReceiptVaultBeaconSetDeployerV2.sol"; /// @title StoxProdV4Test -/// @notice Fork test verifying every V4 Zoltu deployment exists on Base with -/// the expected runtime codehash. V4 ships to Base only (the deploy CI targets -/// Base), so unlike `StoxProdV2Test` there is a single network fork here. +/// @notice Fork test verifying every V4 Zoltu deployment exists on-chain at its +/// pinned address with the expected runtime codehash. +/// +/// The two production networks carry different sets: +/// - Base carries the full accumulated V4 set — the audited 0.1.1 contracts plus +/// the 0.1.2 orchestrator and the 0.1.3 rebuilds — deployed incrementally over +/// those releases by `script/Deploy.sol` (current source). +/// - Ethereum mainnet carries only the audited 0.1.1 production set, shipped by +/// `script/DeployProdV4_0_1_1.sol` from the stored 0.1.1 creation code. The +/// orchestrator (0.1.2) and the 0.1.3 rebuilds are Base-only. /// /// The codehash pins are the same literals `LibProdDeployV4Test` checks against /// the generated pointer files and against a fresh Zoltu redeploy. This test @@ -29,13 +36,14 @@ import { /// `LibProdDeployV4Test.testAuthoriserV4ClonePlaceholder` guards that /// placeholder until the clone is hydrated. contract StoxProdV4Test is Test { - /// Asserts every V4 deployed contract is present at its pinned address with - /// the pinned codehash; that the wrapped-token-vault beacon points at the V4 - /// vault implementation; and that the offchain-asset-receipt-vault - /// beacon-set deployer's two beacons point at the V4 receipt and receipt - /// vault implementations. All three beacons are still held by the beacon - /// initial owner (pre-migration deploy state). - function checkAllV4OnChain() internal view { + /// Asserts the audited 0.1.1 production set is present at its pinned + /// addresses with the pinned codehashes; that the wrapped-token-vault beacon + /// points at the 0.1.1 vault implementation; and that the + /// offchain-asset-receipt-vault beacon-set deployer's two beacons point at + /// the 0.1.1 receipt and receipt vault implementations. All three beacons are + /// still held by the beacon initial owner (pre-migration deploy state). This + /// is the exact set shipped to Ethereum mainnet, and a subset of Base. + function checkProd_0_1_1OnChain() internal view { assertTrue(LibProdDeployV4.STOX_RECEIPT_0_1_1.code.length > 0, "V4 StoxReceipt not deployed"); assertEq(LibProdDeployV4.STOX_RECEIPT_0_1_1.codehash, LibProdDeployV4.STOX_RECEIPT_CODEHASH_0_1_1); assertEq(LibProdDeployV4.STOX_RECEIPT_0_1_1.code, LibProdDeployV4.STOX_RECEIPT_RUNTIME_CODE_0_1_1); @@ -142,6 +150,61 @@ contract StoxProdV4Test is Test { LibProdDeployV4.STOX_CORPORATE_ACTIONS_FACET_RUNTIME_CODE_0_1_1 ); + // The wrapped-token-vault beacon points at the 0.1.1 vault implementation + // and is still held by the beacon initial owner (rainlang.eth), which is + // the deploy-time state before ownership migration to the ST0x + // token-owner Safe. + assertEq( + IBeacon(LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1).implementation(), + LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_0_1_1, + "V4 beacon implementation mismatch" + ); + assertEq( + Ownable(LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1).owner(), + LibProdDeployV4.BEACON_INITIAL_OWNER, + "V4 beacon owner mismatch" + ); + + // The offchain-asset-receipt-vault beacon-set deployer creates two + // beacons in its constructor: the receipt beacon points at the 0.1.1 + // receipt implementation and the offchain-asset-receipt-vault beacon + // points at the 0.1.1 receipt vault implementation, both held by the + // beacon initial owner. + IOffchainAssetReceiptVaultBeaconSetDeployerV2 oarvDeployer = IOffchainAssetReceiptVaultBeaconSetDeployerV2( + LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_0_1_1 + ); + + IBeacon receiptBeacon = oarvDeployer.iReceiptBeacon(); + assertEq( + receiptBeacon.implementation(), + LibProdDeployV4.STOX_RECEIPT_0_1_1, + "V4 OARV receipt beacon implementation mismatch" + ); + assertEq( + Ownable(address(receiptBeacon)).owner(), + LibProdDeployV4.BEACON_INITIAL_OWNER, + "V4 OARV receipt beacon owner mismatch" + ); + + IBeacon vaultBeacon = oarvDeployer.iOffchainAssetReceiptVaultBeacon(); + assertEq( + vaultBeacon.implementation(), + LibProdDeployV4.STOX_RECEIPT_VAULT_0_1_1, + "V4 OARV vault beacon implementation mismatch" + ); + assertEq( + Ownable(address(vaultBeacon)).owner(), + LibProdDeployV4.BEACON_INITIAL_OWNER, + "V4 OARV vault beacon owner mismatch" + ); + } + + /// Asserts the full accumulated V4 set carried by Base: the audited 0.1.1 set + /// (via `checkProd_0_1_1OnChain`) plus the 0.1.2 orchestrator and the 0.1.3 + /// rebuilds, including their beacon wiring. + function checkAllV4OnChain() internal view { + checkProd_0_1_1OnChain(); + // st0x-deploy 0.1.3 rebuilds seven contracts at new Zoltu addresses: the // corporate-actions facet (the cumulative-multiplier change) plus the // receipt vault, OARV beacon-set deployer, unified deployer, orchestrator, @@ -239,56 +302,8 @@ contract StoxProdV4Test is Test { LibProdDeployV4.ST0X_ORCHESTRATOR_BEACON_SET_DEPLOYER_RUNTIME_CODE_0_1_2 ); - // The wrapped-token-vault beacon points at the V4 vault implementation - // and is still held by the beacon initial owner (rainlang.eth), which - // is the deploy-time state before ownership migration to the ST0x - // token-owner Safe. - assertEq( - IBeacon(LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1).implementation(), - LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_0_1_1, - "V4 beacon implementation mismatch" - ); - assertEq( - Ownable(LibProdDeployV4.STOX_WRAPPED_TOKEN_VAULT_BEACON_0_1_1).owner(), - LibProdDeployV4.BEACON_INITIAL_OWNER, - "V4 beacon owner mismatch" - ); - - // The offchain-asset-receipt-vault beacon-set deployer creates two - // beacons in its constructor: the receipt beacon points at the V4 - // receipt implementation and the offchain-asset-receipt-vault beacon - // points at the V4 receipt vault implementation, both held by the - // beacon initial owner. - IOffchainAssetReceiptVaultBeaconSetDeployerV2 oarvDeployer = IOffchainAssetReceiptVaultBeaconSetDeployerV2( - LibProdDeployV4.STOX_OFFCHAIN_ASSET_RECEIPT_VAULT_BEACON_SET_DEPLOYER_0_1_1 - ); - - IBeacon receiptBeacon = oarvDeployer.iReceiptBeacon(); - assertEq( - receiptBeacon.implementation(), - LibProdDeployV4.STOX_RECEIPT_0_1_1, - "V4 OARV receipt beacon implementation mismatch" - ); - assertEq( - Ownable(address(receiptBeacon)).owner(), - LibProdDeployV4.BEACON_INITIAL_OWNER, - "V4 OARV receipt beacon owner mismatch" - ); - - IBeacon vaultBeacon = oarvDeployer.iOffchainAssetReceiptVaultBeacon(); - assertEq( - vaultBeacon.implementation(), - LibProdDeployV4.STOX_RECEIPT_VAULT_0_1_1, - "V4 OARV vault beacon implementation mismatch" - ); - assertEq( - Ownable(address(vaultBeacon)).owner(), - LibProdDeployV4.BEACON_INITIAL_OWNER, - "V4 OARV vault beacon owner mismatch" - ); - // The ST0x orchestrator beacon-set deployer creates one beacon in its - // constructor: the orchestrator beacon points at the V4 orchestrator + // constructor: the orchestrator beacon points at the 0.1.2 orchestrator // implementation, held by the beacon initial owner. IBeacon orchestratorBeacon = ST0xOrchestratorBeaconSetDeployer( LibProdDeployV4.ST0X_ORCHESTRATOR_BEACON_SET_DEPLOYER_0_1_2 @@ -353,17 +368,18 @@ contract StoxProdV4Test is Test { ); } - /// All V4 contracts MUST be deployed on Base with the expected codehashes. + /// The full accumulated V4 set MUST be deployed on Base with the expected + /// codehashes. function testProdDeployBaseV4() external { vm.createSelectFork(LibRainDeploy.BASE); checkAllV4OnChain(); } - /// The V4 contracts are deployed on Ethereum mainnet at the same - /// deterministic Zoltu addresses and codehashes as every other network, - /// identical to Base by construction. + /// Only the audited 0.1.1 production set is shipped to Ethereum mainnet (the + /// orchestrator and 0.1.3 rebuilds are Base-only), so the Ethereum fork is + /// checked against the 0.1.1 set alone. function testProdDeployEthereumV4() external { vm.createSelectFork(LibStoxDeployNetworks.ETHEREUM); - checkAllV4OnChain(); + checkProd_0_1_1OnChain(); } } From bfc6b8b07b210cd35a9e5782b124cb52e26541f5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 16 Jul 2026 14:17:18 +0000 Subject: [PATCH 6/6] Add Ethereum 0.1.1 deploy workflow manual-sol-artifacts-ethereum-0-1-1.yaml dispatches the 0.1.1 audited set (10 suites, no orchestrator) to Ethereum mainnet via script/DeployProdV4_0_1_1.sol, using the rainix reusable's new script + verify inputs. verify is false because the 0.1.1 bytecode of the contracts that changed by 0.1.3 does not match current source; those are verified manually from the 0.1.1 tag. Depends on rainlanguage/rainix#276 (the script + verify inputs) landing on rainix main. Co-Authored-By: Claude Opus 4.8 --- .../manual-sol-artifacts-ethereum-0-1-1.yaml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/manual-sol-artifacts-ethereum-0-1-1.yaml diff --git a/.github/workflows/manual-sol-artifacts-ethereum-0-1-1.yaml b/.github/workflows/manual-sol-artifacts-ethereum-0-1-1.yaml new file mode 100644 index 00000000..66bec846 --- /dev/null +++ b/.github/workflows/manual-sol-artifacts-ethereum-0-1-1.yaml @@ -0,0 +1,52 @@ +name: Manual sol artifacts (Ethereum 0.1.1) +on: + workflow_dispatch: + inputs: + suite: + description: 'Suite to deploy (one contract per suite, deploy in listed order)' + required: true + type: choice + options: + # =================================================================== + # The audited 0.1.1 production set, shipped to Ethereum mainnet only + # via script/DeployProdV4_0_1_1.sol (stored 0.1.1 creation bytecode). + # The orchestrator (introduced at 0.1.2) is not part of this set. + # + # Deploy in the listed order; later entries reference earlier ones via + # dependency pointers so an out-of-order run trips the dep-codehash + # check. + # =================================================================== + # 1. No on-chain dependencies, plus the wrapped-token-vault chain + # (vault -> beacon -> beacon-set deployer) and the two authorizers. + - stox-receipt + - stox-wrapped-token-vault + - stox-wrapped-token-vault-beacon + - stox-wrapped-token-vault-beacon-set-deployer + - stox-offchain-asset-receipt-vault-authorizer-v1 + - stox-offchain-asset-receipt-vault-payment-mint-authorizer-v1 + # 2. Corporate-actions facet (no on-chain dependencies). + - stox-corporate-actions-facet + # 3. Receipt vault (depends on the corporate-actions facet). + - stox-receipt-vault + # 4. OARV beacon-set deployer (depends on the receipt and receipt-vault + # impls above). + - stox-offchain-asset-receipt-vault-beacon-set-deployer + # 5. Unified deployer (depends on the two set-deployers above). + - stox-unified-deployer +jobs: + deploy: + uses: rainlanguage/rainix/.github/workflows/rainix-manual-sol-artifacts.yaml@main + with: + suite: ${{ inputs.suite }} + # Ship the stored 0.1.1 creation bytecode, not current source. + script: script/DeployProdV4_0_1_1.sol:Deploy + # The 0.1.1 bytecode of the contracts that changed by 0.1.3 does not match + # current source, so Etherscan verification against current source would + # fail the run. Deploy unverified; verify manually from the 0.1.1 tag. + verify: false + # This script targets Ethereum only and runs unverified, so it needs only the + # deployer key and the Ethereum RPC. The reusable declares every other secret + # as optional and falls back to `|| vars.* || ''` for any it isn't given. + secrets: + PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} + RPC_URL_ETHEREUM_FORK: ${{ secrets.RPC_URL_ETHEREUM_FORK }}