Skip to content

contracts: generate CGTv2 direct upgrade deposits - #570

Merged
seolaoh merged 12 commits into
celo-contracts/v6.0.0from
seolaoh/cgtv2-direct-upgrade-contracts
Nov 3, 2026
Merged

seolaoh merged 12 commits into
celo-contracts/v6.0.0from
seolaoh/cgtv2-direct-upgrade-contracts

Conversation

@seolaoh

@seolaoh seolaoh commented Oct 28, 2026 •

Copy link
Copy Markdown

Prepare the CGTv2 L2 migration as ordinary upgrade deposits using the existing v6 proxies. The work supports the client migration in celo-org/celo-kona#241, #567 and the Kona integration in celo-org/celo-kona#364, tracked in celo-org/celo-blockchain-planning#1466.

The generator freezes 15 static deposits for implementation deployment, direct upgrades/initialization, authorization, ownership transfer and CGT enablement. It preserves legacy fee-vault settings, balances and totalProcessed, with no initializer reset or StorageSetter. Clients append the separate dynamic reserve-funding deposit using the authenticated EscrowSeeded amount.

The production tool resolves one L2 block and captures three legacy vault getters at that block hash. Token metadata must be supplied explicitly in deployment config as Celo/CELO: the legacy mainnet L1Block getters return Ether/ETH. Generation and preflight verification check the configured metadata against the frozen initializer calldata.

Activation ordering: all Portal deposits from the activation L1 origin, including deposits emitted after EscrowSeeded, execute against the pre-migration L2 state. The client appends the CGTv2 upgrade group after all of that origin's deposits and excludes ordinary L2 user transactions from the activation block.

This remains a draft: the checked-in bundle is synthetic. Final reserved bridge/L1 addresses, governance inputs, production bundle/compiler approval, gas calibration and production devnet parity remain required.

Rebased onto target 8c7d7a12c8 with the same three PR patches. Post-rebase validation at 23862755b7: migration suite 8/8, production workflow 19/19, formatting and all 19 frozen-fixture digests pass. Frozen fixtures are unchanged.

Earlier validation at f815d3176c with the repository's Foundry 1.2.3 pin:

  • Full unit matrix: main 2,122 passed; interop 2,182; Kona/dispute-games 2,122; CGT 2,091. Zero failures, with existing feature skips retained.
  • PR test files pass in all four configurations with 20,000 fuzz runs. This uses the working ci compiler profile because the inherited ciheavy profile fails compilation before tests.
  • Production workflow: 19 Python tests pass.
  • Local fork of Celo mainnet block 81,390,869: the complete upgrade group and reserve deposit pass without state overrides, preserving vault settings/balance/totalProcessed and L1 origin fields. Production-tool generation and verification also pass against this parent. Deployment addresses in this test are placeholders; no transaction was broadcast.
  • Frozen bundle/prestate regeneration is byte-identical. All 19 recorded digests and 20 fixture files in each published client match.
  • Formatting, production build, storage spacers, reinitializers, OPCM checks, deploy-config validation, contract size and Semgrep rule tests pass. All pinned dependency exports match their Git objects.

Inherited failures are reported separately, as agreed: strict Semgrep reproduces 817 base findings with zero new findings; existing interface/import/semver/test-naming checks and generated snapshot/Kontrol-summary comparisons remain failing. Kontrol summary generation and proof-source compilation pass, but coverage compilation fails on warnings in unchanged dependencies. These are not reported as green CI gates.

CI repair validation on 512ba56c89: 8 baseline regression tests and full config validation/processing pass locally, with zero new diff-aware Semgrep findings. PR baselines now come from GitHub PR merge refs without REST API access. Go and memory acceptance jobs use celo-org/2xlarge. In pipeline 3818, the diff-aware Semgrep scan, Go lint and contracts build pass. Go and memory acceptance jobs are still waiting to start, and the contracts test matrix is running. Full CI remains red: contracts checks fail snapshot/interface/import checks and the pinned Semgrep installation lacks pkg_resources; the Cannon job fails during Codecov GPG key validation.

Generate the final 15-step CGTv2 group through existing v6 proxy methods.
Deploy six implementations and initialize the bridge, controller and fee
vault without Karst manager backports or initializer resets. Clients append
the dynamic reserve-funding deposit separately.

Preserve ProxyAdmin, legacy fee-vault settings, balances and totalProcessed.
Cover execution, authorization, failed initialization and zero funding, and
align the existing L2 tests with CGT genesis settings.
Export the synthetic NUT bundle and prestate as deposit RLP vectors with
source hashes, transaction hashes, compiler settings and artifact digests.
Include the separate reserve-funding vector.

Retain the reviewed generated bytes and their original build provenance.
Production network inputs and gas calibration remain unresolved.
Resolve the latest L2 block once, then read legacy fee-vault settings at
that block hash using EIP-1898. Require token metadata in the deployment
config so legacy Ether/ETH getters cannot replace the intended Celo/CELO.
Record the source block, frozen settings and bundle digest.

Add preflight verification, local JSON-RPC workflow tests, usage docs and
a Just entry point. These tools perform no on-chain writes.
@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-direct-upgrade-contracts branch from f815d31 to 2386275 Compare November 2, 2026 11:15
@seolaoh
seolaoh marked this pull request as ready for review November 2, 2026 11:50
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T14:08:58.936374Z 37d1073 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-direct-upgrade-contracts branch from aa32fa2 to 43a8c02 Compare November 3, 2026 09:05
Pin a compatible mise version and invalidate the old tool cache.
Verify the selected version and Foundry tools after installation.

Resolve Semgrep baselines from GitHub PR merge refs without REST
API access. Cover retargeting, shallow clones and invalid refs,
and keep full scans for non-PR pushes and separate rule tests.

Use Celo runners for Go and memory acceptance tests. Make unused
Celo genesis input addresses explicit in interopgen and remove
the upstream devnet metrics upload workflow.
@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-direct-upgrade-contracts branch from fa99ecb to 512ba56 Compare November 3, 2026 10:29
Comment on lines +131 to +134
Predeploys.isPredeployNamespace(_config.bridgeProxy) && !Predeploys.notProxied(_config.bridgeProxy)
&& !Predeploys.isSupportedPredeploy(_config.bridgeProxy, type(uint256).max, true, true)
&& _config.l1Bridge != address(0) && _config.l1Token != address(0) && _config.owner != address(0),
"GenerateCgtV2NUTBundle: invalid configuration"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

bridgeProxy is free config, but L1 expects CeloPredeploys.CELO_GAS_BRIDGE_L2 (0x…07ef, moved in 80cfc40): OPCM uses it as otherBridge and MigrateV1V2 requires it. The fixture uses 0x…07fE. Use the constant and drop the field, or require(bridgeProxy == CELO_GAS_BRIDGE_L2).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 3dfab8e and regenerated the fixtures in 8344403. The generator now uses CeloPredeploys.CELO_GAS_BRIDGE_L2 (0x…07ef) for the proxy upgrade, minter authorization and prestate, and bridgeProxy is no longer configurable.

Added regression checks for the upgrade target and rejected config overrides. All 8 migration tests and 20 production-tool tests pass locally. Matching Go/Rust fixture updates are ready locally for the companion PRs.

Use CeloPredeploys.CELO_GAS_BRIDGE_L2 for upgrades, minter authorization and fixture prestate so L1 and L2 agree on the bridge address. Remove the free bridgeProxy config input and reject overrides in the production tool.

Record the actual contract base and check creation bytecode when exporting fixture provenance.
Regenerate upgrade targets, minter calldata, prestate and transaction hashes from the canonical bridge generator. Preserve all six implementation deployment bytecodes and the dynamic reserve-funding deposit.
CGT genesis authorizes the canonical Celo bridge. Exclude every authorized minter from the unauthorized-caller case, matching the burn test precondition.
Use CircleCI archive RPC secrets for Go tests, pin Semgrep in mise and its Docker job, and remove Codecov uploads. Exclude upstream OP-chain upgrade/coverage jobs from the Celo workflow.

Remove the external OP Sepolia hardfork sync tests, following ethereum-optimism/optimism@38f07c5. Celo already dropped these in its later acceptance-test setup.

Preserve failed Forge diagnostics as artifacts and print only the final 200 console lines so VerifyOPCM failures can be investigated without the trace output limit.

@karlb karlb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code looks fine. I didn't check the CI failures in detail.

seolaoh commented Nov 3, 2026 •

Copy link
Copy Markdown
Author

CI triage for current head 37d107373aa, compared with target 8c7d7a12c8b. All workflows have finished: 44 successful and 10 failing CircleCI status checks. The main workflow failed; acceptance-tests completed successfully.

Confirmed target failures

  • VerifyOPCM: both failing tests reproduce on the exact target with Forge 1.2.3 and FOUNDRY_PROFILE=ci, after a full forge build. The ProxyAdmin blueprint mismatch exactly matches the previous CI run: expected 6,754 bytes, actual 6,152. The existing deployment selects an optimizer-5,000 artifact through vm.getCode("ProxyAdmin"), while the verifier reads the optimizer-999,999 artifact by a fixed path. Running only the two tests from a clean build passes on both base and head, so a focused run can miss this existing build/artifact issue.
  • Snapshot, semver, interface and unused-import checks: reproduced against the target. These include stale OPCM ABI/storage snapshots, missing Celo snapshots, interface errors, and the unused imports in test/invariants/CeloGasBridgeL1.t.sol and test/celo/CeloGasBridgeL1.t.sol. For example, the target's OptimismMintableERC20 already has debitGasFees and creditGasFees, but the committed ABI snapshot omits them. These remain separate from the CGTv2 changes.
  • OPCM Go upgrade: confirmed on both this head and exact target using the same local Anvil fork of Sepolia block 12055962 (0xeb5660d984257cc835dbe7c1164ce1bd11d176ff5d910d9fd79c2a56c102ee0d). The live OP Sepolia factory 0x05F9613aDB30026FFd634f38e5C4dFd30a197Fa1 returns zero for gameImpls(1) and empty bytes for gameArgs(1). V6 OPCM assumes every chain has game type 1, so getWETH falls back to calling weth() on that zero address. The call returns no data and the Solidity address decoder reverts with 0x. Both revisions reproduce the identical call/return trace and inner revert. The target's old panic guard then hides it behind revision id 1 cannot be reverted; the PR's fixed guard exposes UpgradeChain: upgrade failed. This is an existing v6/live-Sepolia integration-test mismatch, unrelated to the CGTv2 changes. Only a fixed fork block and temporary logging hooks were added for diagnosis; all source edits were restored.

Updates included in this head

  • 37d140414c backports the default branch's script panic guard from 781654fd807. It handles both string and error panic values and all snapshot revision IDs. Regression tests cover the previously failing Host.Call cases, preservation of the original EVM error, and cleanup after recovery.
  • 6bd25ad1d9 backports the relevant live-Sepolia test fix from a4982ff1d08: query ProxyAdmin for the actual SuperchainConfig implementation instead of comparing live state with a fixed address. The v6 ProtocolVersions expectations are retained.
  • 37d107373a removes only the duplicate mise-installed Semgrep scan from the contracts checker. The repository-wide Docker scan using returntocorp/semgrep:1.137.0, the rule tests and the rule formatting check are unchanged.

Local verification passed: 149 tests/subtests across the script packages and RPC-independent pipeline tests, go vet, and OPCM integration-package compilation. Follow-up diagnosis ran the failing OPCM integration test on both head and target against the fixed Sepolia fork described above, with and without logging hooks. All four runs reproduced the expected failure; no transaction was broadcast to a live chain.

Final hosted CI result

  • The Docker Semgrep scan and rule tests passed. The duplicate mise-installed scan is absent from the contracts checker.
  • The backported live-Sepolia implementation test and all panic-guard/Host.Call regression tests passed in go-tests-short. Its remaining failure is TestEndToEndBootstrapApplyWithUpgrade/opcm_upgrade_test/upgrade_opcm. The local head/target comparison now confirms the existing live-Sepolia game-type mismatch described above.
  • All eight standard/heavy contract test jobs fail only the same two VerifyOPCM tests. Their full diagnostic artifacts confirm the target's ProxyAdmin mismatch described above. The contracts checker fails only the confirmed target snapshot/semver/interface/unused-import checks.
  • Memory tests passed, and the acceptance-tests workflow completed successfully.

CI remains red because of the confirmed target failures described above, including the OPCM Go integration failure. No checks are still running.

sebastianst and others added 3 commits November 3, 2026 22:45
Handle string and error panics for every snapshot revision ID using the
default branch predicate. Adapt the patch to v6's string-only recovery.

Keep the upstream predicate tests and extend Host.Call regression tests
for error values, revision 36 and preservation of the original EVM error.

(cherry picked from commit 781654f)
Query ProxyAdmin for the SuperchainConfig implementation instead of
comparing live state with a fixed implementation address.

Backport the relevant test change while keeping v6's ProtocolVersions
expectations. The upstream OPCMv2 test changes do not apply to v6.

(cherry picked from commit a4982ff)
Remove the duplicate mise-installed Semgrep scan from the contracts checker. Keep the repository-wide Docker scan, rule tests and rule formatting check unchanged.

seolaoh commented Nov 3, 2026

Copy link
Copy Markdown
Author

Final CI summary for head 37d107373aa, compared against exact target 8c7d7a12c8b: 44 CircleCI status checks passed and 10 failed, with none pending.

All remaining failures reproduce on the exact target. No new CI failures attributable to this PR were found.

  • 8 contract test jobs: the same two VerifyOPCM_Run_Test tests fail across the four standard/heavy configurations. Deployment and verification select different existing ProxyAdmin artifacts (optimizer 5,000 vs 999,999), producing the 6,754-byte vs 6,152-byte blueprint mismatch. Example job.
  • Contracts checks: existing ABI/storage snapshot and semver-lock differences, missing or mismatched Celo interfaces, and unused imports in two existing CeloGasBridgeL1 test files. These reproduce on the target. Job.
  • Go OPCM upgrade integration test: v6 OPCM assumes game type 1 exists, but the live OP Sepolia factory returns address(0). The subsequent weth() call returns empty data and ABI decoding reverts. Both head and target reproduce the same inner failure on a local Anvil fork pinned to Sepolia block 12055962. The target's old panic guard hides it behind a rollback panic; this PR's fixed guard exposes UpgradeChain: upgrade failed. Job.

CI remains red because of these confirmed target issues. The reproduction details and passing CI fixes are recorded in the earlier triage comment.

@seolaoh
seolaoh merged commit 3f5917a into celo-contracts/v6.0.0 Nov 3, 2026
46 of 56 checks passed
@seolaoh
seolaoh deleted the seolaoh/cgtv2-direct-upgrade-contracts branch November 3, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants