Cryptographically prove that an Ethereum address has never interacted with a specified address (e.g., a sanctioned contract) using Herodotus Data Processor (HDP).
This module generates a ZK proof that verifies:
- Complete transaction coverage - Every transaction sent by the address is checked (verified via nonce sequence matching the on-chain account nonce)
- Non-interaction guarantee - None of those transactions were sent to the forbidden address
- Point-in-time attestation - The proof is valid up to a specified block number
The result is a verifiable, tamper-proof attestation that can be checked on-chain or off-chain without trusting any intermediary.
While this example uses Tornado Cash as the forbidden address, the pattern generalizes to:
- Sanctions screening (OFAC, other lists)
- Protocol-specific exclusions (e.g., no interaction with known exploit contracts)
- Counterparty verification for institutional DeFi
- On-chain reputation and eligibility checks
src/lib.cairo: Contains the main Cairo code for the module.Scarb.toml: Configuration file for managing dependencies and build settings using Scarb.input.json: Example input data for the module.run.sh: Shell script to execute the module.generate_input.py: Python script to automatically generate input.json by fetching transactions from RPC/Etherscan.
To work with this project, ensure you have the following installed:
- Cairo programming language
- Scarb for dependency management
- Python 3.7+ (for generating inputs)
requestslibrary:pip install -r requirements.txt
-
Clone the repository:
git clone https://github.com/HerodotusDev/hdp-tornado-module.git cd hdp-tornado-module -
Install HDP using the official installation script:
curl -fsSL https://raw.githubusercontent.com/HerodotusDev/hdp-cairo/main/install-cli.sh | bash cd $(hdp pwd) cat > .env << 'EOF' RPC_URL_ETHEREUM_MAINNET=<your rpc provider> RPC_URL_ETHEREUM_TESTNET=<your rpc provider> RPC_URL_HERODOTUS_INDEXER=https://rs-indexer.api.herodotus.cloud/ EOF
-
Install Python dependencies for input generation:
pip install -r requirements.txt
-
Generate input.json (optional - automatically fetches transactions):
# Interactive mode python3 generate_input.py # Or with command-line arguments python3 generate_input.py <user_address> <forbidden_address> <upper_bound_block> # Set environment variables for RPC/Etherscan (optional) export RPC_URL_ETHEREUM_TESTNET=<your_rpc_url> export ETHERSCAN_API_KEY=<your_api_key> # Recommended for faster results
-
Install dependencies and compile using Scarb:
scarb build
-
Run the module:
./run.sh
The module accepts the following inputs (see input.json for example):
| Parameter | Description |
|---|---|
user_address |
The Ethereum address to verify |
forbidden_address |
The address to check against (e.g., Tornado Cash router) |
upper_bound_block_number |
Block number up to which the proof is valid |
txs |
Array of (block_number, transaction_index) pairs covering all user transactions |
The generate_input.py script automatically fetches all transactions for a given address up to a specified block number. It supports two methods:
- Etherscan API (default, recommended): Fast and efficient. Works without API key for limited requests, but an API key is recommended for higher rate limits.
- Direct RPC: Slower but more private. Set
RPC_URL_ETHEREUM_TESTNETenvironment variable to use this method.
The script automatically:
- Fetches all transactions sent by the user address
- Sorts them by nonce to ensure correct order
- Generates the proper input.json format
- Currently configured for Ethereum Sepolia testnet (
ETHEREUM_TESTNET_CHAIN_ID) - The
generate_input.pyscript automatically discovers transactions, but the module itself verifies completeness - Proof covers direct interactions only (does not trace internal calls or contract-mediated transfers)
src/lib.cairo: This file contains the core logic of the module written in Cairo.Scarb.toml: Defines the dependencies and build configurations for the project.input.json: Provides example input data for testing the module.run.sh: A shell script to execute the module.generate_input.py: Python script that automatically fetches transactions from RPC/Etherscan and generates input.json.requirements.txt: Python dependencies for the input generation script.
