使用Web3.py解码以太坊ERC-20 Transfer事件及读取地址问询
从区块链Transfer事件日志中提取from/to地址
核心结论
是的,from和to地址存在于返回数据的topics字段中。
原理说明
以太坊事件日志的规则:
- 第一个
topic是事件签名的Keccak256哈希值,对应你提供的Transfer(address,address,uint256)的哈希(即0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef)。 - 后续的
topic对应事件中被indexed修饰的参数。标准ERC20的Transfer事件里,from和to这两个address类型参数默认会被标记为indexed,因此会被放入topics数组中;而uint256类型的金额参数未被indexed,所以存放在data字段里。
提取方法
从你给出的日志数据中:
topics[1]是from地址:去掉前24个十六进制的0,得到0xdCa0A91797Bf8A291Aa2B02D8d9cE581d90dB2bFtopics[2]是to地址:去掉前24个十六进制的0,得到0xD563acE91E2748338fED2E170F588C0aED6d087B
如果用Python代码提取(基于Web3.py库):
from web3 import Web3 # 你的日志数据 log = {'address': '0x2B9a49417F9c9c8Dd18EF5bb37c20637441Ad67a', 'topics': [HexBytes('0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'), HexBytes('0x000000000000000000000000dca0a91797bf8a291aa2b02d8d9ce581d90db2bf'), HexBytes('0x000000000000000000000000d563ace91e2748338fed2e170f588c0aed6d087b')], 'data': HexBytes('0x00000000000000000000000000000000000000000002801cad436a90586c431e'), 'blockNumber': 17266903, 'transactionHash': HexBytes('0x16c1191e97b3944b72104db5d3455632a899861c6e121bd59dd33e90b6e35a66'), 'transactionIndex': 0, 'blockHash': HexBytes('0x826d97e893316fc0bf6458521a3c75bf08d8e94a4c7f0e6c0f1c4c7eff2f2792'), 'logIndex': 0, 'removed': False} # 提取from地址(截取后20字节,转成校验和格式) from_addr = Web3.to_checksum_address(log['topics'][1].hex()[26:]) # 提取to地址 to_addr = Web3.to_checksum_address(log['topics'][2].hex()[26:]) # 提取转账金额 amount = int.from_bytes(log['data'], byteorder='big') print(f"From: {from_addr}") print(f"To: {to_addr}") print(f"Amount: {amount}")
代码解释
- 以太坊地址是20字节,而
topic是32字节,因此会在地址前补12字节(24个十六进制字符)的0,所以从第26位(跳过0x和24个0)开始截取即可得到原始地址。 - 使用
Web3.to_checksum_address是为了将地址转换为符合以太坊规范的校验和格式,避免大小写错误。
内容的提问来源于stack exchange,提问作者BAR
相关产品推荐
相关产品推荐

