如何用Python解码以太坊交易日志中的Topics?
解决以太坊交易日志topics解码问题
问题原因
你尝试用abi.decode直接解码整个topics列表失败的原因有两个:
topics的第一个元素是ERC20 Transfer事件的签名哈希(对应Transfer(address,address,uint256)的Keccak256哈希),不属于要解码的参数;abi.decode要求传入连续的字节数据,而非分开的HexBytes数组。
另外要注意:Transfer事件中,from和to是indexed参数(会放在topics里),而value是非indexed参数,存储在日志的data字段中,不在topics内。
正确处理代码
1. 解析转出/转入地址
topics的第2、3个元素是填充了前导0的32字节格式地址,直接截取后20字节并转换为校验和地址:
# 转出地址 from_address = w3.toChecksumAddress(rec[4]["topics"][1].hex()[26:]) # 转入地址 to_address = w3.toChecksumAddress(rec[4]["topics"][2].hex()[26:])
2. 解析转账金额
从日志的data字段解码uint256类型的金额:
from web3 import abi value = abi.decode(['uint256'], rec[4]["data"])[0] # 若是ERC20代币,需根据代币小数位数转换为可读单位 # value_in_token = value / (10 ** token_decimals)
完整示例
rec = w3.eth.getTransactionReceipt('0x034...').logs target_log = rec[4] # 解析地址 from_addr = w3.toChecksumAddress(target_log["topics"][1].hex()[26:]) to_addr = w3.toChecksumAddress(target_log["topics"][2].hex()[26:]) # 解析金额 transfer_value = abi.decode(['uint256'], target_log["data"])[0] print(f"转出地址: {from_addr}") print(f"转入地址: {to_addr}") print(f"转账金额: {transfer_value}")
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

