""" Configuration file for Tornado Cash Analyzer """ import os from dotenv import load_dotenv # Load environment variables load_dotenv() # Bitquery auth (OAuth token required) BITQUERY_OAUTH_TOKEN = os.getenv("BITQUERY_OAUTH_TOKEN", "") BITQUERY_API_URL = "https://streaming.bitquery.io/graphql" # Network configuration # Bitquery network identifiers: eth, matic, bsc, etc. SUPPORTED_NETWORKS = { "eth": "Ethereum Mainnet", "matic": "Polygon", "bsc": "Binance Smart Chain" } # Default network DEFAULT_NETWORK = "eth" # OFAC-Sanctioned Tornado Cash Contract Addresses by Network # Source: U.S. Treasury OFAC SDN List - August 8, 2022 # https://ofac.treasury.gov/recent-actions/20220808 TORNADO_CASH_CONTRACTS_BY_NETWORK = { "eth": { # All sanctioned addresses from OFAC SDN List (Ethereum Mainnet) "0x8589427373D6D84E98730D7795D8f6f8731FDA16", "0x722122dF12D4e14e13Ac3b6895a86e84145b6967", "0xDD4c48C0B24039969fC16D1cdF626eaB821d3384", "0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b", "0xd96f2B1c14Db8458374d9Aca76E26c3D18364307", "0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D", "0xD4B88Df4D29F5CedD6857912842cff3b20C8Cfa3", "0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF", "0xA160cdAB225685dA1d56aa342Ad8841c3b53f291", "0xFD8610d20aA15b7B2E3Be39B396a1bC3516c7144", "0xF60dD140cFf0706bAE9Cd734Ac3ae76AD9eBC32A", "0x22aaA7720ddd5388A3c0A3333430953C68f1849b", "0xBA214C1c1928a32Bffe790263E38B4Af9bFCD659", "0xb1C8094B234DcE6e03f10a5b673c1d8C69739A00", "0x527653eA119F3E6a1F5BD18fbF4714081D7B31ce", "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2", "0xD691F27f38B395864Ea86CfC7253969B409c362d", "0xaEaaC358560e11f52454D997AAFF2c5731B6f8a6", "0x1356c899D8C9467C7f71C195612F8A395aBf2f0a", "0xA60C772958a3eD56c1F15dD055bA37AC8e523a0D", "0x169AD27A470D064DEDE56a2D3ff727986b15D52B", "0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f", "0xF67721A2D8F736E75a49FdD7FAd2e31D8676542a", "0x9AD122c22B14202B4490eDAf288FDb3C7cb3ff5E", "0x905b63Fff465B9fFBF41DeA908CEb12478ec7601", "0x07687e702b410Fa43f4cB4Af7FA097918ffD2730", "0x94A1B5CdB22c43faab4AbEb5c74999895464Ddaf", "0xb541fc07bC7619fD4062A54d96268525cBC6FfEF", "0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc", "0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936", "0x23773E65ed146A459791799d01336DB287f25334", "0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af", "0x610B717796ad172B316836AC95a2ffad065CeaB4", "0x178169B423a011fff22B9e3F3abeA13414dDD0F1", "0xbB93e510BbCD0B7beb5A853875f9eC60275CF498", "0x2717c5e28cf931547B621a5dddb772Ab6A35B701", "0x03893a7c7463AE47D46bc7f091665f1893656003", "0xCa0840578f57fE71599D29375e16783424023357", "0x12d66f87A04A9E220743712cE6d9bb1b5616B8Fc", "0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3C2936", "0x910Cbd523D972eb0a6f4cAe4618Ad62622b39DbF", "0xA160cdAB225685dA1d56aa342Ad8841c3b53f291", "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2" }, "matic": { # Polygon addresses provided by user "0xdf231d99Ff8b6c6CBF4E9B9a945CBAcEF9339178", "0xaf4c0B70B2Ea9FB7487C7CbB37aDa259579fe040", "0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD", "0xa5C2254e4253490C54cef0a4347fddb8f75A4998", "0xDD4c48C0B24039969fC16D1cdF626eaB821d3384" }, "bsc": { # Binance Smart Chain addresses provided by user "0x0d5550d52428e7e3175bfc9550207e4ad3859b17", "0x330bdfade01ee9bf63c209ee33102dd334618e0a" } } # Helper function to get addresses for a network def get_tornado_cash_addresses(network: str = None) -> list: """Get Tornado Cash contract addresses for a given network""" if network is None: network = DEFAULT_NETWORK if network not in TORNADO_CASH_CONTRACTS_BY_NETWORK: network = DEFAULT_NETWORK return list(TORNADO_CASH_CONTRACTS_BY_NETWORK.get(network, set())) # Backward compatibility: default to Ethereum TORNADO_CASH_ADDRESSES = get_tornado_cash_addresses("eth") # Tornado Cash Pool Denominations by Contract Address # Maps contract addresses to their pool sizes (in ETH) # Source: Tornado Cash documentation and OFAC listings POOL_DENOMINATIONS = { "eth": { "0x12d66f87A04A9E220743712cE6d9bb1b5616B8Fc": "0.1 ETH", "0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc": "0.1 ETH", # Case variation "0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3C2936": "1 ETH", "0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936": "1 ETH", # Case variation "0x910Cbd523D972eb0a6f4cAe4618aD62622b39DbF": "10 ETH", "0x910Cbd523D972eb0a6f4cAe4618Ad62622b39DbF": "10 ETH", # Case variation "0xA160cdAB225685dA1d56aa342Ad8841c3b53f291": "100 ETH", "0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b": "Router", # Router contract "0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2": "Relayer Registry", # Relayer registry } } def get_pool_denomination(contract_address: str, network: str = "eth") -> str: """ Get the pool denomination for a given contract address Args: contract_address: The contract address to look up network: Network identifier (eth, matic, bsc, etc.) Returns: Pool denomination string (e.g., "0.1 ETH", "1 ETH", "10 ETH", "100 ETH", "Router", "Relayer Registry", or "Unknown") """ if network not in POOL_DENOMINATIONS: return "Unknown" if not contract_address: return "Unknown" # Normalize address to lowercase for comparison address_lower = contract_address.lower() pool_map = POOL_DENOMINATIONS[network] # Try exact match first if contract_address in pool_map: return pool_map[contract_address] # Try case-insensitive match for addr, denomination in pool_map.items(): if addr.lower() == address_lower: return denomination return "Unknown" # Analysis Configuration DEFAULT_LIMIT = 100 DEFAULT_TIME_TOLERANCE_SECONDS = 7200 #2 hours DEFAULT_NETWORK_WINDOW_DAYS = 14 VALUE_TOLERANCE_PERCENT = 0.01 # 1% tolerance for matching amounts