You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since ca23334 (#174), slot 0 of the governance Safe at 0x…07a0 holds the SafeL2 singleton (0x29fcB43b…C762). deployments-mainnet.json still pairs Safe with SafeImpl = 0x41675C…461a (the L1 singleton), and DeploymentsResolver.t.sol treats Safe/SafeImpl as a coherent proxy/implementation pair. The file billed as the genesis source of truth therefore records an implementation for governance that the genesis it generates does not use.
Failure modes
None of this is a defect in genesis state itself; the mismatch bites whatever consumes the JSON as truth:
An ops script or signer-side check that does "verify the proxy's implementation before signing" reads SafeImpl, compares it to slot 0 on-chain, and reports a mismatch on a perfectly healthy Safe.
Anything that selects its ABI from the recorded implementation decodes governance events against the L1 Safe ABI, which lacks SafeMultiSigTransaction / SafeModuleTransaction, silently dropping exactly the events the SafeL2 switch was made to emit.
A maintainer reading the file gets the wrong mental model of what governance runs on.
To be precise about what is not wrong: SafeImpl's address is still accurate as the location of the L1 Safe singleton predeploy. The false claim is only the implied pairing with the governance proxy.
Related: the new canonical predeploys are unrecorded
The broader half of this was flagged in the #170 review ("the new suite addresses are absent from deployments-testnet.json and deployments-mainnet.json; follow-up issue rather than a blocker") but the follow-up issue never materialized, so tracking it here. The 10 canonical addresses added across #170/#174 (SafeL2, SafeToL2Setup, MultiSend, MultiSendCallOnly, SignMessageLib, CreateCall, SimulateTxAccessor, SafeSingletonFactory, SafeMigration, SafeToL2Migration) exist only as constants in GenerateGenesisPrecompileConfig.s.sol. None appear in Deployments.sol or any deployments-*.json, so they are unreachable through the Deployments struct and uncovered by the resolver tests.
Suggested fix
Add a SafeL2Impl (or similar) member to Deployments.sol and the per-network JSONs, and make the governance proxy's recorded implementation point at it for networks whose genesis builds on SafeL2. The per-network files can legitimately diverge here: adiri's live governance Safe remains on the L1 singleton until the regenesis/fork lands, then flips (via SafeMigration.migrateL2Singleton() per Genesis follow-ups: correct a migration comment, harden vendored .hex, fix the nonce rationale, record the adiri procedure #176).
Add the remaining canonical predeploys to Deployments.sol / the JSONs so future scripts resolve them through _load(...) instead of hardcoding, and extend DeploymentsResolver.t.sol to pin them.
Extend the generator's setUp drift guards (GenerateGenesisPrecompileConfig.s.sol:128-130) to assert the newly recorded addresses, so a JSON edit fails as a named assertion rather than an unexplained yaml diff.
Surfaced while reviewing #174; not a merge blocker there.
Since ca23334 (#174), slot 0 of the governance Safe at
0x…07a0holds theSafeL2singleton (0x29fcB43b…C762).deployments-mainnet.jsonstill pairsSafewithSafeImpl = 0x41675C…461a(the L1 singleton), andDeploymentsResolver.t.soltreatsSafe/SafeImplas a coherent proxy/implementation pair. The file billed as the genesis source of truth therefore records an implementation for governance that the genesis it generates does not use.Failure modes
None of this is a defect in genesis state itself; the mismatch bites whatever consumes the JSON as truth:
SafeImpl, compares it to slot 0 on-chain, and reports a mismatch on a perfectly healthy Safe.SafeABI, which lacksSafeMultiSigTransaction/SafeModuleTransaction, silently dropping exactly the events the SafeL2 switch was made to emit.To be precise about what is not wrong:
SafeImpl's address is still accurate as the location of the L1Safesingleton predeploy. The false claim is only the implied pairing with the governance proxy.Related: the new canonical predeploys are unrecorded
The broader half of this was flagged in the #170 review ("the new suite addresses are absent from
deployments-testnet.jsonanddeployments-mainnet.json; follow-up issue rather than a blocker") but the follow-up issue never materialized, so tracking it here. The 10 canonical addresses added across #170/#174 (SafeL2,SafeToL2Setup,MultiSend,MultiSendCallOnly,SignMessageLib,CreateCall,SimulateTxAccessor,SafeSingletonFactory,SafeMigration,SafeToL2Migration) exist only as constants inGenerateGenesisPrecompileConfig.s.sol. None appear inDeployments.solor anydeployments-*.json, so they are unreachable through theDeploymentsstruct and uncovered by the resolver tests.Suggested fix
SafeL2Impl(or similar) member toDeployments.soland the per-network JSONs, and make the governance proxy's recorded implementation point at it for networks whose genesis builds on SafeL2. The per-network files can legitimately diverge here: adiri's live governance Safe remains on the L1 singleton until the regenesis/fork lands, then flips (viaSafeMigration.migrateL2Singleton()per Genesis follow-ups: correct a migration comment, harden vendored .hex, fix the nonce rationale, record the adiri procedure #176).Deployments.sol/ the JSONs so future scripts resolve them through_load(...)instead of hardcoding, and extendDeploymentsResolver.t.solto pin them.setUpdrift guards (GenerateGenesisPrecompileConfig.s.sol:128-130) to assert the newly recorded addresses, so a JSON edit fails as a named assertion rather than an unexplained yaml diff.Surfaced while reviewing #174; not a merge blocker there.