argument-hint:
name: scan-defi
user-invocable: true
description: Scan one Ethereum Mainnet address for withdrawable / claimable DeFi balances across known protocols — like Rabby, DeBank, Etherscan, or Octav. Use when asked to check what an address can withdraw, find or audit its DeFi positions, discover supplied / staked / LP / vault / savings balances or claimable rewards, or "what is this wallet holding in DeFi". Discovers ERC-20 holdings via Blockscout, confirms exact balances on-chain via Multicall3, classifies them against a per-protocol registry (Aave, Compound, Lido, Uniswap, Curve, Convex, Maker/Sky, Rocket Pool, EigenLayer, Ethena, Morpho, Yearn, Sablier), runs bespoke checks for NFT LPs, withdrawal queues, cooldowns and claimable rewards, then prints a report table with amounts, USD, status, and how to withdraw. Ethereum Mainnet only; strictly read-only (never signs or broadcasts).
Scan DeFi
Find every withdrawable or claimable DeFi balance a single address holds on Ethereum Mainnet (chainId 1), and report it — the discovery step that balance trackers like Rabby / DeBank / Octav perform before you sweep funds. Strictly read-only: this skill never signs or broadcasts.
Read references/overview.md first — it defines the detection model,
the raw→underlying valuation rules, the discovery sources, and the exact output format. This file
is just the workflow. Resolve chain metadata and route all RPC / explorer-API access through
$evm-chains; it owns RouteMesh routing and global ROUTEMESH_API_KEY sourcing. If $evm-chains
is unavailable, tell the user to install it with npx skills add evm-chains before proceeding.
Use cli-cast for cast. Paths below are relative to this skill's directory.
Arguments
<evm-address>— the address to scan. Accept a checksummed/lowercase0x…address or an ENS name (resolve withcast resolve-name <name> --rpc-url $RPC). If omitted, fall back toADDRESSin the repo-root dotenvx.env. Normalize to a checksummed address before use.
Workflow
1. Resolve identity and RPC
Determine the holder address (argument → ENS resolve → repo-root dotenvx .env ADDRESS). Resolve Ethereum
mainnet (chainId 1) and route all RPC and explorer-API access through $evm-chains — let that
skill pick the endpoint (Etherscan API V2 / Blockscout / a JSON-RPC endpoint, RouteMesh when its
global key is available); do not hardcode one here. Use whatever RPC it resolves for
cast/Multicall3 reads (cast chain-id --rpc-url "$RPC" must return 1). No private key
required.
2. Discover holdings (breadth)
Per overview Step A — route every read through $evm-chains:
- Native ETH: via
$evm-chains(Etherscan V2account.balance), orcast balance <ADDR> --rpc-url "$RPC"against the RPC it resolved. - Full ERC-20 holdings: via
$evm-chains, which uses the Blockscout token list for full mainnet holdings (Etherscan's full-list endpoint is PRO-only, so Blockscout is the breadth source). - If the holdings source is unavailable, continue with the sweep alone and note the breadth gap.
3. Sweep receipt tokens (authoritative)
Run the batched Multicall3 reader and keep its non-zero JSON hits:
scripts/scan-receipt-tokens.sh --holder <ADDR> --rpc-url "$RPC"
Each hit carries the registry entry plus a raw integer rawBalance. This is the source of truth
for known protocol receipt balances (independent of Blockscout).
4. Value each position
Apply the overview Step C valuation rules to turn rawBalance into a human withdrawable amount
(1:1 for aTokens/Comet; maxWithdraw for ERC-4626 vaults; ×pricePerShare for Yearn v2;
getStETHByWstETH/getEthValue for wstETH/rETH; pool math for Curve LP). For ERC-4626 positions,
batch maxWithdraw(holder) the same way as the sweep. Read the relevant references/<protocol>.md
when you need the exact conversion or contract.
5. Run bespoke checks
For protocols the holder appears to touch (from Steps 2–3, or when in doubt), read that protocol's
references/<protocol>.md "Bespoke checks" section and run the documented cast sequence — these
catch positions the ERC-20 sweep cannot see (overview Step D): Uniswap v3/v4 NFT LPs and v2 LP
classification, Lido & EigenLayer withdrawal queues, Curve/Convex staked LP + claimable rewards,
Compound claimable COMP, Ethena sUSDe cooldowns, Morpho Blue per-market supply, and Sablier streams.
6. Enrich with USD (optional, best-effort)
If useful, price each underlying with the coingecko-cli skill keyed by token address. Never
fabricate a price — omit the USD column if unavailable.
7. Report
Render the report exactly per overview "Output": a one-line summary, then the DeFi positions table
(Protocol | Position | Withdrawable | USD | Status | Contract), a short withdraw how-to (pointing to
sweep-sablier-lockup, sweep-sablier-flow, then consolidate-stables / unwrap / bridge where
relevant), and optionally a plain-wallet-assets table. If nothing is found, say so for
<address> and still optionally show native ETH / wallet tokens.
Guardrails
- Read-only. Never sign, never broadcast, never request
ETH_PRIVATE_KEY. This skill only reads. - Ethereum Mainnet only in this version (chainId 1). Do not infer other chains.
- Confirm on-chain. Treat Blockscout / indexer balances as discovery hints; the Multicall3 reads
(and the documented bespoke
castcalls) are the source of truth for amounts. - Never report debt as withdrawable. Borrow balances are liabilities; exclude them.
- Show locks honestly. Mark positions that are collateral-locked, in cooldown, queued/unbonding, or in an illiquid market with the right Status instead of overstating "withdrawable now".
- Do not fabricate addresses, prices, or amounts. Use only verified registry addresses and the protocol references; omit unknowns and say so.
- Best-effort batching. A reverting subcall (e.g. a non-standard token) is skipped, not fatal; note anything you couldn't read if the user wants debugging detail.
References
- references/overview.md — read first: detection model, valuation rules, discovery, USD, output format, registry-extension guide.
- Per-protocol detail (read when that protocol's tokens/activity show up): aave · compound · lido · uniswap · curve · convex · maker-sky · rocket-pool · eigenlayer · ethena · morpho · yearn · sablier.
references/registry/*.json— machine-readable token classifier consumed by the sweep script (one shard per protocol; entries with"sweep": falseare markers, not holder balances).
Script
scripts/scan-receipt-tokens.sh --holder ADDRESS --rpc-url URL— batches every registry entry'sbalanceCall(holder)through Multicall3aggregate3and prints the non-zero hits as JSON (each entry plusrawBalance). Flags:--include-zeros,--include-non-sweep,--registry-dir DIR,--entries-stdin. Runscripts/scan-receipt-tokens.sh --helpfor details.
Minimum inputs
- One address (argument or repo-root dotenvx
.envADDRESS). - RPC / explorer-API access resolved via
$evm-chains(works keyless via its Blockscout / public-RPC routes; usesETHERSCAN_API_KEYif set and RouteMesh only through$evm-chainsglobal state). cast,jq,curlavailable.