From 777d5347a9520f2a6ded838660f953cde723fa79 Mon Sep 17 00:00:00 2001 From: George Knee Date: Thu, 19 Dec 2024 16:51:02 +0000 Subject: [PATCH] Fix Holocene SystemConfig upgrade scripts (#13412) * WIP update bundle to use StorageSetter/Reinitalize flow 3 txs instead of 1 Compute initialize calldata in script TODOs for computing correct values for basefeeScalar and blobbasefeeScalar * Use op-chain-ops decoder * thread OP_CONTRACTS_RELEASE through templating system * add Go to Docker image so we can use existing encoder / decoder tooling for ecotone scalars * harmonize variable names * expose entry points into sys-cfg specific cmds we don't need the deploy config or to stub out a deployments.json file * undo changes to submodule * rename variables and read more of them from systemconfigproxy * copy templates in dockerfile * thread through STORAGE_SETTER env var * cachce ecotone-scalar pkg inside dockerfile * read SystemConfig impl from SCR * update STORAGE_SETTER_ADDR * cope with breaking change in superchain registry https://github.com/ethereum-optimism/superchain-registry/pull/768#discussion_r1887582461 * fix TODO description * remove null "data" fields * add back outputs field (empty) to template msup complains if this field is missing. It also complains about the data being null or rmissing. * compute raw calldata for each tx * deep compy templates to docker image * read system config impl from SCR * document direct route to sys-cfg bundle and task * replace go get with go mod download in dockerfile * Update packages/contracts-bedrock/scripts/upgrades/holocene/scripts/common.sh --------- Co-authored-by: Sebastian Stammler --- .../scripts/upgrades/holocene/.env.example | 6 +- .../scripts/upgrades/holocene/README.md | 11 ++- .../scripts/upgrades/holocene/justfile | 34 ++++++++ .../upgrades/holocene/scripts/common.sh | 2 +- .../holocene/scripts/sc-ops-sys-cfg.sh | 8 ++ .../holocene/scripts/sys-cfg-bundle.sh | 72 +++++++++++++++- .../templates/sys-cfg-sc-ops-task/README.md | 2 +- .../sys_cfg_upgrade_bundle_template.json | 85 +++++++++++++++++-- .../upgrades/holocene/upgrade.dockerfile | 17 ++-- 9 files changed, 214 insertions(+), 23 deletions(-) diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example b/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example index 037573528c16..37175eabaab5 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example @@ -5,7 +5,7 @@ # NOTE: The deploy config must be provided as a first argument to `just run`! # The network to deploy the contracts to. -# Must be one of 'mainnet', 'sepolia' +# Must be one of mainnet, sepolia NETWORK= # Etherscan API key used to verify contract bytecode @@ -17,6 +17,10 @@ ETH_RPC_URL= # Private key used to deploy the new contracts for this upgrade PRIVATE_KEY= +# Address of a StorageSetter contract to use for setting storage slots. +# 0xd81f43eDBCAcb4c29a9bA38a13Ee5d79278270cC can be used for mainnet and sepolia +STORAGE_SETTER_ADDR=0xd81f43eDBCAcb4c29a9bA38a13Ee5d79278270cC + # Address of deployed `PreimageOracle` contract. PREIMAGE_ORACLE_ADDR= diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/README.md b/packages/contracts-bedrock/scripts/upgrades/holocene/README.md index f4828cf3d189..4d77ac0dbe2b 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/README.md +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/README.md @@ -18,7 +18,7 @@ This script has several different modes of operation. Namely: - FP options: - With permissionless fault proofs enabled (incl. `FaultDisputeGame`) - With permissioned fault proofs enabled (excl. `FaultDisputeGame`) -1. Deploy and upgrade `op-contracts/v1.3.0` -> `op-contracts/v1.8.0`, with the `L2OutputOracle` still active. +2. Deploy and upgrade `op-contracts/v1.3.0` -> `op-contracts/v1.8.0`, with the `L2OutputOracle` still active. - Only upgrade the `SystemConfig` ```sh @@ -60,3 +60,12 @@ You can use `0x03f89406817db1ed7fd8b31e13300444652cdb0b9c509a674de43483b2f83568` If you want to make local modifications to the scripts in `scripts/`, you need to build the Docker image again with `just build-image` before running `just run`. + +### Upgrading `SystemConfig` only +There is a more direct route available for those wanting to focus on generating the bundle and task for upgrading the `SystemConfig`. This route does not require a deploy config file. Instead of using `just run` as above you can do: +```sh +# You can optionally specify an output folder path different from the default `output/` as a +# second argument to these commands, also as an absolute path. You should use the same path for both commands. +just sys-cfg-bundle +just sys-cfg-task +``` diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/justfile b/packages/contracts-bedrock/scripts/upgrades/holocene/justfile index a22c001c06f6..d2ba668f388b 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/justfile +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/justfile @@ -22,6 +22,40 @@ run deploy-config-path output-folder-path="$(pwd)/output/" *args='': --env-file=.env \ op-holocene-upgrade:local {{args}} +sys-cfg-bundle output-folder-path="$(pwd)/output/" *args='': + #!/bin/bash + if [ ! "$(docker images -q op-holocene-upgrade:local 2> /dev/null)" ]; then + just build-image + fi + + mkdir -p {{output-folder-path}} + + # Run the deployment. + docker run -it \ + --rm \ + -v {{output-folder-path}}:/output \ + -e OUTPUT_FOLDER_PATH=/output \ + --env-file=.env \ + --entrypoint=./scripts/sys-cfg-bundle.sh \ + op-holocene-upgrade:local {{args}} + +sys-cfg-task output-folder-path="$(pwd)/output/" *args='': + #!/bin/bash + if [ ! "$(docker images -q op-holocene-upgrade:local 2> /dev/null)" ]; then + just build-image + fi + + mkdir -p {{output-folder-path}} + + # Run the deployment. + docker run -it \ + --rm \ + -v {{output-folder-path}}:/output \ + -e OUTPUT_FOLDER_PATH=/output \ + --env-file=.env \ + --entrypoint=./scripts/sc-ops-sys-cfg.sh \ + op-holocene-upgrade:local {{args}} + # Build the image locally. build-image: docker build \ diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/common.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/common.sh index a6304322463f..fa5d50f4227f 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/common.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/common.sh @@ -91,7 +91,7 @@ fetch_standard_address() { fi fi - local contract_path=".releases.\"op-contracts/${release_version}\".$contract_name" + local contract_path=".\"op-contracts/${release_version}\".$contract_name" local contract_address contract_address=$(yq "${contract_path}.address // ${contract_path}.implementation_address // \"\"" "${toml_path}") if [[ -z "$contract_address" ]]; then diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh index a87de445d3d5..f4f3c3910d34 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh @@ -8,6 +8,13 @@ SCRIPT_DIR=$(dirname "$0") # shellcheck disable=SC1091 source "$SCRIPT_DIR/common.sh" +NETWORK="${NETWORK:?NETWORK must be set}" +RELEASE=${OP_CONTRACTS_RELEASE:?OP_CONTRACTS_RELEASE must be set} +echo "NETWORK: $NETWORK" +echo "RELEASE: $RELEASE" +SYSTEM_CONFIG_IMPL=${SYSTEM_CONFIG_IMPL_ADDR:-$(fetch_standard_address "$NETWORK" "$RELEASE" "system_config")} +echo "SYSTEM_CONFIG_IMPL: $SYSTEM_CONFIG_IMPL" + # Check required environment variables reqenv "OUTPUT_FOLDER_PATH" reqenv "SYSTEM_CONFIG_IMPL" @@ -26,6 +33,7 @@ msup render -i "$TASK_DIR/input.json" -o "$TASK_DIR/OVERVIEW.md" # Generate the README sed -i "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$TASK_DIR/README.md" +sed -i "s/\$OP_CONTRACTS_RELEASE/$OP_CONTRACTS_RELEASE/g" "$TASK_DIR/README.md" # Generate the validation doc OLD_SYS_CFG=$(cast impl "$SYSTEM_CONFIG_PROXY_ADDR") diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh index bde4917e6b82..6b709892a563 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh @@ -8,12 +8,20 @@ SCRIPT_DIR=$(dirname "$0") # shellcheck disable=SC1091 source "$SCRIPT_DIR/common.sh" +NETWORK="${NETWORK:?NETWORK must be set}" +RELEASE=${OP_CONTRACTS_RELEASE:?OP_CONTRACTS_RELEASE must be set} +echo "NETWORK: $NETWORK" +echo "RELEASE: $RELEASE" +SYSTEM_CONFIG_IMPL=${SYSTEM_CONFIG_IMPL_ADDR:-$(fetch_standard_address "$NETWORK" "$RELEASE" "system_config")} +echo "SYSTEM_CONFIG_IMPL: $SYSTEM_CONFIG_IMPL" + # Check the env reqenv "ETH_RPC_URL" reqenv "OUTPUT_FOLDER_PATH" reqenv "PROXY_ADMIN_ADDR" reqenv "SYSTEM_CONFIG_PROXY_ADDR" reqenv "SYSTEM_CONFIG_IMPL" +reqenv "STORAGE_SETTER_ADDR" # Local environment BUNDLE_PATH="$OUTPUT_FOLDER_PATH/sys_cfg_bundle.json" @@ -22,14 +30,72 @@ L1_CHAIN_ID=$(cast chain-id) # Copy the bundle template cp ./templates/sys_cfg_upgrade_bundle_template.json "$BUNDLE_PATH" -# Tx 1: Upgrade SystemConfigProxy implementation -TX_1_PAYLOAD=$(cast calldata "upgrade(address,address)" "$SYSTEM_CONFIG_PROXY_ADDR" "$SYSTEM_CONFIG_IMPL") +# We need to re-generate the SystemConfig initialization call +# We want to use the exact same values that the SystemConfig is already using, apart from baseFeeScalar and blobBaseFeeScalar. +# Start with values we can just read off: +OWNER=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "owner()") +SCALAR=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "scalar()") +BATCHER_HASH=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "batcherHash()") +GAS_LIMIT=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "gasLimit()") +UNSAFE_BLOCK_SIGNER=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "unsafeBlockSigner()") +RESOURCE_CONFIG=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "resourceConfig()") +BATCH_INBOX=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "batchInbox()") +GAS_PAYING_TOKEN=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "gasPayingToken()(address)") +L1_CROSS_DOMAIN_MESSENGER_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "l1CrossDomainMessenger()(address)") +L1_STANDARD_BRIDGE_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "l1StandardBridge()(address)") +L1_ERC721_BRIDGE_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "l1ERC721Bridge()(address)") +DISPUTE_GAME_FACTORY_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "disputeGameFactory()(address)") +OPTIMISM_PORTAL_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "optimismPortal()(address)") +OPTIMISM_MINTABLE_ERC20_FACTORY_PROXY=$(cast call "$SYSTEM_CONFIG_PROXY_ADDR" "optimismMintableERC20Factory()(address)") + + +# Decode base fee scalar and blob base fee scalar from scalar value: +BASE_FEE_SCALAR=$(go run github.com/ethereum-optimism/optimism/op-chain-ops/cmd/ecotone-scalar --decode="$SCALAR" | awk '/^# base fee scalar[[:space:]]*:/{print $NF}') +BLOB_BASE_FEE_SCALAR=$(go run github.com/ethereum-optimism/optimism/op-chain-ops/cmd/ecotone-scalar --decode="$SCALAR" | awk '/^# blob base fee scalar[[:space:]]*:/{print $NF}') + +# Now we generate the initialization calldata +SYSTEM_CONFIG_INITIALIZE_CALLDATA=$(cast calldata \ + "initialize(address,uint32,uint32,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),address,(address,address,address,address,address,address,address))" \ + "$(cast parse-bytes32-address "$OWNER")" \ + "$BASE_FEE_SCALAR" \ + "$BLOB_BASE_FEE_SCALAR" \ + "$BATCHER_HASH" \ + "$GAS_LIMIT" \ + "$(cast parse-bytes32-address "$UNSAFE_BLOCK_SIGNER")" \ + "($(cast abi-decode "null()(uint32,uint8,uint8,uint32,uint32,uint128)" "$RESOURCE_CONFIG" --json | jq -r 'join(",")'))" \ + "$(cast parse-bytes32-address "$BATCH_INBOX")" \ + "($L1_CROSS_DOMAIN_MESSENGER_PROXY,$L1_ERC721_BRIDGE_PROXY,$L1_STANDARD_BRIDGE_PROXY,$DISPUTE_GAME_FACTORY_PROXY,$OPTIMISM_PORTAL_PROXY,$OPTIMISM_MINTABLE_ERC20_FACTORY_PROXY,$GAS_PAYING_TOKEN)" +) + +UPGRADE_PAYLOAD=$(cast calldata \ + "upgrade(address,address)" \ + "$SYSTEM_CONFIG_PROXY_ADDR" \ + "$STORAGE_SETTER_ADDR" +) + +SETBYTES32_PAYLOAD=$(cast calldata \ + "setBytes32(bytes32,bytes32)" \ + "0x0000000000000000000000000000000000000000000000000000000000000000" \ + "0x0000000000000000000000000000000000000000000000000000000000000000" +) + +UPGRADEANDCALL_PAYLOAD=$(cast calldata \ + "upgradeAndCall(address,address,bytes)" \ + "$SYSTEM_CONFIG_PROXY_ADDR" \ + "$SYSTEM_CONFIG_IMPL" \ + "$SYSTEM_CONFIG_INITIALIZE_CALLDATA" +) # Replace variables sed -i "s/\$L1_CHAIN_ID/$L1_CHAIN_ID/g" "$BUNDLE_PATH" sed -i "s/\$PROXY_ADMIN_ADDR/$PROXY_ADMIN_ADDR/g" "$BUNDLE_PATH" sed -i "s/\$SYSTEM_CONFIG_PROXY_ADDR/$SYSTEM_CONFIG_PROXY_ADDR/g" "$BUNDLE_PATH" sed -i "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$BUNDLE_PATH" -sed -i "s/\$TX_1_PAYLOAD/$TX_1_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$SYSTEM_CONFIG_INITIALIZE_CALLDATA/$SYSTEM_CONFIG_INITIALIZE_CALLDATA/g" "$BUNDLE_PATH" +sed -i "s/\$STORAGE_SETTER/$STORAGE_SETTER_ADDR/g" "$BUNDLE_PATH" +sed -i "s/\$UPGRADE_PAYLOAD/$UPGRADE_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$SETBYTES32_PAYLOAD/$SETBYTES32_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$UPGRADEANDCALL_PAYLOAD/$UPGRADEANDCALL_PAYLOAD/g" "$BUNDLE_PATH" + echo "✨ Generated SystemConfig upgrade bundle at \"$BUNDLE_PATH\"" diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys-cfg-sc-ops-task/README.md b/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys-cfg-sc-ops-task/README.md index 740219586b80..fde79700d537 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys-cfg-sc-ops-task/README.md +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys-cfg-sc-ops-task/README.md @@ -18,7 +18,7 @@ The governance proposal should be treated as the source of truth and used to ver Governance post of the upgrade can be found at . This upgrades the `SystemConfig` in the -[op-contracts/v1.8.0](https://github.com/ethereum-optimism/optimism/tree/op-contracts/v1.8.0-rc.1) release. +[$OP_CONTRACTS_RELEASE](https://github.com/ethereum-optimism/optimism/tree/$OP_CONTRACTS_RELEASE) release. ## Pre-deployments diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys_cfg_upgrade_bundle_template.json b/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys_cfg_upgrade_bundle_template.json index 62746a51982f..5d7c40a2021f 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys_cfg_upgrade_bundle_template.json +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/templates/sys_cfg_upgrade_bundle_template.json @@ -7,29 +7,96 @@ "transactions": [ { "metadata": { - "name": "Upgrade `SystemConfig` proxy", - "description": "Upgrades the `SystemConfig` proxy to the new implementation, featuring configurable EIP-1559 parameters." + "name": "ProxyAdmin.upgrade(SystemConfigProxy, StorageSetter)", + "description": "Upgrades the `SystemConfigProxy`to the StorageSetter." }, "to": "$PROXY_ADMIN_ADDR", - "value": "0x0", - "data": "$TX_1_PAYLOAD", + "data": "$UPGRADE_PAYLOAD", + "value": "0", "contractMethod": { - "type": "function", + "inputs": [ + { + "name": "_proxy", + "type": "address", + "internalType": "address payable" + }, + { + "name": "_implementation", + "type": "address", + "internalType": "address" + } + ], "name": "upgrade", + "payable": false, + "outputs": [] + }, + "contractInputsValues": { + "_proxy": "$SYSTEM_CONFIG_PROXY_ADDR", + "_implementation": "$STORAGE_SETTER" + } + }, + { + "metadata": { + "name": "SystemConfigProxy.setBytes32(0,0)", + "description": "Zeroes out the initialized state variable to allow reinitialization." + }, + "to": "$SYSTEM_CONFIG_PROXY_ADDR", + "data": "$SETBYTES32_PAYLOAD", + "value": "0", + "contractMethod": { + "inputs": [ + { + "name": "_slot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_value", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "name": "setBytes32", + "payable": false, + "outputs": [] + }, + "contractInputsValues": { + "_slot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "_value": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + { + "metadata": { + "name": "ProxyAdmin.upgradeAndCall(SystemConfigProxy, SystemConfigImplementation, Initialize())", + "description": "Upgrades the SystemConfig to a new implementation and initializes it." + }, + "to": "$PROXY_ADMIN_ADDR", + "data": "$UPGRADEANDCALL_PAYLOAD", + "value": "0", + "contractMethod": { "inputs": [ { "name": "_proxy", - "type": "address" + "type": "address", + "internalType": "address payable" }, { "name": "_implementation", - "type": "address" + "type": "address", + "internalType": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "outputs": [], - "stateMutability": "nonpayable" + "name": "upgradeAndCall", + "payable": false, + "outputs": [] }, "contractInputsValues": { + "_data": "$SYSTEM_CONFIG_INITIALIZE_CALLDATA", "_proxy": "$SYSTEM_CONFIG_PROXY_ADDR", "_implementation": "$SYSTEM_CONFIG_IMPL" } diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile b/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile index a675ab91897f..c58eb8eb55dd 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile @@ -1,16 +1,17 @@ # Use a base image with necessary tools FROM ubuntu:20.04 +FROM golang:1.22 ARG REV # Install required packages RUN apt-get update && apt-get install -y \ - git \ - bash \ - curl \ - build-essential \ - jq \ - && rm -rf /var/lib/apt/lists/* + git \ + bash \ + curl \ + build-essential \ + jq \ + && rm -rf /var/lib/apt/lists/* # Install Rust RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y @@ -37,6 +38,7 @@ WORKDIR /app # Clone the repository, only at the target revision RUN git clone --branch $REV --depth 1 https://github.com/ethereum-optimism/optimism.git . +RUN go mod download # Set the working directory to the root of the monorepo WORKDIR /app @@ -59,8 +61,9 @@ RUN forge script ./scripts/upgrades/holocene/DeployUpgrade.s.sol || true # Set the working directory to where upgrade.sh is located WORKDIR /app/packages/contracts-bedrock/scripts/upgrades/holocene -# allows to use modified local scripts +# allows to use modified local scripts and templates COPY scripts/*.sh ./scripts/ +COPY templates/ ./templates/ # Set the entrypoint to the main.sh script ENTRYPOINT ["./scripts/main.sh"]