You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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事件日志,需要使用合约事件对象对应的解码方法,有两种常用方式:

  1. 单条日志解码:直接使用contract.events.Swap.decode_log()方法传入整条日志数据:
# 取第一条日志
log = resp['result'][0]
# 解码日志
decoded_log = contract.events.Swap.decode_log(log)
# 打印解码结果
print(decoded_log)
  1. 批量处理日志:遍历所有获取到的日志逐个解码:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:35:37