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

如何解码交易日志数据?web3.utils.hexToAscii返回乱码问题

正确解码交易日志数据的方法

你直接用web3.utils.hexToAscii()解码整个logs.data会出现乱码,因为日志的data是Solidity ABI编码的结构化数据,包含地址、数值、字符串等多种类型,不能直接整体转ASCII。下面是两种可行的解码方案:

方案一:手动拆分字段解析

根据Solidity ABI编码规则,data中每个参数占32字节(64个十六进制字符),字符串类型会存储偏移量和实际内容,你可以按顺序拆分处理:

function checkHex() {
    web3.eth.getBlock('latest').then(block => {
        for (const txHash of block.transactions) {
            web3.eth.getTransaction(txHash).then(tx => {
                web3.eth.getTransactionReceipt(tx.hash).then(receipt => {
                    for (const log of receipt.logs) {
                        const data = log.data.slice(2); // 去掉前缀0x
                        
                        // 1. 解析地址参数(前32字节)
                        const address = '0x' + data.slice(24, 64); // 地址占最后20字节
                        
                        // 2. 解析数值参数(第二个32字节)
                        const amountHex = data.slice(64, 128);
                        const amount = parseInt(amountHex, 10); // 转十进制,当前0xc8对应200,若预期2000需确认数值是否正确
                        
                        // 3. 解析第一个字符串"Token create"
                        const str1Offset = parseInt(data.slice(128, 192), 16); // 偏移量0x80对应128位
                        const str1Length = parseInt(data.slice(str1Offset*2, str1Offset*2+64), 16); // 字符串长度0xc对应12
                        const str1Hex = data.slice((str1Offset+32)*2, (str1Offset+32)*2 + str1Length*2);
                        const str1 = web3.utils.hexToAscii('0x' + str1Hex);
                        
                        // 4. 解析第二个字符串"101"
                        const str2Offset = parseInt(data.slice(192, 256), 16); // 偏移量0xc0对应192位
                        const str2Length = parseInt(data.slice(str2Offset*2, str2Offset*2+64), 16); // 字符串长度0x3对应3
                        const str2Hex = data.slice((str2Offset+32)*2, (str2Offset+32)*2 + str2Length*2);
                        const str2 = web3.utils.hexToAscii('0x' + str2Hex);
                        
                        // 拼接预期结果
                        console.log(`${amount} ${str1} ${str2}`);
                    }
                });
            });
        }
    });
}

方案二:用ABI解码(更简洁)

如果知道日志对应的Solidity事件ABI,直接用web3.eth.abi.decodeParameters解析会更高效。比如假设你的事件定义是:

event TokenCreate(address indexed sender, uint256 amount, string action, string id);

对应的参数类型数组为:

const paramTypes = ["address", "uint256", "string", "string"];

则解码代码可以写成:

function checkHex() {
    web3.eth.getBlock('latest').then(block => {
        for (const txHash of block.transactions) {
            web3.eth.getTransaction(txHash).then(tx => {
                web3.eth.getTransactionReceipt(tx.hash).then(receipt => {
                    for (const log of receipt.logs) {
                        // 按参数类型解码整个data
                        const decoded = web3.eth.abi.decodeParameters(paramTypes, log.data);
                        
                        // 拼接结果
                        console.log(`${decoded[1]} ${decoded[2]} ${decoded[3]}`);
                    }
                });
            });
        }
    });
}

说明

  • 乱码产生的原因是logs.data前几个参数是十六进制数值(比如0xc8对应十进制200,不是ASCII字符),直接整体转ASCII会出现不可见字符或乱码。
  • 如果预期数值是2000,需要确认日志中的数值参数是否为0x7d0(十进制2000),可能是交易实际数值与预期存在差异,或者事件定义不同。

内容的提问来源于stack exchange,提问作者premchand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:50:37