"Who sent it? Where did it come from? Why is there a Tornado Cash withdrawal 27 minutes before a $12K exploit? Wachi knows."
Wachi is a blockchain transaction OSINT tool that runs as an MCP server. Point it at a suspicious transaction, and it will rip it apart — tracing fund flows, identifying every contract, profiling every address, and following the money all the way back to its origin chain.
Built in Rust with alloy-rs (the library that powers Foundry). No Etherscan API keys. No subgraph dependencies. Just raw RPC calls and pattern matching.
Because reading Etherscan tabs manually is a war crime. Because copy-pasting addresses between explorer windows is not "investigation". Because the attacker used Tornado Cash and a cross-chain bridge and you shouldn't have to be a detective to figure that out.
Wachi turns a transaction hash into a full forensic report in under 30 seconds.
cargo build --releaseThat's it. The binary is at ./target/release/wachi.
Create ~/.wachi/config.toml with your Alchemy key (recommended for trace support and funding analysis):
[rpc_overrides]
arb = "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY"
eth = "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"
base = "https://base-mainnet.g.alchemy.com/v2/YOUR_KEY"
opt = "https://opt-mainnet.g.alchemy.com/v2/YOUR_KEY"Without Alchemy, basic analysis still works (public RPCs). You just won't get internal ETH traces or funding origin tracing.
Wachi exposes 6 MCP tools:
| Tool | What it does |
|---|---|
wachi_analyze_tx |
Transaction basics — from, to, value, gas, status, timestamp |
wachi_fund_flow |
All ERC20 transfers + optional internal ETH traces |
wachi_contracts |
Contract vs EOA identification, EIP-1967 proxy detection |
wachi_address_analysis |
Balances, nonces, roles for every address in the tx |
wachi_trace_funding |
Recursive funding origin tracing with cross-chain support |
wachi_list_tasks |
List all investigation folders |
| Prefix | Chain |
|---|---|
arb |
Arbitrum One |
eth |
Ethereum |
base |
Base |
opt |
Optimism |
Transaction format: chain:0xhash (e.g. arb:0x2c83533c...)
Each investigation gets its own folder under ~/.wachi/tasks/. Tools read and write JSON files there, building up intelligence incrementally. Run them in any order — each one enriches the next.
~/.wachi/tasks/arb_2c83533c.../
├── tx_info.json ← wachi_analyze_tx
├── fund_flow.json ← wachi_fund_flow
├── contracts.json ← wachi_contracts
├── addresses.json ← wachi_address_analysis
├── funding_tree.json ← wachi_trace_funding
└── REPORT.md ← final synthesized analysis
Here's what Wachi produces when pointed at an actual DeFi exploit — a Factor Protocol vault drain on Arbitrum (tx):
{
"chain": "Arbitrum One",
"tx_hash": "0x2c83533c9b76010704b6a93032df03c2e6310349e08ebd53c42d02a1ba474b57",
"block_number": 420639416,
"timestamp": "2026-01-12 16:47:12 UTC",
"from": "0x4e42188ef2221f55ef9f25d55d5a4502dd468de6",
"to": "0x5362133b027a4dc7be6530c36d6658f18b24c537",
"value_eth": "0.000000000000000000",
"gas_used": 3720245,
"method_id": "0x215c0c02",
"status": "success",
"log_count": 117
}{
"summary": {
"total_erc20_transfers": 46,
"unique_tokens": 13,
"unique_addresses": 15,
"has_internal_transfers": true
},
"internal_transfers": [
{
"from": "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
"to": "0x5362133b027a4dc7be6530c36d6658f18b24c537",
"value_eth": "3.920211004002749376",
"call_type": "CALL"
},
{
"from": "0x5362133b027a4dc7be6530c36d6658f18b24c537",
"to": "0x4e42188ef2221f55ef9f25d55d5a4502dd468de6",
"value_eth": "3.920211004002749376",
"call_type": "CALL"
}
]
}{
"summary": {
"total_addresses": 22,
"contracts": 20,
"eoas": 2,
"proxies": 0
}
}{
"target_address": "0x4e42188ef2221f55ef9f25d55d5a4502dd468de6",
"starting_chain": "Ethereum",
"tree": {
"address": "0x4e42188ef2221f55ef9f25d55d5a4502dd468de6",
"chain": "Ethereum",
"is_contract": false,
"incoming_transfers": [
{
"from": "0x12d66f87a04a9e220743712ce6d9bb1b5616b8fc",
"value": 0.09787125813515,
"asset": "ETH",
"category": "internal",
"timestamp": "2026-01-12T16:20:47.000Z"
}
],
"outgoing_transfers": [
{
"to": "0x1231deb6f5749ef6ce6943a275a1d3e7486f4eae",
"value": 0.09,
"asset": "ETH",
"category": "external",
"timestamp": "2026-01-12T16:27:11.000Z"
}
],
"children": [
{
"address": "0x12d66f87a04a9e220743712ce6d9bb1b5616b8fc",
"label": "Tornado Cash (0.1 ETH)",
"is_contract": true,
"children": []
}
]
},
"summary": {
"funding_sources": [
{
"address": "0x12d66f87a04a9e220743712ce6d9bb1b5616b8fc",
"label": "Tornado Cash (0.1 ETH)",
"total_eth_sent": 0.09787125813515,
"transfer_count": 1
}
]
}
}The tools above feed into a single REPORT.md — a complete forensic narrative:
Tornado Cash (0.1 ETH) ──→ Attacker EOA ──→ LiFi Bridge ──→ Arbitrum
│
┌──────────────────┘
▼
Attack Contract
(Morpho flash loan 5 WETH)
│
┌─────────┬───────┴───────┬──────────┐
▼ ▼ ▼ ▼
FPS023 FPS020 FPS022 FPS033
(wstETH) (USDC) (USDT) (WETH)
3.9 wst $2,941 $2,803 1.4 WETH
│ │ │ │
└─────────┴───────┬───────┴──────────┘
▼
Swap all → WETH
Repay 5 WETH flash loan
Unwrap 3.92 WETH → ETH
│
▼
Attacker: +3.92 ETH profit
Total damage: ~3.92 ETH (~$12,000). Total investment by the attacker: 0.09 ETH in gas money from a mixer.
See CLAUDE.md for agent instructions and SKILL.md for the investigation playbook.
The typical workflow: spawn parallel agents → each runs one wachi tool → main LLM reads all results → writes REPORT.md.
MIT