Audit ERC-20 token approvals and allowances for any Ethereum wallet.
When you interact with DeFi protocols, NFT marketplaces, or DEXes, they request token approvals — permission to spend your tokens. These approvals persist on-chain and can be exploited if the spender contract is compromised or if you no longer use the protocol.
This tool scans all Approval events for a wallet, reads current on-chain allowances, assesses risk levels, and helps you identify dangerous or stale approvals.
# Clone or copy the project
cd eth-allowance-checker
# Install dependencies
pip install -r requirements.txt- Python 3.8+
click— CLI frameworkrequests— HTTP clientrich— terminal formatting
| Env Var | Default | Description |
|---|---|---|
ETHERSCAN_API_KEY |
(empty) | Etherscan API key. Optional but recommended (free tier: 5 req/sec). |
ETH_RPC_URL |
https://rpc.ankr.com/eth |
Ethereum JSON-RPC endpoint for eth_call. |
Set them:
export ETHERSCAN_API_KEY="YourApiKeyToken"
export ETH_RPC_URL="https://rpc.ankr.com/eth" # or your own nodepython allowance_checker.py <COMMAND> [OPTIONS]Scans Approval events + known spenders, reads current allowances, shows risk levels.
python allowance_checker.py check 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045Sample output:
Scanning approvals for 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 ...
Fetching Approval event logs from Etherscan ...
Found 12 unique approval events in logs.
Checking known spenders via token transfers ...
Found 8 allowances to known spenders.
Total unique (token, spender) pairs: 15
Done. 11 active approvals found.
Token Approvals (for 0xd8da6bf2…)
┌──────────────────┬─────────────────────┬──────────────┬──────────┐
│ Token │ Spender │ Allowance │ Risk │
├──────────────────┼─────────────────────┼──────────────┼──────────┤
│ USDT (0xdac17f9…) │ Uniswap V2 Router │ UNLIMITED │ CRITICAL │
│ WETH (0xc02aaa3…) │ Uniswap V3 Router │ UNLIMITED │ CRITICAL │
│ USDC (0xa0b8699…) │ Aave V3 Pool │ 1,000,000 │ MEDIUM │
│ DAI (0x6b17547…) │ 1inch Router │ 500.0 │ LOW │
└──────────────────┴─────────────────────┴──────────────┴──────────┘
Export to JSON or CSV:
python allowance_checker.py check 0xWallet... --export approvals.json
python allowance_checker.py check 0xWallet... --export approvals.csvSave a snapshot for later comparison:
python allowance_checker.py check 0xWallet... --snapshot snap_jan.jsonFilters for approvals where allowance ≥ 2^256 - 1 (max uint256).
python allowance_checker.py unlimited 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045Sample output:
No unlimited approvals found. ✓
Or if found:
Unlimited Approvals (CRITICAL)
┌──────────┬───────────────────┬─────────────┬──────────┐
│ Token │ Spender │ Allowance │ Risk │
├──────────┼───────────────────┼─────────────┼──────────┤
│ USDT │ Uniswap V2 Router │ UNLIMITED │ CRITICAL │
│ WETH │ Uniswap V3 Router │ UNLIMITED │ CRITICAL │
└──────────┴───────────────────┴─────────────┴──────────┘
2 unlimited approval(s) found!
These protocols can spend any amount of your tokens at any time.
Consider revoking them if no longer needed.
Checks last interaction with each spender via transaction history.
python allowance_checker.py stale 0xWallet... --days 90Sample output:
Stale Approvals (>90 days)
┌──────────┬───────────────┬───────────┬──────┬──────────────────┐
│ Token │ Spender │ Allowance │ Risk │ Last Interaction │
├──────────┼───────────────┼───────────┼──────┼──────────────────┤
│ USDT │ SushiSwap │ UNLIMITED │ HIGH │ 2024-03-15 │
│ LINK │ 1inch Router │ 1,000 │ LOW │ never │
└──────────┴───────────────┴───────────┴──────┴──────────────────┘
Generates the calldata for approve(spender, 0) without sending anything.
python allowance_checker.py revoke 0xdac17f958d2ee523a2206206994597c13d831ec7 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488DOutput:
Revoke Transaction Data
Token contract : 0xdac17f958d2ee523a2206206994597c13d831ec7
Spender : 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D (Uniswap V2 Router)
Function : approve(address,uint256)
Selector : 0x095ea7b3
Calldata : 0x095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000000
To : 0xdac17f958d2ee523a2206206994597c13d831ec7
Value : 0 ETH
Recommended Gas Settings:
Gas limit : 50,000 – 100,000
Gas price : check current network gas (e.g. via eth_gasPrice)
⚠ This tool does NOT send transactions.
Use a wallet or raw tx sender to broadcast.
Raw calldata to copy:
0x095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000000
python allowance_checker.py summary 0xWallet...Sample output:
═══ Approval Summary for 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 ═══
Total active approvals : 11
CRITICAL (unlimited) : 2
HIGH : 1
MEDIUM : 3
LOW : 5
Per-Token Breakdown:
Token Approvals Max Risk
USDT 3 CRITICAL
WETH 2 CRITICAL
USDC 3 MEDIUM
DAI 3 LOW
Per-Spender Breakdown:
Spender Approvals Max Risk
Uniswap V2 Router 3 CRITICAL
Uniswap V3 Router 2 CRITICAL
Aave V3 Pool 2 MEDIUM
1inch Router 2 LOW
Compare approvals between two points in time.
# Take snapshots on different dates
python allowance_checker.py check 0xWallet... --snapshot snap_jan.json
# ... time passes ...
python allowance_checker.py check 0xWallet... --snapshot snap_feb.json
# Compare
python allowance_checker.py compare snap_jan.json snap_feb.jsonOutput:
═══ Approval Comparison ═══
Snapshot A : snap_jan.json (loaded 2025-01-15T10:00:00+00:00)
Snapshot B : snap_feb.json (loaded 2025-02-15T10:00:00+00:00)
Unchanged : 8
New : 2
Removed : 1
New Approvals:
┌──────┬───────────────────┬──────────────┬──────┐
│ Token│ Spender │ Allowance │ Risk │
├──────┼───────────────────┼──────────────┼──────┤
│ ARB │ Uniswap V3 Router │ UNLIMITED │ HIGH │
│ OP │ CowSwap │ 10,000 │ LOW │
└──────┴───────────────────┴──────────────┴──────┘
Removed Approvals:
┌──────┬──────────────┐
│ Token│ Spender │
├──────┼──────────────┤
│ LINK │ 1inch Router │
└──────┴──────────────┘
python allowance_checker.py known-spendersOutput:
Known Spender Addresses
┌────┬───────────────────────┬──────────────────────────────────────────────┐
│ # │ Name │ Address │
├────┼───────────────────────┼──────────────────────────────────────────────┤
│ 1 │ Uniswap V2 Router │ 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D │
│ 2 │ Uniswap V3 Router │ 0xE592427A0AEce92De3Edee1F18E0157C05861564 │
│ 3 │ Uniswap Universal Rt │ 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD │
│ 4 │ SushiSwap Router │ 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F │
│ 5 │ 1inch Router │ 0x1111111254fb6c44bAC0beD2854e76F90643097d │
│ 6 │ OpenSea (Wyvern) │ 0x00000000006c3852cbEf3e08E8dF289169EdE581 │
│ 7 │ Blur │ 0x39da41747a83aeE65833441429935E07D5843161 │
│ 8 │ Seaport 1.5 │ 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC │
│ 9 │ Aave V3 Pool │ 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2 │
│ 10 │ Compound cETH │ 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5 │
│ 11 │ MetaMask Swap Router │ 0x881D40237659C251811CEC9c364ef91dC08D300C │
│ 12 │ 0x Exchange Proxy │ 0xDef1C0ded9bec7F1a1670819833240f027b25EfF │
│ 13 │ Paraswap │ 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57 │
│ 14 │ CowSwap │ 0xC92E8bdf79f0507F65a392b0ab4667716BFE0110 │
└────┴───────────────────────┴──────────────────────────────────────────────┘
14 known spenders listed.
| Level | Condition | Meaning |
|---|---|---|
| CRITICAL | Allowance = 2^256 - 1 (max uint256) | Unlimited approval. Protocol can spend your entire token balance at any time. Highest risk. |
| HIGH | Allowance > 10^24 | Very large allowance. Likely exceeds any realistic token supply. |
| MEDIUM | Allowance > 10^18 | Large allowance. May be intentional for large portfolios. |
| LOW | Allowance ≤ 10^18 | Small allowance. Likely safe, but still worth reviewing. |
The tool recognises these major protocols:
- Uniswap (V2, V3, Universal Router)
- SushiSwap Router
- 1inch Router
- OpenSea (Wyvern)
- Blur
- Seaport 1.5
- Aave V3 Pool
- Compound cETH
- MetaMask Swap Router
- 0x Exchange Proxy
- Paraswap
- CowSwap
Unknown spenders are displayed with a truncated address.
Token metadata (symbol, name, decimals) is cached for 1 hour at ~/.allowance-cache/.
Allowance values are cached for 5 minutes.
Delete the cache dir to force fresh lookups:
rm -rf ~/.allowance-cache/All subcommands that show data support --export <path>:
.jsonextension → JSON export.csvextension → CSV export- Other extensions default to JSON
-
Unlimited approvals are dangerous. If a protocol contract is compromised or has an upgradeable proxy, unlimited approval means the attacker can drain your entire token balance.
-
Revoke unused approvals. If you no longer use a protocol, revoke its approvals. This tool generates the revoke calldata — you still need to broadcast the transaction.
-
Prefer exact-amount approvals. When interacting with protocols, approve only the exact amount needed rather than unlimited.
-
This tool is read-only. It never sends transactions. The
revokecommand only generates calldata. -
Trust assumptions. This tool relies on Etherscan and a public RPC endpoint. For sensitive operations, verify results independently with your own node.
-
Approval ≠ Transfer. An approval means the spender can transfer tokens — it doesn't mean they have. But revoked approvals immediately prevent future transfers.
-
Discovery: Fetches Approval event logs from Etherscan where
topic1= your wallet address. Also checks all tokens you've interacted with against known spender addresses. -
Allowance Reading: For each (token, spender) pair, calls
allowance(owner, spender)on the token contract viaeth_callthrough a public RPC. -
Metadata: Resolves token symbol, name, and decimals by calling the standard ERC-20 view functions on each token contract.
-
Risk Assessment: Compares the raw uint256 allowance against the thresholds listed above.
MIT