Skip to content

Auto-sync paymaster whitelist for orgs in mirror-mode (autoUpgrade=true) #154

@hudsonhrh

Description

@hudsonhrh

Problem

The default paymaster whitelist is built once, at deploy time, in OrgDeployer._buildDefaultPaymasterRules_appendTaskManagerRules etc. After that, an org's PaymasterHub rules are frozen — they only change when somebody manually calls setRules on that org's hub.

That made sense when the rule set was static. But every time we ship a new user-facing function on a core contract (e.g. createTasksBatch — see #153), every already-deployed org silently breaks for that flow until an admin runs a one-off fix script. We've already got script/fixes/FixTest6OrgMetaRules.s.sol, FixTest6EducationRules.s.sol, FixKubiEducationRules.s.sol — that's the smell. The pattern doesn't scale, and orgs that opted into mirror-mode beacons specifically said "please apply protocol changes to me automatically" — but right now they only get the implementation upgrade, not the paymaster rule change that goes with it.

Ask

When a ContractInfo.autoUpgrade == true (i.e. the org's beacon is in Mirror mode for that module), the org should automatically pick up additions to the protocol's default paymaster rule set for that module — the same way it already picks up implementation upgrades.

Static-mode orgs (autoUpgrade == false) deliberately pinned an old impl and should not receive new whitelist entries; their rule set stays frozen.

Sketch

Three pieces, smallest blast radius first:

  1. Extract the canonical rule set into a callable view. Move the body of _buildDefaultPaymasterRules (and its _appendXxxRules helpers) into a stateless library — DefaultPaymasterRulesLib — so the same logic is reachable both from OrgDeployer (deploy-time) and from a sweeper / PaymasterHub.syncRules() (post-deploy). Today it's internal pure on OrgDeployer, unreachable after bootstrap.

  2. Add a permissionless PaymasterHub.syncRules(orgId) that diffs against the canonical set. For each (target, selector) pair returned by the lib that isn't already allowed for this org, AND whose target is registered in OrgRegistry with autoUpgrade == true, append it (allowed = true, default gas hint). Existing rules and any rules the org executor manually disabled are left alone (don't clobber executor decisions — only add). Emit a RulesSynced(orgId, addedCount) event so dashboards / Slack can flag spend changes.

  3. A sweeper script for the rollout backfill. script/upgrades/SweepPaymasterRulesForAutoUpgradeOrgs.s.sol iterates OrgRegistry, calls syncRules(orgId) on each org's hub. Run once after each protocol release that ships new whitelisted selectors. Replaces the per-org Fix*Rules.s.sol pattern.

Open questions

  • Should rule additions to mirror-mode orgs be silent, or require an opt-in confirmation per change? Protocol-pushed paymaster rules expand what the org pays for, which is a quietly load-bearing economic decision. Mirror mode arguably already covers this (org said yes to auto-following) but we may want a per-org autoSyncPaymasterRules flag separate from the beacon mode for finer control.
  • Rule removals / disabling. If a future protocol release wants to remove a default selector (e.g. deprecating an entry point), do mirror orgs follow that too? Probably yes for consistency, but the framing is different ("the protocol revoked sponsorship" vs "the org executor revoked sponsorship") — worth a paragraph in PAYMASTER_HUB.md.
  • Gas budgets per selector. _buildDefaultPaymasterRules currently passes gasHints[i] = 0 (use default). If the protocol later wants to set custom hints, the lib needs to grow a (uint32 gasHint) per rule and the sync diff has to consider hint mismatches as updates, not just additions.

Related

  • Add createTasksBatch to default paymaster auto-whitelist #153 — Add createTasksBatch to default paymaster auto-whitelist (the trigger for this gap)
  • script/fixes/Fix*Rules.s.sol — current manual workaround
  • SWITCHABLE_BEACON.md — defines the mirror-mode opt-in semantics this issue extends to paymaster config

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions