diff --git a/.env.example b/.env.example index f85f5ba..f88a536 100644 --- a/.env.example +++ b/.env.example @@ -8,7 +8,9 @@ ARBITRUM_RPC_URL=https://arb1.arbitrum.io/rpc BASE_RPC_URL=https://mainnet.base.org BASE_SEPOLIA_RPC_URL=https://sepolia.base.org +BSC_RPC_URL=https://bsc-dataseed.binance.org ETHEREUM_RPC_URL=https://eth-pokt.nodies.app FLARE_RPC_URL=https://flare-api.flare.network/ext/C/rpc HYPEREVM_RPC_URL=https://rpc.hyperliquid.xyz/evm POLYGON_RPC_URL=https://polygon-bor-rpc.publicnode.com +ROBINHOOD_RPC_URL=https://rpc.mainnet.chain.robinhood.com diff --git a/.github/workflows/manual-sol-verify.yaml b/.github/workflows/manual-sol-verify.yaml index 0d66b1a..3b3a481 100644 --- a/.github/workflows/manual-sol-verify.yaml +++ b/.github/workflows/manual-sol-verify.yaml @@ -33,13 +33,16 @@ on: networks: type: string required: true - default: arbitrum base base-sepolia mainnet flare hyperliquid polygon + default: arbitrum base base-sepolia bsc mainnet flare hyperliquid polygon description: | Which explorers to submit to. FOUNDRY's chain names, not the - `[rpc_endpoints]` aliases, and the two differ on three of the seven: + `[rpc_endpoints]` aliases, and the two differ on three of the nine: the aliases `base_sepolia`, `ethereum` and `hyperevm` are rejected outright, and the chain names are `base-sepolia`, `mainnet` and - `hyperliquid`. The default is + `hyperliquid`. Robinhood Chain (4663) is deliberately absent from + the default: Etherscan does not index it, so its Blockscout is the + only explorer target and that has rejected non-browser clients — + verify it through Sourcify by hand. The default is `LibRainDeploy.supportedNetworks()` spelled that way, i.e. every network the deploy broadcasts to, so it has to move when that does. jobs: diff --git a/foundry.toml b/foundry.toml index 3c0583f..4826c97 100644 --- a/foundry.toml +++ b/foundry.toml @@ -77,10 +77,12 @@ recursive_deps = false arbitrum = "${ARBITRUM_RPC_URL}" base = "${BASE_RPC_URL}" base_sepolia = "${BASE_SEPOLIA_RPC_URL}" +bsc = "${BSC_RPC_URL}" ethereum = "${ETHEREUM_RPC_URL}" flare = "${FLARE_RPC_URL}" hyperevm = "${HYPEREVM_RPC_URL}" polygon = "${POLYGON_RPC_URL}" +robinhood = "${ROBINHOOD_RPC_URL}" # `rainix-manual-sol-artifacts` passes `--verify` by default and exports exactly # these variable names, so a deploy without this section broadcasts and then @@ -101,7 +103,16 @@ 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}" } +bsc = { key = "${CI_DEPLOY_BSC_ETHERSCAN_API_KEY}", chain = 56 } 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 } polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}" } +# Robinhood Chain (4663) is not indexed by Etherscan V2. Its Blockscout +# explorer speaks the Etherscan API, so the entry points there; the key is +# whatever `CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY` carries (Blockscout ignores +# it). Blockscout sits behind a browser challenge that has rejected non-browser +# clients, so if `--verify` fails on this network after a broadcast, verify +# afterwards through Sourcify (which supports 4663 and which Blockscout +# imports): `forge verify-contract --verifier sourcify --chain 4663 ...`. +robinhood = { key = "${CI_DEPLOY_ROBINHOOD_ETHERSCAN_API_KEY}", chain = 4663, url = "https://robinhoodchain.blockscout.com/api" } diff --git a/src/lib/LibRainDeploy.sol b/src/lib/LibRainDeploy.sol index 1f0c3e3..d794da2 100644 --- a/src/lib/LibRainDeploy.sol +++ b/src/lib/LibRainDeploy.sol @@ -82,6 +82,11 @@ library LibRainDeploy { /// Config name for Base network. string constant BASE = "base"; + /// Config name for BNB Smart Chain (chain id 56). The Zoltu factory is + /// deployed there with the canonical runtime, so deterministic deploys + /// land at the same addresses as on every other supported network. + string constant BSC = "bsc"; + /// Config name for Base Sepolia testnet. string constant BASE_SEPOLIA = "base_sepolia"; @@ -97,6 +102,12 @@ library LibRainDeploy { /// Config name for Polygon network. string constant POLYGON = "polygon"; + /// Config name for Robinhood Chain (chain id 4663), an Arbitrum Orbit L2 + /// settling to Ethereum. The Zoltu factory is deployed there with the + /// canonical runtime, so deterministic deploys land at the same addresses + /// as on every other supported network. + string constant ROBINHOOD = "robinhood"; + /// Checks whether a block is the first block where a contract with the /// expected code hash exists. True when the target has the expected code /// hash at `blockNumber` and does NOT have it at `blockNumber - 1`. At @@ -284,14 +295,16 @@ library LibRainDeploy { /// Returns the list of networks currently supported by Rain deployments. /// @return The list of supported network names. function supportedNetworks() internal pure returns (string[] memory) { - string[] memory networks = new string[](7); + string[] memory networks = new string[](9); networks[0] = ARBITRUM_ONE; networks[1] = BASE; networks[2] = BASE_SEPOLIA; - networks[3] = ETHEREUM; - networks[4] = FLARE; - networks[5] = HYPEREVM; - networks[6] = POLYGON; + networks[3] = BSC; + networks[4] = ETHEREUM; + networks[5] = FLARE; + networks[6] = HYPEREVM; + networks[7] = POLYGON; + networks[8] = ROBINHOOD; return networks; } diff --git a/test/src/lib/LibRainDeploy.t.sol b/test/src/lib/LibRainDeploy.t.sol index 9c5be2c..e051d40 100644 --- a/test/src/lib/LibRainDeploy.t.sol +++ b/test/src/lib/LibRainDeploy.t.sol @@ -193,18 +193,20 @@ contract LibRainDeployTest is Test { ); } - /// `supportedNetworks` MUST return exactly 7 networks in the expected + /// `supportedNetworks` MUST return exactly 9 networks in the expected /// order matching the library constants. function testSupportedNetworks() external pure { string[] memory networks = LibRainDeploy.supportedNetworks(); - assertEq(networks.length, 7); + assertEq(networks.length, 9); assertEq(networks[0], LibRainDeploy.ARBITRUM_ONE); assertEq(networks[1], LibRainDeploy.BASE); assertEq(networks[2], LibRainDeploy.BASE_SEPOLIA); - assertEq(networks[3], LibRainDeploy.ETHEREUM); - assertEq(networks[4], LibRainDeploy.FLARE); - assertEq(networks[5], LibRainDeploy.HYPEREVM); - assertEq(networks[6], LibRainDeploy.POLYGON); + assertEq(networks[3], LibRainDeploy.BSC); + assertEq(networks[4], LibRainDeploy.ETHEREUM); + assertEq(networks[5], LibRainDeploy.FLARE); + assertEq(networks[6], LibRainDeploy.HYPEREVM); + assertEq(networks[7], LibRainDeploy.POLYGON); + assertEq(networks[8], LibRainDeploy.ROBINHOOD); } /// `ZOLTU_FACTORY_CODEHASH` MUST match the actual codehash of the Zoltu