Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Token Approval Checker

Security tool that scans a wallet for active ERC-20 token approvals across 12 EVM chains. Surfaces unlimited-allowance grants that could drain you in a single transaction if the spender is ever compromised.

npx token-approval-checker 0xYourAddress

Or clone:

git clone https://github.com/swiftnodes/token-approval-checker
cd token-approval-checker
cp .env.example .env             # add your SwiftNodes API key
npm install
node src/cli.js 0xYourAddress

Sample output:

=== Ethereum === 4 active approval(s)
  ⚠️ USDC          -> 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45  UNLIMITED
     token: https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
     last:  https://etherscan.io/tx/0xdeadbeef...
  ⚠️ USDT          -> 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45  UNLIMITED
     ...
    LINK          -> 0x111111125421cA6dc452d289314280a0f8842A65  1,000 LINK
     ...

=== Base === 1 active approval(s)
  ⚠️ USDC          -> 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43  UNLIMITED
     ...

Summary: 5 active approval(s), 3 effectively unlimited.

⚠️  Unlimited approvals can drain your wallet in a single tx if the spender is compromised.
   Revoke via https://revoke.cash or directly call `approve(spender, 0)` on each token.

Why this matters

When you click "Approve USDC" in a dApp, you're often granting an unlimited allowance. That dApp's contract can then move any amount of your USDC at any time — forever, unless you revoke.

Real risk:

  • If a protocol gets hacked → drained immediately
  • If a protocol is upgraded to a malicious version → drained
  • If you stop using a dApp → the approval stays active indefinitely
  • Phishing dApps trick you into approving them → drained on next interaction

Most users have dozens of stale unlimited approvals across multiple chains. This tool finds them all in one shot.

Features

  • ✅ 12 chains scanned in parallel — Ethereum, Base, Arbitrum, Optimism, Polygon, BSC, Avalanche, Scroll, Linea, zkSync Era, Blast, Mantle
  • ✅ Verifies current allowance on-chain — not just historical events. Approvals that have been consumed are filtered out.
  • ✅ Flags "effectively unlimited" (allowance > 10⁶⁰) — the dangerous category
  • ✅ Sorted by risk — unlimited first, then by amount
  • ✅ Direct explorer links for token and last approval tx
  • ✅ --json for piping into a database or alert script
  • ✅ --unlimited-only filter for quick risk-focused audit
  • ✅ Custom lookback window via --blocks N
  • ✅ Single-chain scans via --chain eth

How it works

  1. Query Approval(owner=YOU, spender, value) event logs across a lookback window per chain.
  2. Group by (token, spender) — only the latest event matters (later approvals override earlier).
  3. Drop revoked approvals (value = 0).
  4. Verify current on-chain allowance for each remaining (token, spender) pair via eth_call. This filters out approvals that have been consumed by transferFrom since the event.
  5. Flag anything with allowance > 10⁶⁰ as "effectively unlimited."

The verify-on-chain step is critical: many tools just look at event history and report stale approvals as active. This one actually checks.

Setup

1. Get a SwiftNodes API key

swiftnodes.io — free, no KYC.

2. Configure

cp .env.example .env
# edit: SWIFTNODES_API_KEY=sn_...

3. Scan

npm install
node src/cli.js 0xYourAddress

# Common variations:
node src/cli.js 0xYourAddress --unlimited-only        # only risky ones
node src/cli.js 0xYourAddress --chain base            # one chain
node src/cli.js 0xYourAddress --json > scan.json      # pipeable
node src/cli.js 0xYourAddress --blocks 100000         # quicker but less history

What to do with the output

For each unlimited approval to a contract you no longer use or trust:

Option 1: Use a UI (easiest)

  • revoke.cash — handles all major EVM chains
  • unrekt.net — alternative
  • Each chain's official block explorer often has a "token approvals" page

Option 2: Revoke manually

Call approve(spender, 0) on the token contract via Etherscan's "Write Contract" UI, or sign the tx with viem/ethers:

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

const account = privateKeyToAccount("0x...");
const wallet = createWalletClient({ account, chain: mainnet, transport: http("https://...") });

await wallet.writeContract({
  address: "0x...token...",  // the token contract
  abi: [{
    name: "approve",
    type: "function",
    stateMutability: "nonpayable",
    inputs: [
      { name: "spender", type: "address" },
      { name: "amount", type: "uint256" },
    ],
    outputs: [{ name: "", type: "bool" }],
  }],
  functionName: "approve",
  args: ["0x...spender...", 0n],
});

Each revoke costs gas (~$0.50-$5 on Ethereum, pennies on L2s). Not free but cheap insurance.

Performance

A full 12-chain scan takes 30-90 seconds depending on lookback window and number of historical approvals. Each chain is scanned in parallel; per-chain time is dominated by getLogs and the post-scan allowance verification calls.

If a chain has too much history to scan in one shot, reduce --blocks or override defaultLookback per chain in src/chains.js.

Limitations

  • Only ERC-20 approvals — not ERC-721/1155 setApprovalForAll. NFT approvals are equally dangerous; revoke.cash handles those.
  • Approval2-style routers (Uniswap Permit2, etc.) use a different mechanism — they don't always emit standard Approval events for the underlying token. Check Permit2 separately.
  • Default lookback is conservative — you may miss approvals older than ~1-2 years on chains with high block production. Increase --blocks or run a full scan if you've been active for longer.
  • No private keys — this is a read-only scan. To actually revoke, use a wallet UI or sign txs yourself.

Use cases

  • Wallet hygiene — periodic audit of your own wallets
  • Security incident response — if a protocol gets hacked, find users who had approvals to it
  • DeFi onboarding — scan a freshly-airdrop-farmed wallet before pulling funds
  • For wallet builders — integrate this scan as a wallet security feature

Why SwiftNodes for this

This tool fires getLogs and allowance calls across 12 chains. Most providers either:

  • Limit getLogs block-range aggressively (you'd need many sequential calls)
  • Don't support some chains here (Blast, Mantle, zkSync)
  • Charge per-request

SwiftNodes covers all 12 chains under one flat-rate API key with generous getLogs windows.

License

MIT

About

Security tool that scans a wallet for active ERC-20 token approvals across 12 EVM chains. Surfaces unlimited-allowance grants.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages