From 5f7f3eb7756956b8e4e8d3ed7bddb3ea9a4d044b Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Fri, 31 Jan 2025 14:53:04 +0200 Subject: [PATCH] Add reference to multichain deployment (#1414) * Add reference to multichain deployment * nits --------- Co-authored-by: zerosnacks --- src/forge/deploying.md | 76 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/src/forge/deploying.md b/src/forge/deploying.md index 37a0a68ee..2e1b8f60b 100644 --- a/src/forge/deploying.md +++ b/src/forge/deploying.md @@ -4,7 +4,7 @@ Forge can deploy smart contracts to a given network with the [`forge create`](.. Forge CLI can deploy only one contract at a time. -For deploying and verifying multiple smart contracts in one go, Forge's [Solidity scripting](../tutorials/solidity-scripting.md#deploying-our-contract) would be the more efficient approach. +For deploying and verifying multiple smart contracts on multiple chains in one go, Forge's [Solidity scripting](../tutorials/solidity-scripting.md#deploying-our-contract) would be the more efficient approach. To deploy a contract, you must provide a RPC URL (env: `ETH_RPC_URL`) and the private key of the account that will deploy the contract. @@ -52,6 +52,50 @@ $ forge create --rpc-url \ src/MyToken.sol:MyToken ``` +## Multi-chain deployments + +Deploying and verifying multiple smart contracts on multiple chains in one go is possible by using forking cheatcodes. + +For example, if you want to deploy a `Counter` contract on Sepolia Mainnet and Base Sepolia using a single command, you can configure RPC endpoints and verifiers as: + +```toml +[rpc_endpoints] +sepolia = "${SEPOLIA_URL}" +base-sepolia = "${BASE_SEPOLIA_URL}" + +[etherscan] +sepolia = { key = "${SEPOLIA_KEY}" } +base-sepolia = { key = "${BASE_SEPOLIA_KEY}" } +``` + +and create a `CounterScript` script as: + +```solidity +contract CounterScript is Script { + function run() public { + vm.createSelectFork("sepolia"); + vm.startBroadcast(); + new Counter(); + vm.stopBroadcast(); + + vm.createSelectFork("base-sepolia"); + vm.startBroadcast(); + new Counter(); + vm.stopBroadcast(); + } +} +``` + +When running: + +```sh +$ forge script script/CounterScript.s.sol --slow --multi --broadcast --private-key --verify +``` + +The script will create the Sepolia Mainnet fork (`vm.createSelectFork("sepolia")`), deploy and verify the `Counter` contract, and then move to Base Sepolia chain deployment (`vm.createSelectFork("base-sepolia")`). + +For a list of all available forking cheatcodes see [`forking`](../cheatcodes/forking.md) docs. + ## Verifying a pre-existing contract It is recommended to use the `--verify` flag with `forge create` to automatically verify the contract on explorer after a deployment. @@ -62,18 +106,20 @@ If you are verifying an already deployed contract, read on. You can verify a contract on Etherscan, Sourcify, oklink or Blockscout with the [`forge verify-contract`](../reference/forge/forge-verify-contract.md) command. You must provide: + - the contract address - the contract name or the path to the contract `:` - your Etherscan API key (env: `ETHERSCAN_API_KEY`) (if verifying on Etherscan). Moreover, you may need to provide: + - the constructor arguments in the ABI-encoded format, if there are any - external linked libraries in `src_file_path:library_name:library_address` format, if there are any - [compiler version](https://etherscan.io/solcversions) used for build, with 8 hex digits from the commit version prefix (the commit will usually not be a nightly build). It is auto-detected if not specified. -- the number of optimizations, if the Solidity optimizer was activated. It is auto-detected if not specified. +- the number of optimizations, if the Solidity optimizer was activated. It is auto-detected if not specified. - the [chain ID](https://evm-chainlist.netlify.app/), if the contract is not on Ethereum Mainnet -Let's say you want to verify `MyToken` (see above). You set the [number of optimizations](../reference/config/solidity-compiler.md#optimizer_runs) to 1 million, compiled it with v0.8.10, and deployed it, as shown above, to the Sepolia testnet (chain ID: 11155111). Note that `--num-of-optimizations` will default to 0 if not set on verification, while it defaults to 200 if not set on deployment, so make sure you pass `--num-of-optimizations 200` if you left the default compilation settings. +Let's say you want to verify `MyToken` (see above). You set the [number of optimizations](../reference/config/solidity-compiler.md#optimizer_runs) to 1 million, compiled it with v0.8.10, and deployed it, as shown above, to the Sepolia testnet (chain ID: 11155111). Note that `--num-of-optimizations` will default to 0 if not set on verification, while it defaults to 200 if not set on deployment, so make sure you pass `--num-of-optimizations 200` if you left the default compilation settings. Here's how to verify it: @@ -86,7 +132,7 @@ forge verify-contract \ --etherscan-api-key \ --compiler-version v0.8.10+commit.fc410830 \ \ - src/MyToken.sol:MyToken + src/MyToken.sol:MyToken Submitted contract for verification: Response: `OK` @@ -94,13 +140,15 @@ Submitted contract for verification: url: https://sepolia.etherscan.io//address/0x6a54…3a4c#code ``` -> ℹ️ **Note:** -> -> External libraries can be specified with `--libraries` argument, one for each linked library. For example, to verify a contract with two linked libraries (`Maths` and `Utils`) the `forge verify-command` should be run with +> ℹ️ **Note:** +> +> External libraries can be specified with `--libraries` argument, one for each linked library. For example, to verify a contract with two linked libraries (`Maths` and `Utils`) the `forge verify-command` should be run with +> > ```bash > --libraries src/lib/Maths.sol:Maths: \ > --libraries src/lib/Utils.sol:Utils: > ``` +> > arguments. It is recommended to use the [`--watch`](../reference/forge/forge-verify-contract.md#verify-contract-options) flag along @@ -117,7 +165,7 @@ Contract successfully verified.
> 💡 **Tip** -> +> > Use Cast's [`abi-encode`](../reference/cast/cast-abi-encode.md) to ABI-encode arguments. > > In this example, we ran `cast abi-encode "constructor(string,string,uint8,uint256)" "ForgeUSD" "FUSD" 18 1000000000000000000000` to ABI-encode the arguments. @@ -131,24 +179,28 @@ Contract successfully verified. Make sure the private key string begins with `0x`. ##### `EIP-1559 not activated` + EIP-1559 is not supported or not activated on the RPC server. Pass the `--legacy` flag to use legacy transactions instead of the EIP-1559 ones. If you do development in a local environment, you can use Hardhat instead of Ganache. ##### `Failed to parse tokens` + Make sure the passed arguments are of correct type. ##### `Signature error` + Make sure the private key is correct. ##### `Compiler version commit for verify` + If you want to check the exact commit you are running locally, try: ` ~/.svm/0.x.y/solc-0.x.y --version` where `x` and -`y` are major and minor version numbers respectively. The output of this will be something like: +`y` are major and minor version numbers respectively. The output of this will be something like: ```ignore solc, the solidity compiler commandline interface Version: 0.8.12+commit.f00d7308.Darwin.appleclang ``` -Note: You cannot just paste the entire string "0.8.12+commit.f00d7308.Darwin.appleclang" as the argument for the compiler-version. But you can use the 8 hex digits of the commit to look up exactly what you should copy and paste from [compiler version](https://etherscan.io/solcversions). +Note: You cannot just paste the entire string "0.8.12+commit.f00d7308.Darwin.appleclang" as the argument for the compiler-version. But you can use the 8 hex digits of the commit to look up exactly what you should copy and paste from [compiler version](https://etherscan.io/solcversions). ### Known Issues @@ -156,12 +208,14 @@ Note: You cannot just paste the entire string "0.8.12+commit.f00d7308.Darwin.app Forge passes source directories (`src`, `lib`, `test` etc) as `--include-path` arguments to the compiler. This means that given the following project tree + ```text |- src |-- folder |--- Contract.sol |--- IContract.sol ``` + it is possible to import `IContract` inside the `Contract.sol` using `folder/IContract.sol` import path. Etherscan is not able to recompile such sources. Consider changing the imports to use relative import path. @@ -171,4 +225,4 @@ Etherscan is not able to recompile such sources. Consider changing the imports t Currently, it's not possible to verify contracts on Etherscan with [`bytecode_hash`](../reference/config/solidity-compiler.md#bytecode_hash) set to `none`. Click [here](https://docs.soliditylang.org/en/v0.8.13/metadata.html#usage-for-source-code-verification) to learn more about -how metadata hash is used for source code verification. +how metadata hash is used for source code verification.