如何解码交易日志数据?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
相关产品推荐
相关产品推荐

