Python中用ABI解码Uniswap V2 Swap事件数据报错求助
问题:Uniswap V2 Swap事件日志data字段解码失败
我接触以太坊区块链仅两天,目前知识尚零散,但已成功连接节点并拉取基础区块数据。接下来尝试构建事件过滤器,查询链上历史Swap事件数据(非实时数据),针对USDC的Uniswap V2合约编写了如下代码:
w3 = Web3(Web3.HTTPProvider(NODE_ADDRESS)) # uniswap v2 USDC address = w3.toChecksumAddress('0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc') # get the ABI for uniswap v2 pair events resp = requests.get("https://unpkg.com/@uniswap/v2-core@1.0.0/build/IUniswapV2Pair.json") if resp.status_code==200: abi = json.loads(resp.content)['abi'] # create contract object contract = w3.eth.contract(address=address, abi=abi) # get topics by hashing abi event signatures res = contract.events.Swap.build_filter() # put this into a filter input dictionary filter_params = {'fromBlock':int_to_hex(12000000),'toBlock':int_to_hex(12010000),**res.filter_params} # res.filter_params contains: 'topics' and 'address' # create a filter id (i.e. a hashed version of the filter data, representing the filter) method = 'eth_newFilter' params = [filter_params] resp = self.block_manager.general_sample_request(method,params) if 'error' in resp: print(resp) else: filter_id = resp['result'] # pass on the filter id, in order to query the respective logs params = [filter_id] method = 'eth_getFilterLogs' resp = self.block_manager.general_sample_request(method,params) # takes about 10-12s for about 12000 events
获取到的事件日志结构如下:
resp['result'][0] >>> {'address': '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc', 'topics': ['0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', '0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d', '0x0000000000000000000000000ffd670749d4179558b6b367e30e72ce2efea28f'], 'data': '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000\ 00000000000000000000000000034f0f8a0c7663264000000000000000000000000000000000000000000000\ 000000000019002d5b60000000000000000000000000000000000000000000000000000000000000000', 'blockNumber': '0xb71b01', 'transactionHash': '0x76403053ee0300411b68fc223b327b51fb4f1a26e1f6cb8667e05ec370e8176e', 'transactionIndex': '0x22', 'blockHash': '0x4bd35cb48395e77fd317a0309342c95d6687dbc4fcb85ada2d635fe266d1e769', 'logIndex': '0x16', 'removed': False}
尝试使用contract.decode_function_input(resp['result'][0]['data'])解码data字段时,报错:ValueError: Could not find any function with matching selector,求解决。
解决方法
错误原因
decode_function_input方法是用来解码智能合约函数调用的输入数据(即交易的input字段),而你要处理的是事件日志的data字段,二者编码规则完全不同,因此会触发匹配失败的报错。
正确解码方式
要解码Uniswap V2的Swap事件日志,需要使用合约事件对象对应的解码方法,有两种常用方式:
- 单条日志解码:直接使用
contract.events.Swap.decode_log()方法传入整条日志数据:
# 取第一条日志 log = resp['result'][0] # 解码日志 decoded_log = contract.events.Swap.decode_log(log) # 打印解码结果 print(decoded_log)
- 批量处理日志:遍历所有获取到的日志逐个解码:
decoded_swaps = [] for log in resp['result']: try: decoded = contract.events.Swap.decode_log(log) decoded_swaps.append(decoded) except Exception as e: print(f"解码日志失败: {e}") # 查看解码后的核心字段 for swap in decoded_swaps: print(f"交易哈希: {swap.transactionHash.hex()}") print(f"代币0变动量: {swap.args.amount0}") print(f"代币1变动量: {swap.args.amount1}") print(f"交易发起方: {swap.args.sender}") print(f"接收方: {swap.args.to}") print("---")
补充说明
解码后的结果是一个包含日志元数据(如blockNumber、transactionHash)和事件参数(存在args属性中)的对象,可直接访问对应属性获取所需数据。
内容的提问来源于stack exchange,提问作者user19976975
相关产品推荐
相关产品推荐

