文章目录

  • 一、交易信息获取
    • 1.1 合约事件例子定义
    • 1.2 以太坊交易获取
  • 二、input解析
    • 2.1 input内容解析
    • 2.2 input处理逻辑
  • 三、logs解析
    • 3.1 logs解析代码
  • 四、topics
    • 4.1 概念
    • 4.2 indexed
  • 五、合约交易关键字段解释

一、交易信息获取

1.1 合约事件例子定义

举例,比如合约中事件如下:(以下内容均使用该事件例子)

event Transfer(address indexed from, address indexed to, uint256 value);
  • 事件名称:Transfer
  • 事件的参数:address, address, uint256
  • 注意:此事件的from和to参数前有indexed标记,value没有indexed标记

1.2 以太坊交易获取

当上述事件在合约中调用后,我们通过其交易hash获取交易信息。从以太坊得到一条交易信息的方式有两种:

  • eth_getTransactionByHash: :返回指定交易对应的交易信息
  • eth_getTransactionReceipt :返回指定交易对应的收据信息

eth_getTransactionByHash

返回的具体信息如下

{"jsonrpc": "2.0","id": 1,"result": {"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528","blockNumber": "0xd19505","from": "0xb8262c6a2dcabd92a77df1d5bd074afd07fc5829","gas": "0x10e3d","gasPrice": "0x274daee580","maxFeePerGas": "0x2d48ddd9f1","maxPriorityFeePerGas": "0x6ccc91d0","hash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36","input": "0xa9059cbb000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000016512c902","nonce": "0x14","to": "0xdac17f958d2ee523a2206206994597c13d831ec7","transactionIndex": "0x71","value": "0x0","type": "0x2","accessList": [],"chainId": "0x1","v": "0x1","r": "0xa1d7455286525df11602aab34e9e8ab21b092e2c7853a0d6beca0dfb2a78b2e8","s": "0x75a485b8c378173a829b27a2e55312311fdb33c68ae65f4c74e5f9cc0a748e0d"}
}

web3调用中文文档:https://www.wenjiangs.com/doc/pr2nvcat

curl 调用:

curl -s -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36"],"id":1}' http://127.0.0.1:8545

eth_getTransactionReceipt

{"jsonrpc": "2.0","id": 1,"result": {"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528","blockNumber": "0xd19505","contractAddress": null,"cumulativeGasUsed": "0x6c847e","effectiveGasPrice": "0x274daee580","from": "0xb8262c6a2dcabd92a77df1d5bd074afd07fc5829","gasUsed": "0xa169","logs": [{"address": "0xdac17f958d2ee523a2206206994597c13d831ec7","topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000b8262c6a2dcabd92a77df1d5bd074afd07fc5829","0x000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"],"data": "0x000000000000000000000000000000000000000000000000000000016512c902","blockNumber": "0xd19505","transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36","transactionIndex": "0x71","blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528","logIndex": "0xa0","removed": false}],"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000080000000000000000000000000000000000000000000000000000000000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000004000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000200","status": "0x1","to": "0xdac17f958d2ee523a2206206994597c13d831ec7","transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36","transactionIndex": "0x71","type": "0x2"}
}

注意:getTransaction返回结果中包含input,而getTransactionReceipts返回结果中包含logs。

二、input解析

2.1 input内容解析

input=0x则为非合约调用,否则为合约方法调用。

以合约方法function transfer(address to, uint tokens) 为例;

input数据分为3个部分:

  • 第一部分: 4 字节,是方法名的哈希

例如:a9059cbb,具体可参见:以太坊智能合约各方法对应的签名编码

  • 第二部分: 32字节,以太坊地址,目前以太坊地址是20个字节,高位补0
例如:000000000000000000000000abcabcabcabcabcabcabcabcabcabcabcabcabca
  • 第三部分:32字节,是需要传输的代币数量,这里是1*10^18 GNT
例如:0000000000000000000000000000000000000000000000000de0b6b3a7640000

所有这些加在一起就是交易数据:

a9059cbb000000000000000000000000abcabcabcabcabcabcabcabcabcabcabcabcabca0000000000000000000000000000000000000000000000000de0b6b3a7640000

2.2 input处理逻辑

如下为处理input的逻辑(web3.js):

if(transanctionInput=='0x'){// 非合约调用return;
}else{retJson['function'] = {'funcName':null,'inputs':null,'outputs':null,'exeResult':null};var funcArr = mxxContractABI.filter(function (per) {return per.signature == funcHash ;});if(funcArr!==null&&funcArr.length>0){   // 得到方法名if(funcArr[0].hasOwnProperty("name") && funcArr[0].name!==null){retJson['function']['funcName'] = funcArr[0].name;}if(funcArr[0].hasOwnProperty("inputs") && funcArr[0].inputs!==null){funcArr[0].inputs.map(function (res) {  // 得到方法inputs(输入)inputs.push(res.type);});retJson['function']['inputs'] = inputs;}if(funcArr[0].hasOwnProperty("outputs")&& funcArr[0].outputs!==null){funcArr[0].outputs.map(function (res) {// 得到方法outputs(输出)outputs.push(res.type);});retJson['function']['outputs']= outputs;}}status = transanctionReceipt.status;if(status == '0x1'){//执行成功retJson['function']['exeResult'] = 'Successfully Executed';}else {retJson['function']['exeResult'] = 'Failed Executed';}

三、logs解析

智能合约通过【事件】来产生【日志】,日志存储的Gas费用要比合约的存储便宜很多(日志每个字节花费8个Gas,而合约存储是每32个字节20000个Gas)。想要通过合约向用户返回数据,则需将数据以事件的形式传给用户,用户拿到transactionReceipt后解析log,log.args.x拿到数据。Input只能拿到调用合约以及function的信息,而不能拿到function运行后内部产生的事件(事件不一定和function拥有相同名称和参数)。

3.1 logs解析代码

logs解析步骤代码(web3.js)

web3SolidityEvent = require('./node_modules/truffle-contract/node_modules/web3/lib/web3/event.js');
var transferErc20Json = {"anonymous": false,"inputs": [{"indexed": true,"name": "from","type": "address"}, {"indexed": true,"name": "to","type": "address"}, {"indexed": false,"name": "value","type": "uint256"}],"name": "Transfer","type": "event","signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
};
var transferEvent = new web3SolidityEvent(null, config.transferErc20Json, null);
async function processReceiptLogs(transactionReceipt){let ethErc20LogRecord = null;let logs = transactionReceipt.logs;for (let i = 0; i < logs.length; i++) {let isContractExists = await redis.contractExists(logs[i].address);if (isContractExists === true) {//判断redis中是否存在//是否是ERC-20 transfer事件,用topics来判断if(logs[i].topics[0] === transferErc20Json.signature){ var log = await transferEvent.decode(logs[i]);logger.debug(prefixOfLogger +'--'+'transferEvent decode result:',log);ethErc20LogRecord = {txHash: log.transactionHash,logIndex: log.logIndex,contractAddress: log.address,fromAddress: log.args.from ,toAddress: log.args.to,value: log.args.value.div(Math.pow(10, 18)).toString(),data: log.args.data,blockNumber: log.blockNumber,removed: log.removed};db.setCreateAndUpdateTime(ethErc20LogRecord);let createLogRecord = await tables.EthErc20Log.create(ethErc20LogRecord);}}
}
  1. 取出transactionReceipt中logs;

  2. 取出logs中一条log;

  3. 使用event.js得到transferEvent,然后用transferEvent的decode方法解析log;

若是公链转币,以太坊转账,则交易回执转logs为空。

若是执行合约的事件,则logs不为空,故ERC-20代币转账,会执行合约Transfer方法,产生logs

四、topics

4.1 概念

Topics[]是一个数组

  • Topics[0] :指向特定的事件,是事件的签名,如ERC-20 Transfer方法:
sha3('Transfer(address,address,uint256)') => 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
  • Topics[1] :是address类型的from参数补齐64位结果(合约交易中真正的from地址)

  • Topics[2] :是address类型to参数补齐64位的结果(合约交易中真正的to地址)

由于value没有indexed标记,因此放在data中,将value的值转化为16进制并补齐64位

4.2 indexed

Transfer事件的第一个和第二个参数被标记为indexed, 因此他们的值被放在 topics array 中. 由于value参数没有标记为indexed, 所以value值被放在data字段. 如果事件中有多个字段未标记为indexed, 那么他们的值都会被记录在data字段中。

事件规则

  • topic[0] : keccak(“Transfer(address,address,uint256)”),对事件的字符做keccak散列运算

  • topic[1] : address类型from参数补齐64位

  • topic[2] : address类型to参数补齐64位

data: 没有indexed标记的value的值转化为16进制,并补齐64位

注意:

事件中的参数类型需要写成完整的,如Transfer(address,address,uint)就不行,需要将uint改为uint256。

五、合约交易关键字段解释

{"jsonrpc": "2.0",   //RPC版本号,2.0"id": 1,      //RPC请求编号"result": {  //调用结果,为交易收据,主要包含如下字段:"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528",  // 区块哈希"blockNumber": "0xd19505",   // 区块高度"contractAddress": null,    //合约地址"cumulativeGasUsed": "0x6c847e",  //当前交易执行后累计花费的gas总值"effectiveGasPrice": "0x274daee580",  //当前交易预计使用的gas总值"from": "0xb8262c6a2dcabd92a77df1d5bd074afd07fc5829",   //当前交易发送者的地址"gasUsed": "0xa169",    //执行当前这个交易单独花费的gas"logs": [   //这个交易产生的日志对象数组{"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",   //当前交易被调用的合约地址"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",  //keccak(Transfer(address,address,uint256)), //合约事件签名哈希值,对事件的字符做keccak散列运算"0x000000000000000000000000b8262c6a2dcabd92a77df1d5bd074afd07fc5829",  //当前交易from的地址"0x000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"   //当前交易to的地址], "data": "0x000000000000000000000000000000000000000000000000000000016512c902",     //包含日志的非索引参数"blockNumber": "0xd19505",    // 区块高度"transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36",   //交易的哈希值,32字节"transactionIndex": "0x71"   //交易在区块里面的序号,当交易为pending时为空"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528","logIndex": "0xa0",    //块中日志索引位置的整数,当交易为pending时日志为空。"removed": false   //当由于链重组而删除日志时,为True。 如果它是一个有效的日志则为False。  }],//bloom过滤器,当交易为pending时日志为空"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000080000000000000000000000000000000000000000000000000000000000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000004000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000200","status": "0x1",   //交易事务状态,1(成功)或0(失败)"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",   //当前交易被调用的合约地址"transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36",  //交易的哈希值,32字节"transactionIndex": "0x71",  //交易在区块里面的序号,当交易为pending时为空"type": "0x2"  }
}

getTransactionReceipt返回信息字段详情可参考:https://infura.io/docs/ethereum/json-rpc/eth-getTransactionReceipt


以上,就是今天分享的全部内容了。

希望大家通过以上方式可以解决自己的实际需求,解决自己目前所遇到的问题。

如果在查看过程中有任何疑问,可以扫描下面的二维码,添加我的个人微信,备注:地区-职业方向-昵称,欢迎来撩,加入区块链技术交流群,与更多的区块链技术大佬学习交流。

原创不易,码字不易。 觉得这篇文章对你有点用的话,麻烦你为本文点个赞,留言或转发一下,因为这将是我输出更多优质文章的动力,感谢!

以太坊交易信息及event、input、logs、topics等概念机制相关推荐

  1. 刺猬文│以太坊交易信息解析方法

    (图片出自网络,版权归原作者所有) 上一篇刺猬文中,提到了合约进行编码后的abi码问题.之后有朋友问我,abi码是干啥的?这个问题问的我无从回答--大家只要在百度上搜索一下,就有一大把一大把的现成答案 ...

  2. 区块链 以太坊 交易结构、执行、存储 解析 交易中为什么没有包含发送者地址这条数据

    一. 交易的结构 1. Transaction结构 交易结构定义在 core/types/transaction.go 中: type Transaction struct {//交易数据data t ...

  3. Web3j通过合约地址监听transfer事件获取以太坊交易数据

    Web3j通过合约地址监听transfer事件获取以太坊交易数据 We3j web3j是一个轻量级的Java库,用于在Ethereum网络上集成客户端(节点). 核心特性 通过Java类型的JSON- ...

  4. java如何监听以太坊交易

    2019独角兽企业重金招聘Python工程师标准>>> 你可以在web3j库的帮助下使用java轻松监听以太坊交易,但此库无法监听Erc20 Token交易. 要监听Erc20Tok ...

  5. Infura Http 客户端 以太坊 交易

    web3j Infura 模块提供了一个Infura Http 客户端(InfuraHttpService),它为Infura特定的Infura-Ethereum-Preferred-Client提供 ...

  6. 以太坊交易中的nonce和confirmation

    1. 以太坊交易中的nonce及其价值 1.1 以太坊交易中的nonce值 在以太坊中,每笔交易都有一个nonce值,该nonce值代表的是从该交易发起地址发出的交易数.(当存在使用同一地址从多个客户 ...

  7. 以太坊交易Nonce设置

    1 什么是nonce? 以太坊中的nonce有两个意义: 1.工作量证明:为了证明工作量的无意义的值,这是采矿的本质,这个值将决定采矿的难度, 2.账户的随机数:在一个账户中的防止多重交易的用途.例如 ...

  8. 以太坊地址和公钥_以太坊交易签名解析源码解读

    上篇文章<以太坊交易签名过程源码解析[1]>从源码角度分析了一个合约调用的的签名过程,签名后的交易发送到以太坊节点后,节点需要从签名交易中还原出公钥(从公钥中单向计算出账号地址),进而将交 ...

  9. 观点:以太坊交易费市场泡沫预警,交易费日渐成为用户难以承受之重

    在经历了一次大熊市之后,以太坊已经再次流行起来.受包括 ETH 价格反弹以及所谓"去中心化金融"(DeFi)的采用等因素的综合影响,以太坊区块链的活跃用户和日交易量都出现了强力增长 ...

最新文章

  1. canvas 中的元素拖拽
  2. boxfilter 函数
  3. Spring整合ActiveMQ完成消息队列MQ编程
  4. The 2020 ICPC Asia Macau Regional Contest J. Jewel Grab(数颜色+链表)
  5. .net core 装了没生效_王者荣耀:辅助装出现惊天bug?辅助光环对自己无效?
  6. 如何保持安全在线的五大技巧
  7. Memcached、MongoDB、Redis和tokyotyrant
  8. python函数type的用意_Python内置函数Type()函数一个有趣的用法
  9. 网络爬虫-原理篇(一)
  10. python是干什么的
  11. opencv有基于c语言的教程吗_VS2019配置opencv详细图文教程和测试代码的实现
  12. spring Bean的生命周期管理
  13. Solidworks如何绘制标准螺纹线
  14. TeamTalk消息协议
  15. 24张最新可视化大屏模板,各行业数据直接套用
  16. linux usleep占用cpu,[RK_2014_0918]linux下,测试usleep函数对CPU占用率的影响
  17. 鸟哥Linux私房菜:第七章笔记
  18. 针对等额本金还款模式的客户,写一个程序按顺序输入贷款总额(单位为万元)、月利率、贷款总月数,输出第一个月客户还款金额(单位为元,取整数)。
  19. JS/Jquery遍历JSON对象、JSON数组、JSON数组字符串、JSON对象字符串
  20. C++不同发展方向的知识点储备

热门文章

  1. 第五章 ERP计划的时间概念
  2. 博客实名与一年前的预言
  3. win11添加右键在此处打开命令窗口
  4. 【无限互联】学员作品:仿汽车之家的App
  5. 小程序实现漂亮的个人中心版面
  6. c语言位域变量定义,C语言位域_Lee_1985的博客的技术博客_51CTO博客
  7. openstack平台上创建云主机
  8. RPA是什么?推荐让电商运营10倍提效的自动化工具
  9. SAP汇率损益处理方法
  10. Kali-WIFI攻防(二)----无线网络分析工具Aircrack-ng