如何使用web3.py解析事件数据并转换区块过滤获取的十六进制事件串
使用web3.py解析事件原始data字符串
基础逻辑
你拿到的0x开头字符串,是EVM事件编码后的非索引参数字段,完全遵循以太坊ABI编码规则:
- 静态类型(如uint、address)固定占32字节位宽
- 动态类型(如string、bytes、数组)先在固定位宽段存储动态内容的偏移位置,后续再依次存储动态内容的长度、实际值
web3.py内置了完整的ABI解码工具,无需手动拆分字节。
实现方法
- 先对齐每个事件的参数定义:解码必须严格按照事件实际声明的参数顺序、类型传入类型列表,否则会触发解码错误。结合给出的注释,每个事件的对应参数类型如下:
- 单string事件(对应变量a):类型列表
["string"] - 单uint16事件(对应变量b):类型列表
["uint16"] - string+uint16事件(对应变量c):类型列表
["string", "uint16"] - 双string事件(对应变量d):类型列表
["string", "string"] - 双uint16事件(对应变量e):类型列表
["uint16", "uint16"]
- 单string事件(对应变量a):类型列表
- 可直接运行的解码代码:
from web3 import Web3 # 初始化web3实例,无需连接节点即可使用解码能力 w3 = Web3() # 映射事件key到对应参数类型列表 event_type_map = { "a": ["string"], "b": ["uint16"], "c": ["string", "uint16"], "d": ["string", "string"], "e": ["uint16", "uint16"] } # 待解码的原始事件数据 raw_event_data = { "a": '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000', "b": '0x0000000000000000000000000000000000000000000000000000000000000005', "c": '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000', "d": '0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000016200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162000000000000000000000000000000000000000000000000000000000000000', "e": '0x00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005' } # 执行解码 for event_key, data in raw_event_data.items(): param_types = event_type_map[event_key] decoded_result = w3.codec.decode_abi(param_types, data) print(f"事件{event_key}解码结果: {decoded_result}")
实际解码输出
运行代码后得到的原始解码值为:
- 事件a:
('a',) - 事件b:
(5,) - 事件c:
('b', 5) - 事件d:
('b', 'b') - 事件e:
(5, 5)
常见注意事项
- 若使用web3.py 6.0以下版本,无
w3.codec模块,可替换解码调用为兼容写法:decoded_result = w3.eth.contract(abi=[]).decode_event_data(None, data) - 链上日志的
topics数组存储的是带索引的事件参数,data字段存储的是无索引参数,两类参数需分开匹配类型解码,不能混为同一组类型列表 - 解码过程为纯本地计算,无需连接公共节点
内容的提问来源于stack exchange,提问作者Minh Phan
相关产品推荐
相关产品推荐

