Skip to content

Commit

Permalink
Fix Holocene SystemConfig upgrade scripts (#13412)
Browse files Browse the repository at this point in the history
* 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

ethereum-optimism/superchain-registry#768 (comment)

* 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 <[email protected]>
  • Loading branch information
geoknee and sebastianst authored Dec 19, 2024
1 parent 2073f40 commit 777d534
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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=

Expand Down
11 changes: 10 additions & 1 deletion packages/contracts-bedrock/scripts/upgrades/holocene/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
```
34 changes: 34 additions & 0 deletions packages/contracts-bedrock/scripts/upgrades/holocene/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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\""
Original file line number Diff line number Diff line change
Expand Up @@ -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 <placeholder>.

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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"]

0 comments on commit 777d534

Please sign in to comment.