Skip to content

docs(l2): add per-release upgrade test guide#6597

Open
avilagaston9 wants to merge 2 commits into
mainfrom
docs/upgrade-test-guide
Open

docs(l2): add per-release upgrade test guide#6597
avilagaston9 wants to merge 2 commits into
mainfrom
docs/upgrade-test-guide

Conversation

@avilagaston9
Copy link
Copy Markdown
Contributor

Motivation

No documented procedure for the per-release upgrade acceptance test.

Description

Adds docs/developers/l2/upgrade-test.md. Only <VERSION_FROM> / <VERSION_TO> are placeholders; the rest of the commands use Makefile defaults.

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) — N/A, docs only.

…st.md.

The procedure walks through running the previous release, draining the
committer via the admin RPC, upgrading the contracts when they changed,
and running the new release against the upgraded contracts.
Only VERSION_FROM and VERSION_TO are placeholders; every other value is
the default from crates/l2/Makefile.
@avilagaston9 avilagaston9 marked this pull request as ready for review May 11, 2026 15:41
Copilot AI review requested due to automatic review settings May 11, 2026 15:41
@avilagaston9 avilagaston9 requested a review from a team as a code owner May 11, 2026 15:41
@github-actions
Copy link
Copy Markdown

🤖 Kimi Code Review

Review of docs/developers/l2/upgrade-test.md:

Security Issues:

  1. Hardcoded Private Keys Without Prominent Warnings (Multiple locations, e.g., lines 83, 98, 140, 266, 273, 288, 296, 324, 346, 385, 439)
    The document contains multiple hardcoded private keys (e.g., 0x385c546456b6a603a1cfcaa9ec9494ba4832da08dd6bcf4de9a71e4a01b74924). While these appear to be test keys, there is no prominent warning that these are for local development only and must never be used in production or on public testnets with real value.

    Recommendation: Add a large warning block at the top of the document:

    > **⚠️ WARNING: Test Keys Only**
    > The private keys in this document are publicly known test keys for local devnets only. 
    > Never use these on mainnet or public testnets with real funds.
  2. Unclear Security Council Key Source (Lines 273, 288)
    Step 3.3 references <SECURITY_COUNCIL_PK> for emergencyExecute calls but never defines this value or maps it to the keys established in Step 1.2. Given that Step 1.2 sets --on-chain-proposer-owner 0x4417092b70a3e5f10dc504d0947dd256b965fc62, you should clarify that the Security Council PK in this test setup is the private key corresponding to this address, or provide the explicit key if it's a known test key.

Documentation Correctness:

  1. Missing L2 Chain ID Specification (Line 313)
    Step 3.3 instructs to deploy on L2 "note: L2 RPC, L2 chain id" but never specifies what the L2 chain ID is or how to retrieve it from the genesis file or running node.

    Recommendation: Add: "The L2 chain ID can be found in $WORK/l2-genesis-pinned.json under the config.chainId field, or queried via eth_chainId from the L2 RPC."

  2. Ambiguous Bytecode Parameter Format (Line 265)
    The command rex deploy <NEW_IMPL_BYTECODE> 0 ... doesn't specify whether <NEW_IMPL_BYTECODE> should be a hex string, a file path, or a prefixed 0x hex value.

  3. Hardcoded Gas Limit Without Context (Line 321)
    The upgradeL2Contract call uses a hardcoded 1000000 gas limit. This should include a note that this value may need adjustment based on the implementation contract size, or recommend estimating gas first.

Ethereum-Specific Accuracy:

  1. Correct Proxy Patterns (Lines 255-330)
    The distinction between UUPS (L1) and Transparent Upgradeable Proxy (L2) patterns is correctly documented. The ERC-1967 implementation slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc (lines 332, 351) is correct.

  2. Genesis Reuse Warning (Lines 45, 199)
    The repeated warnings about using the $VERSION_FROM genesis file when starting the $VERSION_TO sequencer (to avoid state divergence) are accurate and critical for consensus safety.

Minor Improvements:

  1. Step 3.2 Build Command (Line 240)
    The command COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null is a bit hacky to trigger a build. Consider using a more explicit make command or build script if available, or document that this is intentionally using the side-effect of help generation to compile contracts.

Overall Assessment:
The documentation is technically accurate regarding the upgrade mechanics and correctly identifies the critical safety constraint of preserving the L2 genesis file across version upgrades. The primary concerns are the security implications of documented private keys and the missing definition of the Security Council private key reference.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions
Copy link
Copy Markdown

🤖 Claude Code Review

Now I have everything I need for a thorough review.


Review: PR #6597docs(l2): add per-release upgrade test guide

Overview

This PR adds docs/developers/l2/upgrade-test.md, a copy-paste-oriented walkthrough for the per-release upgrade acceptance test. The guide covers workspace setup, running the old stack, draining and stopping it safely, performing contract upgrades, starting the new stack, and running integration tests.


What's done well

  • All internal cross-reference links resolve correctly (tested against the current tree).
  • The ERC-1967 implementation slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc is correct.
  • The drain-and-stop sequence in Step 2 is technically sound: the explanation of the commit-hash → verification-key lookup issue (why you must drain the prover before stopping) is accurate and not obvious.
  • The genesis-pinning warning is prominent and the rationale is correct.
  • The diff -qr sanity check in Step 3.2 is a solid defensive addition.
  • upgradeL2Contract function signature in the rex send call matches the contract source exactly.

Issues

1. Minor technical inaccuracy — L2 system contract upgrade description

Step 3.3 states:

"The bridge owner triggers a privileged L1→L2 transaction targeting 0x...f000, which acts as the proxy admin and forwards upgradeToAndCall to the L2 proxy."

Looking at CommonBridge.sol:683:

_sendToL2(L2_PROXY_ADMIN, sendValues);   // sendValues.to = l2Contract

The privileged message targets l2Contract (the proxy), not 0x...f000. L2_PROXY_ADMIN is the sender of the L2 transaction — i.e., msg.sender on L2 is 0x...f000. The proxy accepts upgradeToAndCall because the caller is the registered admin, not because 0x...f000 "forwards" anything.

Suggested rewording:

"The bridge owner triggers a privileged L1→L2 transaction where 0x...f000 (the proxy admin) calls upgradeToAndCall directly on the proxy. Because msg.sender is the proxy admin, the proxy accepts the call."

2. Dev private keys embedded without a standalone warning

Three raw private keys from Makefile defaults appear in the commands:

  • 0x385c546456b6a603a1cfcaa9ec9494ba4832da08dd6bcf4de9a71e4a01b74924 (committer/deployer)
  • 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e (bridge owner)
  • 0x39725efee3fb28614de3bacaffe4cc4bd8c436257e2c8bb887c4b5c4be45e76d (proof coordinator)

The intro notes they come from the Makefile, but there is no callout warning that these are well-known public dev keys. These keys are already in the public Makefile, so the security risk is equivalent. Still, a short > **Warning:** These are public development keys. Never use them with real funds or on any live network. block near the "Placeholders" section would prevent a future copy-paste mistake.

3. rex deploy unexplained positional argument

Step 3.2:

rex deploy <NEW_IMPL_BYTECODE> 0 0x385c...  --rpc-url http://localhost:8545

The 0 argument is not explained. A brief note clarifying it's the ETH value (in wei) to send with the deployment would help readers who aren't familiar with rex's argument order.

4. Hacky compile trigger in Step 3.2

COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null  # touches the build script

Running --help to trigger a build side-effect is surprising and the comment "touches the build script" doesn't fully explain what this achieves. The very next sentence contradicts it: "The compiled bytecode is embedded in the binary; to get standalone .bytecode files use forge/solc…".

It's unclear whether this command actually produces the deployable bytecode the reader needs for rex deploy. If it doesn't, this step will mislead testers. Consider either:

  • Replacing this with the actual forge build / solc invocation needed to get the .bytecode file, or
  • Adding a note clarifying that this step is a cache warm-up and the actual bytecode must be extracted differently.

5. --l1.timelock-address flag inconsistency between Step 1.3 and Step 4.1

Step 1.3 conditionally includes it:

"If the release you are testing requires --l1.timelock-address, add --l1.timelock-address "$ETHREX_TIMELOCK_ADDRESS". From v9 onwards this is required."

Step 4.1 includes it unconditionally in the command block. A tester running VERSION_FROM = v8 would omit the flag in Step 1.3 but see it hardcoded in Step 4.1. Either apply the same conditional note to Step 4.1, or consolidate the guidance (e.g., "add this flag for both Step 1.3 and Step 4.1 if VERSION_FROM >= v9").


Minor nits

  • Step 3.3 comment block for the <SECURITY_COUNCIL_PK> placeholder is left unsubstituted in the Timelock upgrade block. It could mention where that key comes from (the --on-chain-proposer-owner key passed at deploy time), since that context is only stated in the OCP block above it.
  • The --backend exec flag in Steps 1.4 and 4.2 has no explanation. A one-liner noting this is the CPU/execution backend (no GPU or external prover required) would help orientation.

Summary

The guide is well-structured and technically sound for the happy path. The main actionable items before merging are: fixing the L2 privileged-message target description (Point 1, it's currently wrong), clarifying the compile step (Point 4, currently misleading), and adding a visible warning about the embedded dev keys (Point 2). Points 3 and 5 are lower priority.


Automated review by Claude (Anthropic) · sonnet · custom prompt

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR adds docs/developers/l2/upgrade-test.md, a new step-by-step acceptance guide for per-release node upgrades covering workspace setup, draining and stopping the old sequencer, upgrading L1/L2 contracts in-place, and running the integration test suite against the new binary.

  • The guide is well-structured and covers the full upgrade lifecycle, including L1 UUPS proxies, L2 transparent proxies, the Timelock emergencyExecute path, and the genesis-pinning invariant.
  • Two issues block the copy-paste experience: the "Build and deploy" subsection in Step 3.2 uses COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null which is a no-op against a pre-compiled binary (the variable is consumed only by Cargo's build script at compile time), and Step 3.3 leaves <SECURITY_COUNCIL_PK> as an unresolved placeholder despite every other key in the guide being a concrete hex value.

Confidence Score: 3/5

Safe to merge once the two copy-paste blockers in Steps 3.2 and 3.3 are resolved; the rest of the guide is accurate and well-grounded in the actual codebase defaults.

The "Build and deploy" compile step silently does nothing (the env var is build-time only), leaving the rex deploy command with no path to obtain the bytecode it needs. Separately, <SECURITY_COUNCIL_PK> appears in two consecutive commands but is never defined, directly contradicting the guide's own copy-paste promise. Both gaps would stall a developer mid-procedure at the most sensitive part of the upgrade.

docs/developers/l2/upgrade-test.md — specifically the "Build and deploy" block in Step 3.2 and both emergencyExecute commands in Step 3.3.

Important Files Changed

Filename Overview
docs/developers/l2/upgrade-test.md New per-release upgrade test guide; well-structured overall but has two blockers: the "Build and deploy" compile step is a no-op against a pre-compiled binary, and two <SECURITY_COUNCIL_PK> placeholders in Step 3.3 break the copy-paste promise.
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 4
docs/developers/l2/upgrade-test.md:276-291
**Misleading compile step — `COMPILE_CONTRACTS` is a build-time variable, not a runtime one**

`COMPILE_CONTRACTS` is read exclusively by `cmd/ethrex/build.rs` (the Cargo build script) at compile time; setting it when invoking an already-compiled binary has no effect. The command `COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null` silently does nothing useful: `--help` exits immediately and the env var is ignored by the running process.

As the next comment in the code block already notes, the bytecode is embedded in the binary at build time. To obtain standalone `.bytecode` files needed for `rex deploy`, a user must either (a) recompile the binary from the `$VERSION_TO` source tree with `COMPILE_CONTRACTS=true cargo build --release --features l2,l2-sql` and extract the files from `$OUT_DIR/contracts/solc_out/`, or (b) compile with `forge`/`solc` directly against the contract sources. Neither path is actually shown, leaving `rex deploy <NEW_IMPL_BYTECODE>` as an unactionable placeholder.

### Issue 2 of 4
docs/developers/l2/upgrade-test.md:309-313
**`<SECURITY_COUNCIL_PK>` left as a placeholder, breaking the copy-paste promise**

The introduction states "the commands below are ready to copy-paste; the only thing you need to substitute is the version tags." However, Step 3.3 uses `<SECURITY_COUNCIL_PK>` without resolving it to a concrete value. The Security Council key corresponds to the `--on-chain-proposer-owner` address (`0x4417092b70a3e5f10dc504d0947dd256b965fc62`), whose private key is the `BRIDGE_OWNER_PRIVATE_KEY` used everywhere else in this guide (`0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e`). Substituting the literal hex value is consistent with how every other key in this document is presented.

```suggestion
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_OCP_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
  'emergencyExecute(address,uint256,bytes)' "$ETHREX_COMMITTER_ON_CHAIN_PROPOSER_ADDRESS" 0 "$UPGRADE_CALLDATA" \
  --private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
  --rpc-url http://localhost:8545
```

### Issue 3 of 4
docs/developers/l2/upgrade-test.md:321-325
Same unresolved `<SECURITY_COUNCIL_PK>` placeholder in the Timelock-self-upgrade block. Should be the same concrete key as above.

```suggestion
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_TIMELOCK_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
  'emergencyExecute(address,uint256,bytes)' "$ETHREX_TIMELOCK_ADDRESS" 0 "$UPGRADE_CALLDATA" \
  --private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
  --rpc-url http://localhost:8545
```

### Issue 4 of 4
docs/developers/l2/upgrade-test.md:432-435
**Redundant `.env` copy in Step 5**

Step 4.1 already copies `cmd/.env` into the `$VERSION_TO` tree. Repeating the copy in Step 5 is a no-op and may confuse readers into thinking the file might have changed between steps.

```suggestion
cd "$WORK/ethrex-$VERSION_TO/crates/l2"
make test
```

Reviews (1): Last reviewed commit: "Remove the expected-duration sentence fr..." | Re-trigger Greptile

Comment on lines +276 to +291
```bash
cd "$WORK/ethrex-$VERSION_TO"
# Compile the contracts into local bytecode files (writes to target/.../solc_out/).
COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null # touches the build script
# The compiled bytecode is embedded in the binary; to get standalone .bytecode files use forge/solc on
# the contract sources under crates/l2/contracts/src/l1/ — see the build script in cmd/ethrex/build_l2.rs.
```

For each upgradable contract listed in the migration guide:

```bash
# 1. Deploy the new implementation. Use the deployer's private key; this is just a code deployment.
rex deploy <NEW_IMPL_BYTECODE> 0 0x385c546456b6a603a1cfcaa9ec9494ba4832da08dd6bcf4de9a71e4a01b74924 \
--rpc-url http://localhost:8545
# rex prints the new implementation address — note it.
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Misleading compile step — COMPILE_CONTRACTS is a build-time variable, not a runtime one

COMPILE_CONTRACTS is read exclusively by cmd/ethrex/build.rs (the Cargo build script) at compile time; setting it when invoking an already-compiled binary has no effect. The command COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null silently does nothing useful: --help exits immediately and the env var is ignored by the running process.

As the next comment in the code block already notes, the bytecode is embedded in the binary at build time. To obtain standalone .bytecode files needed for rex deploy, a user must either (a) recompile the binary from the $VERSION_TO source tree with COMPILE_CONTRACTS=true cargo build --release --features l2,l2-sql and extract the files from $OUT_DIR/contracts/solc_out/, or (b) compile with forge/solc directly against the contract sources. Neither path is actually shown, leaving rex deploy <NEW_IMPL_BYTECODE> as an unactionable placeholder.

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/developers/l2/upgrade-test.md
Line: 276-291

Comment:
**Misleading compile step — `COMPILE_CONTRACTS` is a build-time variable, not a runtime one**

`COMPILE_CONTRACTS` is read exclusively by `cmd/ethrex/build.rs` (the Cargo build script) at compile time; setting it when invoking an already-compiled binary has no effect. The command `COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null` silently does nothing useful: `--help` exits immediately and the env var is ignored by the running process.

As the next comment in the code block already notes, the bytecode is embedded in the binary at build time. To obtain standalone `.bytecode` files needed for `rex deploy`, a user must either (a) recompile the binary from the `$VERSION_TO` source tree with `COMPILE_CONTRACTS=true cargo build --release --features l2,l2-sql` and extract the files from `$OUT_DIR/contracts/solc_out/`, or (b) compile with `forge`/`solc` directly against the contract sources. Neither path is actually shown, leaving `rex deploy <NEW_IMPL_BYTECODE>` as an unactionable placeholder.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +309 to +313
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_OCP_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_COMMITTER_ON_CHAIN_PROPOSER_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key <SECURITY_COUNCIL_PK> \
--rpc-url http://localhost:8545
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 <SECURITY_COUNCIL_PK> left as a placeholder, breaking the copy-paste promise

The introduction states "the commands below are ready to copy-paste; the only thing you need to substitute is the version tags." However, Step 3.3 uses <SECURITY_COUNCIL_PK> without resolving it to a concrete value. The Security Council key corresponds to the --on-chain-proposer-owner address (0x4417092b70a3e5f10dc504d0947dd256b965fc62), whose private key is the BRIDGE_OWNER_PRIVATE_KEY used everywhere else in this guide (0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e). Substituting the literal hex value is consistent with how every other key in this document is presented.

Suggested change
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_OCP_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_COMMITTER_ON_CHAIN_PROPOSER_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key <SECURITY_COUNCIL_PK> \
--rpc-url http://localhost:8545
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_OCP_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_COMMITTER_ON_CHAIN_PROPOSER_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
--rpc-url http://localhost:8545
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/developers/l2/upgrade-test.md
Line: 309-313

Comment:
**`<SECURITY_COUNCIL_PK>` left as a placeholder, breaking the copy-paste promise**

The introduction states "the commands below are ready to copy-paste; the only thing you need to substitute is the version tags." However, Step 3.3 uses `<SECURITY_COUNCIL_PK>` without resolving it to a concrete value. The Security Council key corresponds to the `--on-chain-proposer-owner` address (`0x4417092b70a3e5f10dc504d0947dd256b965fc62`), whose private key is the `BRIDGE_OWNER_PRIVATE_KEY` used everywhere else in this guide (`0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e`). Substituting the literal hex value is consistent with how every other key in this document is presented.

```suggestion
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_OCP_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
  'emergencyExecute(address,uint256,bytes)' "$ETHREX_COMMITTER_ON_CHAIN_PROPOSER_ADDRESS" 0 "$UPGRADE_CALLDATA" \
  --private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
  --rpc-url http://localhost:8545
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +321 to +325
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_TIMELOCK_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_TIMELOCK_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key <SECURITY_COUNCIL_PK> \
--rpc-url http://localhost:8545
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Same unresolved <SECURITY_COUNCIL_PK> placeholder in the Timelock-self-upgrade block. Should be the same concrete key as above.

Suggested change
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_TIMELOCK_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_TIMELOCK_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key <SECURITY_COUNCIL_PK> \
--rpc-url http://localhost:8545
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_TIMELOCK_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
'emergencyExecute(address,uint256,bytes)' "$ETHREX_TIMELOCK_ADDRESS" 0 "$UPGRADE_CALLDATA" \
--private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
--rpc-url http://localhost:8545
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/developers/l2/upgrade-test.md
Line: 321-325

Comment:
Same unresolved `<SECURITY_COUNCIL_PK>` placeholder in the Timelock-self-upgrade block. Should be the same concrete key as above.

```suggestion
UPGRADE_CALLDATA=$(rex encode 'upgradeToAndCall(address,bytes)' <NEW_TIMELOCK_IMPL_ADDR> 0x)
rex send "$ETHREX_TIMELOCK_ADDRESS" \
  'emergencyExecute(address,uint256,bytes)' "$ETHREX_TIMELOCK_ADDRESS" 0 "$UPGRADE_CALLDATA" \
  --private-key 0x941e103320615d394a55708be13e45994c7d93b932b064dbcb2b511fe3254e2e \
  --rpc-url http://localhost:8545
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +432 to +435
cd "$WORK/ethrex-$VERSION_TO"
cp "$WORK/ethrex-$VERSION_FROM/cmd/.env" cmd/.env # contract addresses from the v$VERSION_FROM deploy
cd crates/l2
make test
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant .env copy in Step 5

Step 4.1 already copies cmd/.env into the $VERSION_TO tree. Repeating the copy in Step 5 is a no-op and may confuse readers into thinking the file might have changed between steps.

Suggested change
cd "$WORK/ethrex-$VERSION_TO"
cp "$WORK/ethrex-$VERSION_FROM/cmd/.env" cmd/.env # contract addresses from the v$VERSION_FROM deploy
cd crates/l2
make test
cd "$WORK/ethrex-$VERSION_TO/crates/l2"
make test
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/developers/l2/upgrade-test.md
Line: 432-435

Comment:
**Redundant `.env` copy in Step 5**

Step 4.1 already copies `cmd/.env` into the `$VERSION_TO` tree. Repeating the copy in Step 5 is a no-op and may confuse readers into thinking the file might have changed between steps.

```suggestion
cd "$WORK/ethrex-$VERSION_TO/crates/l2"
make test
```

How can I resolve this? If you propose a fix, please make it concise.

@github-actions
Copy link
Copy Markdown

🤖 Codex Code Review

  1. Medium – docs/developers/l2/upgrade-test.md:278: COMPILE_CONTRACTS=true ./ethrex l2 deploy --help will not generate fresh .bytecode artifacts. COMPILE_CONTRACTS is consumed by the Rust build script at cargo build time, not when executing an already-downloaded binary (cmd/ethrex/build_l2.rs:27), and the deployer reads embedded bytecode via include_bytes! (cmd/ethrex/l2/deployer.rs:510). As written, Step 3.2 leaves the operator with no supported way to obtain <NEW_IMPL_BYTECODE>, so the documented upgrade flow cannot actually be completed.

  2. Medium – docs/developers/l2/upgrade-test.md:309, docs/developers/l2/upgrade-test.md:391: the guide assumes $ETHREX_TIMELOCK_ADDRESS already exists, but that is false for the v8→v9 migration where Timelock is introduced during the upgrade. Step 4 then copies the old cmd/.env back into $VERSION_TO, so the new address is dropped before restart; the integration tests also source cmd/.env (test/tests/l2/utils.rs:17). The guide needs an explicit “persist/merge migrated addresses into .env” step, at minimum for ETHREX_TIMELOCK_ADDRESS, or the restart command can fail / target the wrong contract.

Aside from those documentation blockers, the PR is docs-only and I did not see runtime/EVM logic changes to review.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new developer-facing L2 “upgrade acceptance test” runbook to standardize the per-release procedure for stopping a running stack, upgrading L1/L2 contracts, and validating the upgraded system via the existing integration test suite.

Changes:

  • Introduces a step-by-step upgrade test guide covering workspace setup, safe shutdown, contract upgrade paths, restart, and validation.
  • Documents how to pin the $VERSION_FROM L2 genesis to avoid chain divergence during upgrades.
  • Recommends using the standard L2 integration tests (make test) as the final acceptance check.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +278 to +281
# Compile the contracts into local bytecode files (writes to target/.../solc_out/).
COMPILE_CONTRACTS=true ./ethrex l2 deploy --help >/dev/null # touches the build script
# The compiled bytecode is embedded in the binary; to get standalone .bytecode files use forge/solc on
# the contract sources under crates/l2/contracts/src/l1/ — see the build script in cmd/ethrex/build_l2.rs.
pkill -INT -f 'ethrex l2 --watcher' || true # sequencer
pkill -INT -f 'ethrex l2 prover' || true # prover
sleep 2
sudo ss -tlnp | grep -E ':(1729|3900|5555)\b' || echo "L2 ports clean"
make test
```

`make test` calls `cargo test -p ethrex-test l2_integration_test --features l2 -- --nocapture`. It assumes the dev node and prover are already up on the default ports (`L2 RPC 1729`, `proof coordinator 3900`), which is exactly the state Step 4 leaves you in.
Comment on lines +1 to +9
# Upgrade test

This is a per-release acceptance test. The goal is to verify that:

1. A node running the **previous release** (`<VERSION_FROM>`) can be cleanly stopped.
2. The L1 contracts can be upgraded following the per-release migration guide.
3. The **new release** (`<VERSION_TO>`) sequencer and prover resume operation against the upgraded contracts without re-deploying from scratch.

The commands below are ready to copy-paste. The only thing you need to substitute is the version tags. Every other value (private keys, addresses, ports, fee parameters) is taken from the defaults in `crates/l2/Makefile`; feel free to override them, but the values below give you a working baseline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L2 Rollup client

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants