Ethereum以太坊事件日志查询参数

目录

  • 一、Ethereum事件日志查询参数
  • 二、需求
  • 三、实现
  • 四、其他
    • 4.1、topics中4个子数组之间是OR的关系
    • 4.2、涉及枚举入参类型计算事件签名

一、Ethereum事件日志查询参数

详见:https://www.quicknode.com/docs/ethereum/eth_getLogs

  • address:合约地址
  • fromBlock:开始区块
  • toBlock:结束区块
  • topics:主题数组
  • blockHash:区块哈希,优先级高于fromBlock、toBlock

这里主要介绍topics参数,其他参数都比较好理解,topics是长度为4的数组集合,topic分为2种:一种事件签名topic,另一种indexed索引参数值topic。
topics的的0号位子数组放事件签名哈希,1/2/3号位子数组对应放事件的indexed索引参数值对应的哈希。
以demo合约举例:

pragma solidity ^0.4.4;contract Hello {string name;event LogSet(string s);event LogSet1(string indexed s1);event LogSet2(string indexed s1, string indexed s2);event LogSet3(string indexed s1, string indexed s2, string indexed s3);constructor() public {name = "hello";}function get() public view returns (string) {return name;}function set(string newName) public {name = newName;emit LogSet(newName);emit LogSet1(newName);emit LogSet2(newName, "name2");emit LogSet3(newName, "name2", "name3");}
}

如果合约调用set(“Tom”),事件LogSet3的1号位indexed索引参数值为"Tom",2号位为"name2",3号位为"name3"。
注意:
合约事件里最多只能有3个indexed索引参数。
如果事件定义改为:

event LogSet3(string indexed s1, string s2, string indexed s3);

事件LogSet3的1号位indexed索引参数值为"Tom",2号位为"name3",没有3号位。

二、需求

部署一个新的Hello合约,并调用一次set函数,以触发生成4条不同的事件日志。要求查询该合约的LogSet3事件日志。

三、实现

第一步,合约部署前,获取到最新块高,作为fromBlock,假设9684。
第二步,部署Hello合约,并调用set函数,入参newName=“Tom”,假设获取到新合约地址0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b。
第三步,再次获取最新块高,作为toBlock,假设9686。
第四步,计算事件LogSet3(string,string,string)的签名,得到0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b。
第五步,计算第一个indexed索引参数值"Tom"的哈希0x6984758a5a2907300d836a0ed6101bb5426c0a4422c0d996e8bbf9e59bb8c7cc,计算第二个indexed索引参数值"name2"的哈希0x7d51639d4f8290223cffdcc7a75498fd9c00ab65e7daf27837046fec6a6d6504,计算第三个indexed索引参数值"name3"的哈希0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074。
第六步,组装日志查询请求参数,如下:

{"address": "0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b","toBlock": "9686","topics": [["0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b"],["0x6984758a5a2907300d836a0ed6101bb5426c0a4422c0d996e8bbf9e59bb8c7cc"],["0x7d51639d4f8290223cffdcc7a75498fd9c00ab65e7daf27837046fec6a6d6504"],["0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074"]],"fromBlock": "9684"
}

实际上,如果指定了具体的Hello合约地址,请求参数里不需要第一个和第二个索引参数topic,也可以唯一区分开该合约的其他三个事件,如此,请求参数如下:

{"address": "0x0dba67483eddb71a84ac0834cd4c8c89dc971d4b","toBlock": "9686","topics": [["0x3e03ccf7099c79040ac78f368a6a038e5d7918b8504f8cc99fd4d1ae71181e7b"],null,null,["0x289ff8670e65b79f5a7c14daf83f381a29ae238fff49f37396cc9100fb243074"]],"fromBlock": "9684"
}

四、其他

4.1、topics中4个子数组之间是OR的关系

以太坊官网说明:https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newfilter

  • topics: Array of DATA, - (optional) Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options.

举例:
[[A, B], [A, B]] “(A OR B) in first position AND (A OR B) in second position (and anything after)”

4.2、涉及枚举入参类型计算事件签名

如果事件参数中包含枚举类型,如何正确计算该事件签名的topic。
在solidity中的enum类型,实际上是无符号整数,当枚举数量是小于等于256(2的8次方)个,则enum是uint8类型的,如果大于256且小于等于65536(2的16次方),则enum是uint16类型的,以次类推。其实在remix中也可以看到,枚举内的数量小于256,枚举类型自动使用uint8,如下:
uint8
所以对上面的例子,事件签名DataSaved(ProofType,bytes)是错误的,DataSaved(enum,bytes)也是错误的。正确应该是DataSaved(uint8,bytes)
如果ProofType枚举的类型从2种变为257种,在remix里重新部署合约后,可以看到uint8自动变为uint16,如下:
uint16


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部