Skip to content

fix(frontend): useAccountClient race can sign tx with wrong wallet #526

@yu23ki14

Description

@yu23ki14

One-liner

useAccountClient の async effect に cleanup が無く、wallet 切り替え中に古い effect が後勝ちで setClient を上書きすると、ユーザーの意図と異なる wallet で writeContract が署名される。

Description

pkgs/frontend/hooks/useWallet.ts:17-45useAccountClientuseEffect は以下のような構造:

setClient(undefined);
setWallet(undefined);
// ...
const provider = await wallet.getEthereumProvider();
// ...
setClient(walletClient);

cancelled flag / AbortController が無いため、新しい wallets 配列が await の途中に到着すると、古い effect が後勝ちで setClient(walletClient_old) を実行する。

失敗シナリオ

  1. ユーザーが MetaMask の wallet A → wallet B にスイッチ(Privy の wallets 配列が更新)
  2. 古い effect の getEthereumProvider() がまだ resolve していない
  3. 新しい effect が即座に開始 & 完了
  4. その後で古い effect が setClient(walletClient_old) を上書き
  5. 次の writeContract は wallet A で署名される(ユーザーは B で署名するつもり)

特に admin 系の destructive な操作(renounce hat / revoke authority)で誤った account から実行される危険がある。

Requirements

  • useAccountClient 内の useEffect に cancelled フラグ(または AbortController)を導入
  • await 後に if (cancelled) return; を入れる
  • cleanup function で cancelled = true を設定
  • 同様の race が useViem.ts や smart-wallet 系にも無いか確認

Supplements

関連ファイル:

  • pkgs/frontend/hooks/useWallet.ts (L17-45)
  • pkgs/frontend/hooks/useViem.ts

出典: v3 code-review (/code-review ultra-high effort, 2026-05-27)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    HighPriority HighbugSomething isn't working

    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