3MIKAN
仮想通貨DeFi

MetaMaskのSpending capとは?approve・revoke・Permitを安全に確認

MetaMaskのSpending cap、ERC-20 approve、allowance、revoke、Permitを区別し、token・spender・amount・chainを確認する手順を解説します。

owner、token contract、spender、allowanceを分けて確認するtoken approvalの構造

MetaMaskにSpending cap requestと表示されたら、送金額だけを見る画面ではありません。多くの場合は、特定のtokenを、特定のspenderが、いくらまで使えるかをERC-20 token contractへ記録するapproveの確認画面です。

先に記録するのは、account、chain、token contract、spender、amountの5項目です。サイト名やボタン名だけでは、この5項目を確定できません。

dappのDisconnectとrevokeは別

Disconnectはサイトからaccount情報を切り離す操作です。すでにchain上へ記録されたallowanceは消えません。tokenを動かす権限を止めるには、対象のallowanceを別に確認してrevokeします。

この記事ではERC-20のtoken approvalを対象に、署名前、既存権限の確認、revoke後の確認までを順に整理します。contract addressやABIから確認したい場合は、先に直コンの安全確認手順を参照してください。

approval・Spending cap・allowance・revokeの違い

表示・用語 何を指すか 確認する場所
approval / approve spenderへ利用上限を設定するon-chain transaction walletのfunction詳細、token contract、receipt
Spending cap MetaMaskが表示する利用上限。通常はapproveのamountに対応する MetaMaskのEstimated changes、Spender、Method
allowance token contractが保持するowner → spenderの残り上限 allowance(owner, spender)、Approval Checker
revoke 同じtoken・spenderの上限を0などへ更新するon-chain transaction revoke画面、receipt、更新後のallowance

ERC-20では、approve(spender, value)を再度実行すると、そのowner・spenderのallowanceをvalueへ更新します。spenderはtransferFromを使い、allowanceの範囲でownerのtokenを移動できます。

ownerがtoken contractへapproveを送り、spenderがallowanceの範囲でtransferFromし、revokeで同じ組み合わせを0へ更新する図

approvalは「サイト全体への包括的な許可」ではありません。少なくとも次の組み合わせごとに別のstateです。

chain + token contract + owner + spender = allowance

同じdappでもrouterのversionやchainが変わればspenderは別addressになり得ます。反対に、画面上のサイト名が違っても、共通のspender contractを使う場合があります。

署名前に固定する5項目

1. account

approvalを出すowner accountです。複数accountを使っている場合、別accountのallowanceを見ても署名対象の確認にはなりません。

2. chain

Ethereum、Base、Arbitrumなど、現在のnetworkを記録します。同じ形式のaddressでも、chainが違えば別のstateです。revokeに必要なnetwork fee用のnative tokenもchainごとに異なります。

3. token contract

token名やsymbolだけでなくcontract addressを確認します。偽tokenや同名tokenを避けるため、project公式資料とExplorerの両方で照合します。

4. spender

実際にtransferFromを呼べるaddressです。dappのドメイン、transactionのto、spenderは同じとは限りません。通常のERC-20 approveでは、transactionのtoはtoken contract、calldataの引数がspenderです。

5. amount

人が読むtoken数量と、decimals()を反映したraw valueを分けます。Maxやサイト提案値が、今使う予定量と同じとは限りません。

functionと引数をさらに確認する場合は、ABI・calldata・event logsの読み方toと引数を分けてください。

MetaMaskのSpending cap requestを読む

MetaMask公式HelpのSepoliaサンプルでSpending cap、Spender、Request from、Interacting with、Method Approveが表示された確認画面
MetaMask公式HelpのExtensionサンプル。Sepoliaの説明用accountで、Spending cap、Spender、Methodが分かれて表示されています。3MIKANのwalletを接続した画面ではありません。

画面では、少なくとも次を照合します。

  • 上部のaccountとnetwork
  • Spending capの数量
  • Spenderのaddress
  • Request fromのdomain
  • Interacting withのtoken contract
  • MethodApprove
  • Estimated changesやsecurity warning

Request fromは「どのWebサイトが要求を開いたか」の手掛かりです。権限を持つ主体は、chain上のspender addressで確認します。domainが正しく見えても、spenderのcodeやupgrade権限まで安全と証明するものではありません。

unlimited approvalは即時被害ではないが、将来残高も範囲に入る

ExplorerやwalletがUnlimitedと表示するapprovalは、非常に大きな上限を設定している状態です。承認した瞬間にtokenが移動するとは限りませんが、spenderが呼び出せる状態なら、新しい署名なしでallowanceの範囲を利用できます。

リスクを判断するときは、現在残高だけでなく次を確認します。

  • 今後同じaddressへ入るtokenも対象になり得るか
  • spenderがproxyか、implementationを変更できるか
  • dappを今も使うか
  • 必要量に対して上限が過大ではないか
  • allowanceに期限がある仕組みか
  • token・spenderの両方を公式情報で照合できるか

unlimited approvalは正規dappでも使われます。一方で、spenderの脆弱性、鍵の侵害、悪意あるupgradeがあれば影響範囲が大きくなります。「Unlimitedだから詐欺」「有名dappだから無条件に安全」のどちらにも決めつけません。

既存allowanceをPortfolioとExplorerで確認する

MetaMask PortfolioのSpending Caps画面では、token、account、spender、Spending Capを同じ行で確認し、対象ごとにRevokeへ進めます。

MetaMask公式HelpのPortfolio Spending Caps画面でUSDC、account、spender、10 USDCの上限、Revokeボタンが並ぶサンプル
MetaMask公式HelpのPortfolioサンプル。対応networkや画面配置は変更される場合があるため、実際のchain selectorとaccountを確認してください。

ExplorerのApproval Checkerは、walletを接続しなくても公開addressを検索できます。読み取りだけなら署名は不要です。

Etherscan Token Approval Checkerで公式寄付addressのtransaction hash、asset、approved spender、original allowanceが表示された公開画面
2026年8月28日のEtherscan公開画面。Etherscanサイト下部に掲載された寄付addressをread-only検索した例で、3MIKANのwalletは接続していません。金額やapproval件数は撮影時点の表示です。

一覧では、表示名だけでなく次を記録します。

  1. chainとowner address
  2. token contract
  3. approved spender address
  4. current allowanceとoriginal allowanceの区別
  5. 最後に更新したtransaction hashと時刻
  6. spenderのverification、proxy、現在のimplementation

Explorerのname tagは便利ですが、それだけで公式性や安全性は確定しません。project公式資料のaddressと照合します。

revokeは同じtoken・spenderのallowanceを更新する

通常のERC-20では、revoke UIがapprove(spender, 0)を送る形が一般的です。実行前後を次の順で確認します。

  1. 対象accountとchainを固定する
  2. token contractと正確なspenderを記録する
  3. 現在のallowance(owner, spender)を読む
  4. revokeのcallが同じtoken・spenderと0を対象にしているか確認する
  5. network feeとシミュレーション結果を確認する
  6. 署名・送信後にreceiptのstatusを見る
  7. 更新後のallowance(owner, spender)を読み、0になったか確認する

現在値は次のようにread-onlyで確認できます。

import { erc20Abi, formatUnits } from 'viem'

const [allowance, decimals] = await Promise.all([
  publicClient.readContract({
    address: token,
    abi: erc20Abi,
    functionName: 'allowance',
    args: [owner, spender],
  }),
  publicClient.readContract({
    address: token,
    abi: erc20Abi,
    functionName: 'decimals',
  }),
])

console.log({
  chainId: await publicClient.getChainId(),
  token,
  owner,
  spender,
  rawAllowance: allowance.toString(),
  displayAllowance: formatUnits(allowance, decimals),
})

このreadはrevoke transactionを送りません。実際に書き込む場合は、token固有の実装、0へ変更してから別amountへ更新する必要性、proxyの現在ABIも確認します。シミュレーションが成功しても、contractの安全性や本番成功を保証しません。

receiptの確認はreceipt・calldata・logsを追う手順へ進みます。revokeがpending・failed・replacedのどれか分からない場合は、transaction状態の判定フローで元hashとreplacement hashの両方を残してください。

revokeが反映されないときの確認順

症状 最初に確認すること 次に見る証拠
Revokeボタンを押せない wallet接続、account、chain、native token残高 対応network、walletのerror
送信したが一覧に残る receipt.status、block、transaction hash index遅延を避けてallowanceを直接読む
allowanceが0にならない token、owner、spenderの組み合わせ calldata、Approval event、別spender
transactionがpending nonce、gas、同じnonceの別hash pending / replaced / dropped候補を分ける
transactionがfailed revert reason、token固有制約 シミュレーション、current implementation
dappをDisconnectしたのに残る Disconnectとrevokeの取り違え on-chain allowanceを確認する
1件消しても権限が見える routerやversionごとの複数spender すべてのtoken・spender行を確認する

Revokeは将来の利用上限を変える操作です。すでに移動したtokenを取り戻す処理ではありません。被害が疑われる場合は、追加署名を止め、hash、署名要求、token、spender、時刻を保存します。

PermitとPermit2は通常のapproveと分ける

gas feeが表示されない署名でも、token利用権限に関係する場合があります。

方式 署名・transaction 確認する主な値
ERC-20 approve ownerがtoken contractへon-chain transaction chain、token、spender、value
ERC-2612 permit ownerがEIP-712 typed dataへ署名し、別accountでもtoken contractへ提出可能 domain、chainId、verifyingContract、owner、spender、value、nonce、deadline
Permit2 AllowanceTransfer tokenからPermit2へのapprovalに加え、指定spender・amount・expirationの権限 token、Permit2 address、downstream spender、amount、expiration、nonce
Permit2 SignatureTransfer 署名を使う1回のtransfer。Uniswap実装では使用transactionの間だけ有効 token、amount、spender、nonce、deadline。recipientなどを拘束するwitnessの有無

ERC-2612のpermitは、署名が正しく、nonceとdeadlineが条件を満たすとallowanceを更新します。tokenがERC-2612を実装しているか、同名の独自permitではないかも確認が必要です。

Permit2AllowanceTransferSignatureTransferを持ちます。統合前には、token側からPermit2 contractへapprovalする層もあります。そのため、通常のApproval CheckerでspenderがPermit2と表示されても、実際のdapp側spenderや署名の期限まで一行で分かるとは限りません。

署名だけでchain上にtransactionが残らない場合もあります。署名画面では、少なくともdomain、verifying contract、spender、token、amount、nonce、deadlineを読み、理解できないtyped dataは拒否します。

最終チェックリスト

  • signing accountとchainを確認した
  • token名ではなくcontract addressを照合した
  • dappのdomainとspender addressを分けた
  • Spending capの人間向け数量とraw valueを確認した
  • Maxやサイト提案値をそのまま選んでいない
  • unlimited approvalの対象tokenと将来残高を確認した
  • Disconnectとrevokeを混同していない
  • revoke前のallowanceを記録した
  • revoke transactionのtoken、spender、0、feeを確認した
  • receipt成功後にallowanceを読み直した
  • Permitならdomain、nonce、deadlineを確認した
  • Permit2ならtoken→Permit2とPermit2→spenderの層を分けた

最短の確認方法は、画面の「Approve」「Revoke」という動詞を信じ切ることではありません。chain、token、owner、spender、allowanceを同じ組み合わせで署名前後に読み直すことです。

確認した一次情報