Conversation
…291) manual_contract-upgrade.yml no longer signs Base-mainnet Diamond facet upgrades directly. The `main` path now deploys facets and proposes the diamondCut to the Safe multisig (no PHALA key exposed), gated by the `production-base` environment; `next` keeps direct upgrade behind a light `staging-base` gate. Adds a main verify workflow and CODEOWNERS coverage for contracts + CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Hardens the manual Diamond upgrade process on Base mainnet by removing the ability for a workflow_dispatch caller to perform a direct diamondCut signed with a privileged mainnet key, instead routing main upgrades through a Safe proposal flow and adding CODEOWNERS coverage for security-critical paths.
Changes:
- Split
manual_contract-upgrade.ymlinto a Safe-proposal-only flow formain(gated byproduction-base) and a direct upgrade flow fornext(gated bystaging-base). - Add a new “phase 2” verification workflow for
mainto confirm Safe execution and on-chain facets/selectors match compiled artifacts. - Add
.github/CODEOWNERSentries to require review for.github/,lit-api-server/blockchain/, andNodeConfig.*.toml.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| .github/workflows/manual_contract-upgrade.yml | Reworks manual upgrades so main produces a Safe proposal (no direct upgrades) while next remains a direct upgrade behind an environment gate. |
| .github/workflows/manual_contract-upgrade-main-2-verify.yml | Adds post-execution verification for main upgrades (Safe execution + facet bytecode/selector validation). |
| .github/CODEOWNERS | Adds required-review coverage for workflow/contract/config surfaces tied to upgrade security. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Clarify main-branch comment: Diamond owner key is never exposed; the proposer EOA can only propose to the Safe, not upgrade the Diamond. - Fail fast if SAFE_PROPOSER_PRIVATE_KEY is unset instead of silently falling back to the deployer's built-in default key. - Extract SAFE_TX_HASH from the task's machine-readable SAFE_TX_HASH= line and fail if it can't be parsed. - Verify NodeConfig exists and contract_address is present before running facet verification. - Make execute-safe-tx revert message generic (drop addComposeHash). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🤖 Code review (Claude)Summary: This PR closes the CPL-291 hole where Findings (most severe first)1. HIGH — This branch regresses the CPL-293 shell-injection fix (#485). Rebase required.
Fix: rebase onto current 2. MEDIUM — Environment gates protect the job, not the secrets; the gate is bypassable until secrets are environment-scoped. 3. MEDIUM — Verify workflow never binds the Safe tx to the expected Safe. 4. LOW — 5. LOW — Nits
VerdictNeeds changes. The Safe-routing design is correct and consistent with the existing prod flow, but finding 1 (regressing the already-landed CPL-293 injection fix) must be resolved via rebase + re-applying validation before merge, and finding 2 means the PR doesn't actually close CPL-291 until the secrets are environment-scoped and Diamond ownership moves to the Safe. |
…Safe verify Findings from the Claude code review on PR #516: - HIGH (#1): re-apply the CPL-293 shell-injection hardening (PR #485) that this branch predates, in BOTH new jobs. Validate the NodeConfig-derived network (allowlist) and contract_address (0x+40 hex) at read time, and pass network/address/RPC/Safe values through env: with quoted shell refs instead of interpolating them into run: scripts. - MEDIUM (#3): bind Safe-tx verification to our Safe. verify workflow now passes --safe vars.SAFE_ADDRESS_CHIPOTLE_MAIN, and execute-safe-tx asserts the tx's Safe matches the expected one (no-op when --safe is omitted, so the prod verify flow is unaffected but can adopt it for free). - LOW (#4): pass dispatcher-controlled safe_tx_hash via env: and validate it as 0x+64 hex before use. - LOW (#5): upgrade-next now refuses to run when its deployer key is unset (empty or the literal "false" the ternary yields), matching propose-main. - Nit: note in CODEOWNERS that the gate covers the default branch only. Findings #2 (environment-scope the secrets + move Diamond ownership to the Safe) are GitHub-settings/operational and can't be fixed in-repo — left for the maintainer; see PR comment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Response to Claude code review — addressed in
|
Closes the CRITICAL CPL-291 path where
manual_contract-upgrade.ymllet any workflow_dispatch caller sign Base-mainnet Diamond facet upgrades directly withPHALA_DSTACKAPP_PRIVATE_KEY. Themainbranch now deploys facets and proposes thediamondCutto the Safe multisig (vars.SAFE_ADDRESS_CHIPOTLE_MAIN, signed withSAFE_PROPOSER_PRIVATE_KEY— the direct mainnet key is no longer exposed to that job), gated by a newproduction-baseenvironment; thenexttesting Diamond keeps its direct upgrade behind a lightstaging-basegate. A newmanual_contract-upgrade-main-2-verify.ymlverifies on-chain facet bytecode/selectors after Safe execution, mirroring the existing prod flow..github/CODEOWNERSadds required-review coverage forlit-api-server/blockchain/,NodeConfig.*.toml, and.github/.Operational prerequisites (controls are inert without these): create the
production-base(required reviewers) andstaging-baseenvironments, setvars.SAFE_ADDRESS_CHIPOTLE_MAIN, transfer themainDiamond's ownership to that Safe if still EOA-owned, and enable "Require review from Code Owners" branch protection. CODEOWNERS uses@GTC6244pending a proper team slug.🤖 Generated with Claude Code