Skip to main content

Scan ERC20 approvals, assess risk, and build revoke transactions — zero dependencies

Project description

🔍 ERC20 Checker

Scan ERC20 approvals · Assess risk · Build revoke transactions

Zero dependencies · Pure Python · Multi-chain

PyPI License: MIT Tests


⚡ Quick Start

CLI (recommended)

pip install erc20-checker

# Scan all approvals
erc20-check scan ethereum 0xYourWalletAddress

# Check a specific allowance
erc20-check allowance ethereum 0xYourWallet 0xUSDC 0xSpender

# Build revoke transactions for high-risk approvals
erc20-check revoke ethereum 0xYourWalletAddress

Python API

from erc20_checker.scanner import scan_approvals
from erc20_checker.risk import risk_report, summary

# Scan all approvals for a wallet on Ethereum
result = scan_approvals("ethereum", "0xYourWalletAddress")

# Add risk assessment
report = risk_report(result["approvals"])
print(summary(report))
# {'total': 3, 'highRisk': 1, 'mediumRisk': 0, 'lowRisk': 2}

That's it. Three lines of code to audit every ERC20 approval on your wallet.

🛡️ Risk Levels

Level Criteria Meaning
🔴 HIGH Unlimited approval (≥ 2¹²⁸) Spender can drain all your tokens. Revoke immediately.
🟡 MEDIUM Unknown spender contract Spender is not a recognized protocol. Exercise caution.
🟢 LOW Finite approval, known spender Normal DeFi interaction. Low risk.

📦 Install

pip install erc20-checker

Or from source:

git clone https://github.com/counterfactual5/erc20-checker.git
cd erc20-checker
pip install -e .

🔧 Usage

Scan All Approvals

from erc20_checker.scanner import scan_approvals

result = scan_approvals(
    chain="base",
    wallet="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    start_block=0,
    max_logs=5000,
)

for approval in result["approvals"]:
    print(f"{approval['tokenSymbol']}: {approval['humanAllowance']}{approval['spender']}")

Check Single Allowance

from erc20_checker.allowance import query_allowance

result = query_allowance(
    chain="ethereum",
    wallet="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    token="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",  # USDC
    spender="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",  # Uniswap Router
)
print(result["humanAllowance"])  # e.g. "115792089237316195423570985008687907853269984665640564039457584007913129639935"

Risk Assessment

from erc20_checker.risk import risk_report, summary

report = risk_report(result["approvals"])
for entry in report:
    print(f"{entry['tokenSymbol']}: {entry['riskLabel']} (infinite: {entry['isInfinite']})")

# Aggregate
print(summary(report))

Build Revoke Transactions

from erc20_checker.revoke import build_revoke_tx, build_revoke_batch

# Single revoke
tx = build_revoke_tx(
    token_address="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    spender="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
)
# tx = {"to": "0xa0b8...", "data": "0x095ea7b3...00000000", "value": "0"}

# Batch revoke for all high-risk approvals
high_risk = [e for e in report if e["riskLevel"] == 3]
batch = build_revoke_batch(high_risk)

📋 Example Output

{
  "chain": {"key": "ethereum", "chainId": 1},
  "wallet": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  "approvalCount": 3,
  "approvals": [
    {
      "tokenAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "tokenSymbol": "USDC",
      "spender": "0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",
      "rawAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
      "humanAllowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
      "decimals": 6,
      "lastApprovalBlock": 19283000,
      "riskLevel": 3,
      "riskLabel": "🔴 HIGH",
      "isInfinite": true
    }
  ]
}

🔗 Supported Chains

Chain Chain ID Etherscan
Ethereum 1 etherscan.io
Base 8453 basescan.org
Arbitrum 42161 arbiscan.io
Optimism 10 optimistic.etherscan.io
Polygon 137 polygonscan.com

📊 Comparison

Feature erc20-checker revoke.cash Manual (Etherscan)
Programmatic API ❌ (web only)
Multi-chain ✅ 5 chains Per-chain manual
Risk scoring ✅ Built-in ⚠️ Basic
Batch revoke data
Zero dependencies N/A N/A
Self-hosted / offline

⚙️ Configuration

Set environment variables:

# Required for scanning (Etherscan API)
export ETHERSCAN_API_KEY="your-api-key"

# RPC URL (auto-detected by chain name)
export ETHEREUM_RPC_URL="https://eth.llamarpc.com"
export BASE_RPC_URL="https://mainnet.base.org"
export ARBITRUM_RPC_URL="https://arb1.arbitrum.io/rpc"
# ... or use a generic fallback
export RPC_URL="https://eth.llamarpc.com"

⚠️ Security

  • Read-only: This library only reads on-chain data and builds unsigned transaction payloads. It never signs or broadcasts transactions.
  • No private keys: No wallet private keys or seed phrases are ever needed.
  • No external dependencies: Only Python standard library — minimal attack surface.
  • Verify before revoking: Always verify the to address and data in the revoke transaction before signing. The calldata should be approve(spender, 0).

🛠️ Development

git clone https://github.com/counterfactual5/erc20-checker.git
cd erc20-checker

# Install with dev deps
uv pip install -e ".[dev]"

# Run tests
uv run pytest tests/ -v

🗺️ Roadmap

  • Risk scoring (infinite + unknown spender detection)
  • Revoke transaction builder
  • Multi-chain support (5 chains via Etherscan v2)
  • CLI tool (erc20-check command)
  • Interactive HTML dashboard
  • Multi-wallet batch scanning
  • Gas estimation for revoke transactions
  • Discord / Telegram bot integration

📄 License

MIT © 2026 counterfactual5

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

erc20_checker-0.1.0-py3-none-any.whl (18.4 kB view details)

Uploaded Python 3

File details

Details for the file erc20_checker-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: erc20_checker-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for erc20_checker-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4c346c33285089bfc899fdfb81a94de17d8038f7c60a56249165413120345c92
MD5 eea28946a897e2d225faa88a6bd1b2d9
BLAKE2b-256 6d2467caf576264108a5dccbf0d739af4d302193ba9bb76bce08c34b5046da11

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page