From 577dfb3517599965bcfe762512b8f2099502b15d Mon Sep 17 00:00:00 2001 From: Josh Hardy Date: Thu, 10 Sep 2026 14:38:05 +0000 Subject: [PATCH 1/2] Bump rain-deploy to 0.1.8: Robinhood Chain (4663) + BNB Smart Chain (56) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `LibRainDeploy.supportedNetworks()` gains the two chains at 0.1.8, so the deploy and the inherited liveness test cover them; `[rpc_endpoints]` and `[etherscan]` gain the matching rows (Robinhood Chain via its Blockscout, which speaks the Etherscan API; BscScan is covered by Etherscan V2). Import prefixes and the lock move with the bump; no contract bytecode changes. The dispatcher gains a `suite` input listing the frozen release keys next to the rolling candidate: a newly supported network needs the RELEASED suite — the addresses every consumer pins — and current source has moved since it was cut, so the candidate would land elsewhere. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01HiqQdxokJ4edjAFyAkN9G3 --- .github/workflows/manual-sol-artifacts.yaml | 11 ++++++++++- foundry.toml | 11 ++++++++++- script/Build.sol | 4 ++-- script/Deploy.sol | 2 +- soldeer.lock | 8 ++++---- src/abstract/RainDeploySuitesBase.sol | 2 +- test/src/abstract/CloneFactoryDeployChain.t.sol | 2 +- test/src/abstract/CloneFactoryDeploySnapshot.t.sol | 2 +- test/src/lib/LibCloneFactoryDeploy.t.sol | 2 +- test/src/lib/LibCloneFactoryDeployCandidate.t.sol | 2 +- 10 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 88c7d0b..85320b0 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -1,9 +1,18 @@ name: Manual sol artifacts on: workflow_dispatch: + inputs: + suite: + description: "The suite to deploy. The bare key is the rolling candidate (current source); a `@` key is a frozen release, which is what a newly supported network needs so the addresses every consumer pins land there." + required: true + type: choice + options: + - clone-factory + - clone-factory@0_1_9 + - clone-factory@0_1_10 jobs: deploy: uses: rainlanguage/rainix/.github/workflows/rainix-manual-sol-artifacts.yaml@main with: - suite: clone-factory + suite: ${{ inputs.suite }} secrets: inherit diff --git a/foundry.toml b/foundry.toml index af991f0..4dd9fa2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -42,7 +42,7 @@ runs = 2048 forge-std = "1.16.2" "@openzeppelin-contracts" = "5.6.1" "rain-extrospection" = "0.1.1" -"rain-deploy" = "0.1.7" +"rain-deploy" = "0.1.8" "rain-sol-codegen" = "0.1.36" "rain-factory" = "0.1.9" @@ -56,6 +56,8 @@ base_sepolia = "${BASE_SEPOLIA_RPC_URL}" ethereum = "${ETHEREUM_RPC_URL}" flare = "${FLARE_RPC_URL}" hyperevm = "${HYPEREVM_RPC_URL}" +robinhood = "${ROBINHOOD_RPC_URL}" +bsc = "${BSC_RPC_URL}" polygon = "${POLYGON_RPC_URL}" [etherscan] @@ -65,4 +67,11 @@ base_sepolia = { key = "${CI_DEPLOY_BASE_SEPOLIA_ETHERSCAN_API_KEY}" } ethereum = { key = "${CI_DEPLOY_ETHEREUM_ETHERSCAN_API_KEY}", chain = 1 } flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}" } hyperevm = { key = "${CI_DEPLOY_HYPEREVM_ETHERSCAN_API_KEY}", chain = 999 } +# Robinhood Chain (4663) is not indexed by Etherscan V2. Its Blockscout speaks +# the Etherscan API, so the entry points there (the key is ignored). That +# explorer has rejected non-browser clients, so if `--verify` fails there, +# verify afterwards through Sourcify: `forge verify-contract --verifier +# sourcify --chain 4663 ...`. +robinhood = { key = "${CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY}", chain = 4663, url = "https://robinhoodchain.blockscout.com/api" } +bsc = { key = "${CI_DEPLOY_BSC_ETHERSCAN_API_KEY}", chain = 56 } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}" } diff --git a/script/Build.sol b/script/Build.sol index 949fbf0..6c276f4 100644 --- a/script/Build.sol +++ b/script/Build.sol @@ -2,10 +2,10 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {BuildScript} from "rain-deploy-0.1.7/src/abstract/BuildScript.sol"; +import {BuildScript} from "rain-deploy-0.1.8/src/abstract/BuildScript.sol"; import {DeployCandidate} from "../src/abstract/RainDeploySuitesBase.sol"; import {CloneFactoryDeploySuites} from "../src/abstract/CloneFactoryDeploySuites.sol"; -import {LibRainDeploySnapshot} from "rain-deploy-0.1.7/src/lib/LibRainDeploySnapshot.sol"; +import {LibRainDeploySnapshot} from "rain-deploy-0.1.8/src/lib/LibRainDeploySnapshot.sol"; /// One contract's generated files: the rolling snapshot, the alias lib that /// re-exports its pins and the released-suites lib emitted from its record. diff --git a/script/Deploy.sol b/script/Deploy.sol index 393b0d8..f1ebfb5 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {RainDeployBroadcast} from "rain-deploy-0.1.7/src/abstract/RainDeployBroadcast.sol"; +import {RainDeployBroadcast} from "rain-deploy-0.1.8/src/abstract/RainDeployBroadcast.sol"; import {CloneFactoryDeploySuites} from "../src/abstract/CloneFactoryDeploySuites.sol"; /// @title Deploy diff --git a/soldeer.lock b/soldeer.lock index 042000a..5f13e42 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -14,10 +14,10 @@ integrity = "5fb4325b60d7d4194bd0481e2f94398cf1d9c6561dd12a66fb2748ef4a68205f" [[dependencies]] name = "rain-deploy" -version = "0.1.7" -url = "https://soldeer-revisions.s3.amazonaws.com/rain-deploy/0_1_7_19-08-2026_05:57:12_rain.zip" -checksum = "d0e868184ad16fc6abb704bb1dddab57ebf2beb042529690e030568f5c81a9b3" -integrity = "e51da6f2b3a0f427a0aac5d7714bed2027f5cf0f39b31f0692e9623ceeaa47f2" +version = "0.1.8" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-deploy/0_1_8_10-09-2026_14:32:04_rain.zip" +checksum = "506d4b9acea5a06bd6d49442caa17075fd40a70c9662d26fbc6e79339e6e1dc4" +integrity = "44375e425fed5e640711e47c9256aff7643566454870d940f9e831b502d940e5" [[dependencies]] name = "rain-extrospection" diff --git a/src/abstract/RainDeploySuitesBase.sol b/src/abstract/RainDeploySuitesBase.sol index d1dc438..294c5a2 100644 --- a/src/abstract/RainDeploySuitesBase.sol +++ b/src/abstract/RainDeploySuitesBase.sol @@ -12,4 +12,4 @@ import { DeployCandidate, DeploySuite, RainDeploySuitesBase -} from "rain-deploy-0.1.7/src/abstract/RainDeploySuitesBase.sol"; +} from "rain-deploy-0.1.8/src/abstract/RainDeploySuitesBase.sol"; diff --git a/test/src/abstract/CloneFactoryDeployChain.t.sol b/test/src/abstract/CloneFactoryDeployChain.t.sol index 8e5d9f3..29bbe20 100644 --- a/test/src/abstract/CloneFactoryDeployChain.t.sol +++ b/test/src/abstract/CloneFactoryDeployChain.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {RainDeployVerifyChain} from "rain-deploy-0.1.7/src/abstract/RainDeployVerifyChain.sol"; +import {RainDeployVerifyChain} from "rain-deploy-0.1.8/src/abstract/RainDeployVerifyChain.sol"; import {CloneFactoryDeploySuites} from "src/abstract/CloneFactoryDeploySuites.sol"; /// @title CloneFactoryDeployChainTest diff --git a/test/src/abstract/CloneFactoryDeploySnapshot.t.sol b/test/src/abstract/CloneFactoryDeploySnapshot.t.sol index fa3fb72..68a43d5 100644 --- a/test/src/abstract/CloneFactoryDeploySnapshot.t.sol +++ b/test/src/abstract/CloneFactoryDeploySnapshot.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {RainDeployVerifySnapshot} from "rain-deploy-0.1.7/src/abstract/RainDeployVerifySnapshot.sol"; +import {RainDeployVerifySnapshot} from "rain-deploy-0.1.8/src/abstract/RainDeployVerifySnapshot.sol"; import {CloneFactoryDeploySuites} from "src/abstract/CloneFactoryDeploySuites.sol"; /// @title CloneFactoryDeploySnapshotTest diff --git a/test/src/lib/LibCloneFactoryDeploy.t.sol b/test/src/lib/LibCloneFactoryDeploy.t.sol index f44b37d..70cb8f3 100644 --- a/test/src/lib/LibCloneFactoryDeploy.t.sol +++ b/test/src/lib/LibCloneFactoryDeploy.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std-1.16.2/src/Test.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.7/src/lib/LibRainDeploy.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.8/src/lib/LibRainDeploy.sol"; import {LibCloneFactoryDeploy} from "../../../src/lib/LibCloneFactoryDeploy.sol"; import {CloneFactory} from "../../../src/concrete/CloneFactory.sol"; diff --git a/test/src/lib/LibCloneFactoryDeployCandidate.t.sol b/test/src/lib/LibCloneFactoryDeployCandidate.t.sol index 3a26683..7bee847 100644 --- a/test/src/lib/LibCloneFactoryDeployCandidate.t.sol +++ b/test/src/lib/LibCloneFactoryDeployCandidate.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std-1.16.2/src/Test.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.7/src/lib/LibRainDeploy.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.8/src/lib/LibRainDeploy.sol"; import { BYTECODE_HASH, DEPLOYED_ADDRESS, From f4694daae12b945d54808ba8c7e07c3d72e1c8da Mon Sep 17 00:00:00 2001 From: Josh Hardy Date: Thu, 10 Sep 2026 17:17:55 +0000 Subject: [PATCH 2/2] Record the audited rain-factory 0.1.1 CloneFactory as a frozen release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `src/generated/0_1_1/CloneFactory.sol` freezes the 0.1.1 factory at `0x444acC…`: creation code (reproduces the address through Zoltu), runtime code read from Base, and the codehash `0xf21b813c…` that `rain-factory-0.1.1`'s `LibCloneFactoryDeploy` pins. It predates this repo's release lifecycle, is live on every supported network but the two newest, and is what S01-Issuer/st0x.deploy makes its authoriser clones through (0.1.10 is unaudited; 0.1.1 was audited). Recording it makes `clone-factory@0_1_1` a dispatchable, liveness-tested suite here instead of a frozen blob in a consumer. Released libs regenerated by `script/Build.sol`; the dispatcher lists the new key. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01HiqQdxokJ4edjAFyAkN9G3 --- .github/workflows/manual-sol-artifacts.yaml | 1 + src/generated/0_1_1/CloneFactory.sol | 26 +++++++++++++++++++++ src/lib/LibCloneFactoryReleased.sol | 21 +++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/generated/0_1_1/CloneFactory.sol diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 85320b0..1bef9df 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -8,6 +8,7 @@ on: type: choice options: - clone-factory + - clone-factory@0_1_1 - clone-factory@0_1_9 - clone-factory@0_1_10 jobs: diff --git a/src/generated/0_1_1/CloneFactory.sol b/src/generated/0_1_1/CloneFactory.sol new file mode 100644 index 0000000..4b6c94c --- /dev/null +++ b/src/generated/0_1_1/CloneFactory.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity ^0.8.25; + +// THIS FILE IS AUTOGENERATED BY THE BUILD SCRIPT. DO NOT EDIT BY HAND. + +/// @dev Hash of the known bytecode. +bytes32 constant BYTECODE_HASH = bytes32(0xf21b813c7075a1621285df3a8369d0652c31ea80cb807be1aaadafeecd134475); + +/// @dev The deterministic deploy address of the contract when deployed via +/// the Zoltu factory. +address constant DEPLOYED_ADDRESS = address(0x444acC29d63fa643E8adCC35FD9aa6DE111dCb39); + +/// @dev The creation bytecode of the contract. +bytes constant CREATION_CODE = + hex"6080604052348015600e575f80fd5b506103f48061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; + +/// @dev The runtime bytecode of the contract. +bytes constant RUNTIME_CODE = + hex"608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; + +/// @dev The addresses that MUST already have code on a network before +/// this release can be broadcast there, `abi.encode`d as an `address[]` +/// because Solidity has no file-scope constant of dynamic array type. +bytes constant DEPENDENCIES = + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000"; diff --git a/src/lib/LibCloneFactoryReleased.sol b/src/lib/LibCloneFactoryReleased.sol index eb62c76..8c1fcb0 100644 --- a/src/lib/LibCloneFactoryReleased.sol +++ b/src/lib/LibCloneFactoryReleased.sol @@ -6,6 +6,14 @@ pragma solidity ^0.8.25; import {DeploySuite} from "../abstract/RainDeploySuitesBase.sol"; +import { + DEPLOYED_ADDRESS as CloneFactory_0_1_1_DEPLOYED_ADDRESS, + BYTECODE_HASH as CloneFactory_0_1_1_BYTECODE_HASH, + CREATION_CODE as CloneFactory_0_1_1_CREATION_CODE, + RUNTIME_CODE as CloneFactory_0_1_1_RUNTIME_CODE, + DEPENDENCIES as CloneFactory_0_1_1_DEPENDENCIES +} from "../generated/0_1_1/CloneFactory.sol"; + import { DEPLOYED_ADDRESS as CloneFactory_0_1_9_DEPLOYED_ADDRESS, BYTECODE_HASH as CloneFactory_0_1_9_BYTECODE_HASH, @@ -42,8 +50,17 @@ library LibCloneFactoryReleased { /// Every frozen release, in tag order. /// @return The released suites. function releasedSuites() internal pure returns (DeploySuite[] memory) { - DeploySuite[] memory suites = new DeploySuite[](2); + DeploySuite[] memory suites = new DeploySuite[](3); suites[0] = DeploySuite({ + suite: "clone-factory@0_1_1", + creationCode: CloneFactory_0_1_1_CREATION_CODE, + storedDeployedAddress: CloneFactory_0_1_1_DEPLOYED_ADDRESS, + storedBytecodeHash: CloneFactory_0_1_1_BYTECODE_HASH, + storedRuntimeCode: CloneFactory_0_1_1_RUNTIME_CODE, + artifactPath: "src/concrete/CloneFactory.sol:CloneFactory", + dependencies: abi.decode(CloneFactory_0_1_1_DEPENDENCIES, (address[])) + }); + suites[1] = DeploySuite({ suite: "clone-factory@0_1_9", creationCode: CloneFactory_0_1_9_CREATION_CODE, storedDeployedAddress: CloneFactory_0_1_9_DEPLOYED_ADDRESS, @@ -52,7 +69,7 @@ library LibCloneFactoryReleased { artifactPath: "src/concrete/CloneFactory.sol:CloneFactory", dependencies: abi.decode(CloneFactory_0_1_9_DEPENDENCIES, (address[])) }); - suites[1] = DeploySuite({ + suites[2] = DeploySuite({ suite: "clone-factory@0_1_10", creationCode: CloneFactory_0_1_10_CREATION_CODE, storedDeployedAddress: CloneFactory_0_1_10_DEPLOYED_ADDRESS,