chore(deploy): harmonize Periphery ownership to refundWallet#1815
Conversation
Aligns deploy scripts with the agreed Periphery ownership policy:
- All Periphery contracts that hold owner/withdraw authority use
refundWallet, with two exceptions:
- FeeCollector keeps its dedicated feeCollectorOwner (on the way to
deprecation, intentionally left as-is).
- FeeForwarder keeps withdrawWallet (treasury reporting context).
Updated:
- DeployERC20Proxy(.zksync).s.sol: was deployerAddress -> refundWallet.
- DeployGasZipPeriphery(.zksync).s.sol: was per-network safeAddress
-> refundWallet.
- DeployPermit2Proxy(.zksync).s.sol: was per-network safeAddress
-> refundWallet.
Existing on-chain deployments are not touched by this PR; ownership
migration is tracked separately.
Supersedes #1106 (which became unrebaseable after main's deploy-idiom
migration).
WalkthroughDeployment scripts for ERC20Proxy, GasZipPeriphery, and Permit2Proxy across Solidity and ZkSync are refactored to read owner/withdrawal recipient addresses from centralized ChangesGlobal Refund Wallet Configuration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Aligns healthCheck with the policy in this PR. Both the Tron and EVM paths previously compared the on-chain ERC20Proxy owner against deployerWallet — switch them to refundWallet. After this PR, fresh deployments will pass owner verification. Existing on-chain deployments will keep flagging until the separate ownership migration runs (the current mainnet ERC20Proxy is owned by a stale historical deployer EOA 0x11f1..c00c, not deployerWallet, so healthCheck was already failing on it).
…mit2Proxy/GasZipPeriphery Adds the missing `_owner` entries to `deployRequirements.json` so the pre-deploy validator catches a zero `refundWallet` before the periphery contracts get deployed bricked. `TransferrableOwnership` does not check for `address(0)` on the owner, and `ERC20Proxy`/`Permit2Proxy` have no inline check either — without this guard a missing/renamed `.refundWallet` key in `global.json` would silently deploy contracts with `owner = address(0)` and no recovery path. Per Michał's review on #1815.
Same gap as ERC20Proxy/Permit2Proxy/GasZipPeriphery — Executor's constructor relies on TransferrableOwnership, which doesn't reject address(0). The deploy script reads _owner from global.json .refundWallet, so a missing/renamed key would silently deploy with owner = address(0). Per Michał's addendum on #1815.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
script/deploy/healthCheck.ts (1)
721-850: ⚡ Quick winAdd post-deploy ownership checks for GasZipPeriphery and Permit2Proxy.
This PR also moves those two contracts' owner/withdraw authority to
refundWallet, but this ownership block still only validatesERC20Proxy,FeeCollector, andReceiver. A wrong non-zerorefundWalleton either contract would currently pass healthCheck.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@script/deploy/healthCheck.ts` around lines 721 - 850, The health check omits post-deploy ownership validation for GasZipPeriphery and Permit2Proxy, so add the same ownership checks used for ERC20Proxy/FeeCollector/Receiver: call checkOwnershipTron(...) in the Tron branch and checkOwnership(...) in the EVM/publicClient branch for the deployedContracts entries 'GasZipPeriphery' and 'Permit2Proxy', verifying their owner/withdraw authority equals refundWallet (use the same pattern as the existing FeeCollector and Receiver checks and the erc20Proxy owner read logic).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@script/deploy/healthCheck.ts`:
- Around line 791-795: The health check now expects the ERC20Proxy owner to be
refundWallet (uses getAddress(erc20ProxyOwner) !== getAddress(refundWallet)),
which will falsely fail existing mainnet deployments; revert this change by
restoring the original expected owner (the old EOA) or wrap the new expectation
in a gated check that only runs when a migration/redeployment marker is set
(e.g., check a feature flag or isMigrationComplete) before comparing
getAddress(erc20ProxyOwner) to getAddress(refundWallet); update the healthCheck
logic around the getAddress/erc20ProxyOwner/refundWallet comparison accordingly
so existing deployments remain unchanged until rollout is completed.
---
Nitpick comments:
In `@script/deploy/healthCheck.ts`:
- Around line 721-850: The health check omits post-deploy ownership validation
for GasZipPeriphery and Permit2Proxy, so add the same ownership checks used for
ERC20Proxy/FeeCollector/Receiver: call checkOwnershipTron(...) in the Tron
branch and checkOwnership(...) in the EVM/publicClient branch for the
deployedContracts entries 'GasZipPeriphery' and 'Permit2Proxy', verifying their
owner/withdraw authority equals refundWallet (use the same pattern as the
existing FeeCollector and Receiver checks and the erc20Proxy owner read logic).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f0d5fab1-2a35-4ee6-ba66-0ba5c1f149c7
📒 Files selected for processing (8)
script/deploy/facets/DeployERC20Proxy.s.solscript/deploy/facets/DeployGasZipPeriphery.s.solscript/deploy/facets/DeployPermit2Proxy.s.solscript/deploy/healthCheck.tsscript/deploy/resources/deployRequirements.jsonscript/deploy/zksync/DeployERC20Proxy.zksync.s.solscript/deploy/zksync/DeployGasZipPeriphery.zksync.s.solscript/deploy/zksync/DeployPermit2Proxy.zksync.s.sol
Upstream PR lifinance#1815 changed the expected ERC20Proxy owner on every active network from the Safe to refundWallet. On somnia (newly added in this sync) the on-chain owner is still the Safe, so the deploy health check fails on a sync PR that introduces zero protocol code. Short-term unblock per Slack thread with smartcontract_core (Goran ack): flip skipHealthcheck=true on somnia only. The proper ownership transfer to refundWallet is tracked separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Upstream PR lifinance#1815 changed the expected ERC20Proxy owner on every active network from the Safe to refundWallet. On somnia (newly added in this sync) the on-chain owner is still the Safe, so the deploy health check fails on a sync PR that introduces zero protocol code. Short-term unblock per Slack thread with smartcontract_core (Goran ack): flip skipHealthcheck=true on somnia only. The proper ownership transfer to refundWallet is tracked separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Aligns the deploy scripts (and the healthCheck script) of the three Periphery contracts whose owner key was inconsistent with the agreed policy.
Policy
All Periphery contracts that hold owner / withdraw authority use
refundWallet, with two intentional exceptions:feeCollectorOwner(on the way to deprecation, intentionally left as-is).withdrawWallet(treasury reporting context).Changes
deployerAddress(ephemeral — has produced a stale-EOA-owned mainnet deployment)refundWalletsafeAddressrefundWalletsafeAddressrefundWalletAll six deploy script files (3 EVM + 3 zksync mirrors) updated to read
.refundWalletfromconfig/global.json, matching the canonical pattern used byDeployExecutor.s.sol,DeployTokenWrapper.s.sol, the receiver family, etc.script/deploy/healthCheck.tsupdated: the EVM + Tron ERC20Proxy ownership checks now expectrefundWalletinstead ofdeployerWallet. (GasZipPeripheryandPermit2Proxyhave no ownership checks in healthCheck.) Note that the current mainnet ERC20Proxy is owned by a stale historical deployer EOA (0x11f1…c00c, notdeployerWallet), so healthCheck was already failing on it today — this PR aligns the expectation; the migration will close the gap on-chain.Out of scope
Existing on-chain deployments keep their current owners. A migration script (
transferOwnershipper chain) is a separate follow-up — particularly important for mainnetERC20Proxy.Context
Supersedes #1106, which became unrebaseable after main's
config.sh → .envdeploy-idiom migration. Full audit of the periphery surface was done before this PR — only the three contracts above were misaligned.Test plan
forge buildclean.tsc --noEmitclean forhealthCheck.ts.No findings ✔on both commits.refundWallet.ERC20Proxy owner is correct.🤖 Generated with Claude Code