Add governance proposal 24: de-whitelist same-address multisig, nominee cleanup, GuardCM allowlist#308
Conversation
…s multisig, nominee cleanup, GuardCM allowlist) Adds the staging builder + fork tests for a single GovernorOLAS proposal (41 actions): - de-whitelist GnosisSafeSameAddressMultisig on ServiceRegistry (L1) / ServiceRegistryL2 (7 L2s) via changeMultisigPermission(addr,false) — mainnet direct, L2s bridged through their mediators; - remove 32 retired staking nominees from VoteWeighting via removeNominee(bytes32,uint256); - extend the GuardCM allowlist via setTargetSelectorChainIds with 19 emergency-pause/drain triples. Bridge encodings mirror the autonolas-governance proposal-11 builder; the GuardCM batch mirrors its Phase-0 setTargetSelectorChainIds. Arbitrum retryable params are SDK-estimated (proposal_15 method: +1000% buffers, value = deposit*10) and baked concrete. Fork tests (test/Proposal24Fork*.t.sol): full propose->vote->queue->execute on a mainnet fork (asserts the mainnet de-whitelist, all 32 nominee removals, and all 19 GuardCM triples) plus per-L2 bridge-delivery sims for Optimism/Base/Celo/Mode (OP-stack) and Gnosis/Polygon/Arbitrum. Not run in CI (CI only runs Staking/PolySafe forge matches); run locally with forge test --match-contract Proposal24Fork. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
annotate.js decodes the Forge builder's authoritative calldata (calldata.json) into a self-contained, color-coded HTML breakdown of all 41 entries (de-whitelist / removeNominee / GuardCM setTargetSelectorChainIds, including the bridged L2 payloads). proposalId in the HTML matches the builder and the L1 fork test (0xd33102bf...25ba). Mirrors the autonolas-governance proposal-11 annotate.js. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ic address, false positive) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…k test (false positive) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lygon Polygon has a second same-address adapter, PolySafeSameAddressMultisig (0xBcb1BAC84B5BcAb350C89c50ADc9064eD15a4485) — the same adopt-an-existing-Safe primitive as GnosisSafeSameAddressMultisig (identical bytecode/artifact, proxyHash + DEFAULT_DATA_LENGTH=20), currently whitelisted on the Polygon ServiceRegistryL2. It was missing from the de-whitelist, leaving the same-address adoption path open on Polygon. (configuration.json sweep confirms this is the only such gap; all 8 GnosisSafeSameAddressMultisig were already covered.) Both Polygon adapters are now batched as two concatenated tuples in the single FxRoot message (FxGovernorTunnel.processMessageFromRoot loops over them), so the proposal stays at 41 entries. The Polygon L2 fork test asserts both adapters flip to de-whitelisted. Regenerated description.txt / calldata.json / HTML. New proposalId 0x0b61f9b79b549a6601b530c83a032cf8fa848170ca8663772f2e5c029d78e39e. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Overfunding msg.value does not change the retryable ticket's gas bid: the ticket uses the explicit maxFeePerGas argument. The estimator was baking the raw current L2 gas price (~0.02 gwei) instead of the SDK's buffered p.maxFeePerGas (+1000%), so a rise in Arbitrum L2 gas before execution could leave the retryable underbid and not auto-redeemed (still manually redeemable, but not the intended behaviour for a governance action). Now bakes the buffered maxFeePerGas (220_000_000 ~ 0.22 gwei) and refreshes maxSubmissionCost/value from a fresh estimate; value (deposit*10) already covered the buffered deposit. estimate_arb_submission_cost.js now uses p.maxFeePerGas (not getGasPrice). Regenerated calldata.json + HTML. New proposalId 0x73e8480bad6a2e344017aeeb789a356653a82d275cba156c8a889c0d5f1a7f49. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Independent review — Proposal 24 (de-whitelist + nominee cleanup + GuardCM allowlist)Reviewed all three bundled actions against current on-chain state and the proposal payload ( 1. De-whitelist same-address adapters — ✅ completeEnumerated the whitelisted adopt-existing-Safe multisig implementations directly on-chain via
2. Nominee removals (32×) — ✅ sound
3. GuardCM allowlist extension (19 triples) — ✅ sound
Notes (non-blocking)
— audit-claude, 2026-06-22 |
Summary
Adds the staging builder, description, Arbitrum cost estimator, and fork tests for GovernorOLAS proposal 24 — a single proposal bundling 41 actions:
GnosisSafeSameAddressMultisig(8) —changeMultisigPermission(adapter, false)onServiceRegistry(Ethereum) andServiceRegistryL2(Gnosis, Polygon, Arbitrum, Optimism, Base, Celo, Mode). Mainnet is a direct Timelock call; each L2 is bridged through its mediator (AMB / FxRoot / Arbitrum Inbox retryable / OP-stack messenger). Removes the same-address multisig adoption path from service deployment.VoteWeighting.removeNominee(bytes32, uint256)for retired(account, chainId)pairs across Ethereum, Gnosis, Base, Polygon, Optimism, Celo, Arbitrum.setTargetSelectorChainIds(...)adding 19 emergency-pause / drain triples (DispensersetPauseState, ServiceManager / RegistriesManagerpause, per-L2TargetDispenserL2.pause, plus the Modedrainbackfill). All statuses = true.Bridge encodings mirror the autonolas-governance proposal-11 builder; the GuardCM batch mirrors its Phase-0
setTargetSelectorChainIds. Arbitrum retryable params are SDK-estimated (proposal_15 method: +1000% buffers,value = deposit × 10) and baked concrete, so the stagingproposalIdis the one that will be submitted.Fork tests
test/Proposal24ForkL1.t.sol— full propose → vote → queue → execute on a mainnet fork through the live GovernorOLAS; asserts the mainnet de-whitelist, all 32 nominee removals, and all 19 GuardCM triples. Arbitrum retryable is executor-funded (Timelock keeps no balance).test/Proposal24ForkL2OpStack.t.sol— Optimism / Base / Celo / Mode mediator-replay → adapter de-whitelisted.test/Proposal24ForkL2Other.t.sol— Gnosis (AMB) / Polygon (FxRoot) / Arbitrum (aliased Timelock) → adapter de-whitelisted.All 10 pass locally. They self-fork via
vm.createSelectFork(public RPC defaults, overridable via*_RPCenv). They are not run in CI (CI runs only theStaking/PolySafeCreatorforge matches) — run locally withforge test --match-contract Proposal24Fork.Operational notes
Dispenser.removeNomineereverts within the last week of the ongoing epoch — execute this proposal with > 7 days left in the epoch (epoch length 14 days).estimate_arb_submission_cost.jsright before submission to refresh the baked ArbitrumARB_*constants against L1 basefee drift.Notes
scripts/proposals/andtest/.proposalId=0xd33102bf0356f624d51130dc7099a7285d3e125bb03687b488c3df66bfd825ba(recomputed if the Arbitrum params are refreshed at submission).