如何在Python中获取以太坊地址的所有代币授权及对应合约?
实现思路
当然可以直接通过Python实现,核心是利用以太坊的事件日志机制:ERC20代币的授权操作会触发Approval事件,我们可以直接查询该事件的历史记录,过滤出目标地址作为owner的所有条目,就能获取对应的授权合约和授权对象,完全不需要依赖第三方网站。
具体实现步骤
- 安装依赖:用
web3.py库与以太坊节点交互,执行pip install web3完成安装。 - 连接节点:使用第三方节点服务(如Infura、Alchemy)或本地运行的以太坊节点,从根源避免请求被拦截的问题。
- 定义事件ABI:需要ERC20
Approval事件的ABI片段来解析日志内容。 - 创建过滤器:构建事件过滤器,指定目标地址作为
owner,查询指定区块范围的日志。 - 解析日志:从返回的日志中提取代币合约地址、授权对象、授权金额等关键信息。
代码示例
from web3 import Web3 # 替换为你的节点URL和API密钥(使用第三方节点时) w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/your-api-key')) # 要查询的目标以太坊地址 target_address = '0xYourTargetAddress' # ERC20 Approval事件的ABI approval_event_abi = { "anonymous": False, "inputs": [ {"indexed": True, "name": "owner", "type": "address"}, {"indexed": True, "name": "spender", "type": "address"}, {"indexed": False, "name": "value", "type": "uint256"} ], "name": "Approval", "type": "event" } # 构建事件过滤器:过滤owner为目标地址的Approval事件 event_filter = w3.eth.filter({ 'topics': [ # 事件签名哈希 w3.keccak(text='Approval(address,address,uint256)').hex(), # 目标地址的哈希(对应indexed的owner参数) Web3.to_bytes(hexstr=target_address).hex() ], # 建议缩小区块范围加快查询,比如从目标地址首次交易的区块开始 'fromBlock': 0, 'toBlock': 'latest' }) # 获取所有匹配的日志条目 logs = event_filter.get_all_entries() # 解析并整理授权信息 authorizations = [] for log in logs: decoded = w3.eth.account.decode_logs([log], [approval_event_abi])[0] auth_data = { 'token_contract': log['address'], 'spender_address': decoded['args']['spender'], 'approved_amount': decoded['args']['value'], 'block_number': log['blockNumber'], 'tx_hash': log['transactionHash'].hex() } authorizations.append(auth_data) # 输出结果 for idx, auth in enumerate(authorizations, 1): print(f"授权 {idx}:") print(f" 代币合约地址: {auth['token_contract']}") print(f" 授权对象地址: {auth['spender_address']}") print(f" 授权金额: {auth['approved_amount']}") print(f" 所在区块: {auth['block_number']}") print(f" 交易哈希: {auth['tx_hash']}") print("-" * 50)
额外注意事项
- 区块范围优化:从创世块查询全量日志会非常慢,建议先获取目标地址的首次交易区块号,以此作为
fromBlock的起始值,大幅提升查询效率。 - 多代币标准支持:如果需要查询ERC721/ERC1155的授权,只需替换对应的事件ABI(如ERC721的
ApprovalForAll)和事件签名即可。 - 节点稳定性:使用本地以太坊节点(如Geth、OpenEthereum)可以避免第三方节点的请求限额问题,适合大规模查询。
- 去重处理:同一代币合约对同一授权对象的多次授权操作会生成多条日志,可通过
token_contract和spender_address去重,保留最新的授权金额。
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

