Skip to content

fix(card-spend): disable the retired v2 module when moving a Safe onto v2 - #2589

Merged
MayankMittal1 merged 1 commit into
masterfrom
mayank/fix/retired-cash-module-v2
Sep 25, 2026
Merged

MayankMittal1 merged 1 commit into
masterfrom
mayank/fix/retired-cash-module-v2

Conversation

@MayankMittal1

@MayankMittal1 MayankMittal1 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Wirex card payments are declining with SAFE_NOT_REGISTERED for Safes that moved from v1 to v2.

The Fuse SolidCashModuleV2 was redeployed on 2026-09-24:

Module Lens
Retired 0xE2d4FB3d…7b2B 0x34c3…6E32
Live (backend reads this) 0xa98f2D4b…A999 0xf21d…3c2c

At least one shipped client still had the retired address in EXPO_PUBLIC_CASH_MODULE_V2_ADDRESS. Its v1→v2 batch disabled v1 and enabled the retired core. The backend lens reports those Safes as not registered, so every authorization declines. The retired lens still reports them as set up, so the app shows no error, and the backend's registration-confirm step only logs a warning.

On-chain as of 2026-09-25:

State Safes Effect
Only the retired core enabled 36 every card payment declines
Retired and live cores both enabled 6 payments work; retired core still attached
Already cleaned up 1 none

None of them has debt or escrowed collateral on the retired core.

Fix

  • New setting: ADDRESSES.fuse.retiredCashModulesV2, read from EXPO_PUBLIC_RETIRED_CASH_MODULE_V2_ADDRESSES (comma-separated). It defaults to 0xE2d4… when unset, and never includes the live core.
  • Set-up / enable button (register): whenever the target is v2, the batch now also disables any retired core still on the Safe.
  • Mode switch (switchMode): the same cleanup is added. This is what covers the 6 Safes that have both cores.
  • Batch ordering: the new lib/utils/safeModules.ts works out each disableModule predecessor against the list as earlier calls leave it. v1 and the retired core are often neighbours, and reading both predecessors off one snapshot reverts with GS103.

Stranded Safes need no new UI. With the live address in the build, they read as awaitingV2 (v1 off, live v2 neither enabled nor registered), so the existing "Card spending isn't set up" banner offers setup. It carries over their v1 limits, and the retired core is now removed in the same signature.

Disabling the retired core can't trap funds: withdrawCollateral works after the module is revoked.

Deploy steps (required: this PR alone doesn't fix prod)

  1. In the Vercel and EAS production environments, set:
    • EXPO_PUBLIC_CASH_MODULE_V2_ADDRESS=0xa98f2D4b79A465B265F68F745f5048BC369DA999
    • EXPO_PUBLIC_SPEND_LENS_V2_ADDRESS=0xf21d360Ce044e5f28019B4BE09642f05270B3c2c
  2. EXPO_PUBLIC_RETIRED_CASH_MODULE_V2_ADDRESSES can stay unset (it defaults to 0xE2d4…).
  3. Redeploy web and ship the iOS update.

Testing

  • npx jest lib/utils/__tests__/safeModules.test.ts: 11 passing. Cases covered:
    • the stranded-Safe list;
    • v1 and the retired core as neighbours, in both removal orders;
    • a target deeper in the list;
    • addresses in mixed case;
    • parsing the env list, including the default and dropping the live core.
  • tsc --noEmit and eslint are clean on the changed files.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…o v2

The Fuse v2 module was redeployed on 2026-09-24 (0xE2d4…7b2B → 0xa98f…A999),
but a shipped build kept the old address and moved Safes onto the retired core.
The backend reads only the new module, so those cards decline every payment
with SAFE_NOT_REGISTERED, while the old lens still tells the app they are set up.

Once a build has the new address, those Safes show the enable-spending banner.
The set-up and mode-switch batches now also disable any retired v2 core still
on the Safe. Disables are computed against the module list as each earlier call
leaves it, so v1 and the retired core can come off in one batch without GS103.

Retired cores are listed in EXPO_PUBLIC_RETIRED_CASH_MODULE_V2_ADDRESSES,
which defaults to 0xE2d4… and never includes the live core.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
solid-app Ignored Ignored Sep 25, 2026 4:47pm UTC
solid-app-staging Ignored Ignored Sep 25, 2026 4:47pm UTC

Request Review

@claude

claude Bot commented Sep 25, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@MayankMittal1
MayankMittal1 merged commit 5fd6011 into master Sep 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant