feat(zeronet): add Cobalt upgrade task - #790
Conversation
Bundles the three Cobalt L1 changes into a single ProxyAdmin-owner transaction for Zeronet: - Dynamic upgrades: deploys a ProtocolVersions registry (proxy plus implementation) and redeploys AggregateVerifier, which binds the registry as a constructor immutable and so cannot be upgraded in place. - EthLockbox removal: upgrades OptimismPortal2 and SystemConfig. - CREATE2 for dispute games: upgrades DisputeGameFactory and registers the new AggregateVerifier for game type 621. Deployment is split across two Foundry profiles because base/contracts pins per-contract optimizer runs (5000 for the portal, system config, factory and proxy; 999999 for the registry and verifier). Zeronet's SystemConfig carries a local MAX_GAS_LIMIT raise, so the task re-applies it as a patch and asserts the resulting build suffix rather than letting a stock build silently revert the limit. Co-authored-by: Cursor <cursoragent@cursor.com>
✅ Heimdall Review Status
|
Co-authored-by: Cursor <cursoragent@cursor.com>
Moves BASE_CONTRACTS_COMMIT from 30e4390 to 0ae2de1, which reverts the AggregateVerifier cadence split (#436) and removes the BaseTime predeploy (#437). ProtocolVersions, OptimismPortal2, SystemConfig and DisputeGameFactory are untouched between the two pins. The revert collapses the slow/fast interval pairs back to a single blockInterval/intermediateBlockInterval pair, so the constructor takes two plain arguments instead of an IntervalConfig struct and the previously assumed fast-cadence values are gone -- both intervals now come straight from the live implementation. The revert also rolls AggregateVerifier back to 0.1.0, the same version the live implementation reports, so version no longer distinguishes them. The upgrade script now asserts the redeploy produced a different address and relies on the PROTOCOL_VERSIONS binding, which the predecessor does not have, as the real discriminator. Co-authored-by: Cursor <cursoragent@cursor.com>
- Point the pin comment at the v8.3.0 release branch. - Drop RECORD_STATE_DIFF; the pinned signer tool injects it when it spawns forge (src/lib/state-diff.ts). - Schedule Cobalt for 2026-09-16 18:00:00 UTC instead of leaving it unscheduled. - Set the minimum protocol version to v1.4.0, documenting the packing and the cast command to re-derive it. - Blank the TEE and ZK program hashes with a TODO pointing at base/base releases/v1.4.0; the deploy script refuses to run until they are set. Every other AggregateVerifier constructor argument, including the config hash and block intervals, is now read back from the live implementation, and the portal's proof maturity delay is read from the live portal. - Record the ABI-encoded constructor args in addresses.json so the verify targets no longer rebuild them from config. - Remove the DEPLOYER variable and both Makefile validation targets; the scripts already assert these conditions. - Fold the shared remappings into profile.default so the Cobalt profiles only carry the optimizer settings that actually differ. - Trim the facilitator risk list to the items that apply to us. Co-authored-by: Cursor <cursoragent@cursor.com>
… profiles Move the Cobalt activation to 2026-09-16 16:00:00 UTC and lower the minimum protocol version to v1.3.2. Replace the two Cobalt foundry profiles with FOUNDRY_* overrides on the deploy targets, matching what the verify targets already do. Verified the overrides reproduce the profile builds byte for byte for OptimismPortal2 at 5000 runs and for ProtocolVersions and AggregateVerifier at 999999. Co-authored-by: Cursor <cursoragent@cursor.com>
Set the three AggregateVerifier proof hashes and move to the semver bump commit on releases/v8.3.0. The repin changes OptimismPortal2 5.2.0 -> 6.0.0, DisputeGameFactory 1.4.0 -> 1.5.0 and AggregateVerifier 0.1.0 -> 0.2.0, so update the version assertions in all three scripts. Because version() now distinguishes old from new, add postchecks that read it back through the portal and factory proxies and off the registered verifier, and drop the FACILITATOR note that said version strings were useless here. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Heads up on a gap this task surfaced, raised upstream:
#439, the commit this task now pins to, bumped Minor rather than major since no function, error or event declarations moved, matching the This PR is unaffected as it stands — it stays pinned to |
base/contracts#441 landed the SystemConfig bump on releases/v8.3.0, so SystemConfig now goes 3.13.2 -> 3.14.0 and the patched build is 3.14.0+max-gas-limit-2000M. Regenerate max-gas-limit.patch against the new baseline rather than editing the hunks by hand, and update the patched-version assertions in DeployCobaltCoreImpls and in the ExecuteCobaltUpgrade pre- and postchecks. SystemConfig is no longer the contract where only the implementation address distinguishes old from new, so drop that caveat from FACILITATOR.md; all four upgraded contracts now bump their version. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Repinned to
Re-validated on a hoodi fork at the new pin. Both deploys produce |
forge verify-contract runs with lib/contracts as the project root, which is the only root the target paths resolve from. base/contracts imports its own dependencies through literal lib/<dep>/... paths that resolve against that root as well, but the build keeps them a level up in active/evm/lib, so the submitted standard JSON omitted them and Etherscan failed to compile. Link the four dependencies in for the duration of each verify target and remove them afterwards. Leaving them in place is not an option: the build then matches those imports in two locations and fails as ambiguous.
The schedule assumed a re-genesised Zeronet had every fork through Beryl active at the genesis timestamp. Azul and Beryl actually activated after it, at genesis +300s and +600s, per the ZERONET chain config in base/base, which is what the nodes fork on. Ids 10 and 11 were therefore importing activations five and ten minutes earlier than they happened. Every other id matches the node config. The schedule is an initialize argument passed in the upgrade transaction, and neither the deployed AggregateVerifier nor the registry bakes it in, so nothing needs redeploying.
Co-authored-by: Cursor <cursoragent@cursor.com>
The three hashes were listed with no provenance, so a reviewer had no way to check them short of asking. Record the node release they are built from, base/base releases/v1.4.0, and how each is produced: the TEE value is PCR0 of the reproducible Nitro enclave image from crates/proof/tee, and the two ZK values are the SP1 range and aggregation verification keys from just succinct vkeys --build. All three match the AggregateVerifier already deployed at 0x2504B1c3.
Approved review 5213222189 from roger-bai-coinbase is now dismissed due to new commit. Re-request for approval.
What changed? Why?
Adds the Zeronet configuration for the Cobalt upgrade task, scheduled for September 16, 2026 at 16:00 UTC. It deploys the required implementations and prepares one ProxyAdmin-owner Safe transaction that:
ProtocolVersionsfor dynamic upgrades;OptimismPortal2andSystemConfigfor EthLockbox removal;DisputeGameFactoryto deploy new dispute games withCREATE2; andAggregateVerifierfor game type 621, bound to the new registry.The task includes deployment artifacts, Base and Security Council signer validation files, source-verification targets, and explicit
TASK_NETWORK=zeronetMake targets. It pins the requiredbase/contractsrevision and compiler profiles so the deployed bytecode matches the contract compilation restrictions.Notes to reviewers
SystemConfigpatch preserves its 2,000,000,000 gas limit through the upgrade.ProtocolVersions.initializerequires at least one hour of notice before the configured activation, so execute before September 16, 2026 at 15:00 UTC, or reschedule Cobalt.How has it been tested?
AggregateVerifierregistry binding.