智能合约代码应用层由4部分组成,这里主要讲解一下event和logs作用以及如何实现。
事件(event):我们平时就称为它事件,更确切的叫广播事件。它在智能合约代码中需要单独定义,而后由方法进行调用,向外广播的同时生成一条日志(log,logs是log的集合)。当事件向外广播时,一些第三方程序如果部署了监听区块的脚本,同时广播的事件又符合他们监听的条件,则他们可以获得这次事件的参数,然后进行后续程序的执行。
日志(logs):由事件广播时生成,事件每广播一次就会生成一条日志,日志能保留广播时的所有信息,可以查询历史记录。
两者的作用在实际开发中几乎是一样的,无论是事件监听还是查询记录都能实现我们预期的效果,区别在于两点:
1.事件是实时触发的,响应更快更及时,当我们需要等待返回结果后再往后执行时推荐监听事件。缺点可能会因服务器或网络原因有遗漏。
2.日志稳定,需要按条件查询,一般需要做数据同步和数据统计的时候可以用到。缺点是没有实时性,需要定时触发,且频率不能太快。
两者相辅相成,一些好的项目一边监听事件,一边通过日志补漏,可以完美的与链上数据进行同步。
async md5() {
//获取当前区块高度
let height = await provider.getBlockNumber();
//定义查询条件
let filter = {
address: '0x2c4eb3c76D7115E210Fadf3cBFe8E0a3d5b8448F',
fromBlock: 0,
toBlock: height,
topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000173f8ce8356dd214813f4874c316739f560d8022"
]
}
let res = await provider.getLogs(filter)
console.log(res)
}
async md7() {
let greet = new ethers.Contract('0x2c4eb3c76D7115E210Fadf3cBFe8E0a3d5b8448F', erc20abi, signer);
let height = await provider.getBlockNumber();
let myAddress = await signer.getAddress()
let filterFrom = greet.filters.Transfer(myAddress, null);
let filterTo = greet.filters.Transfer(null, myAddress);
let res = await greet.queryFilter(filterTo, 0, height)
},
直接通过查询条件进行筛选日志,两种查法的区别在于第一种的直接根据地址和合约方法编码后的字符串进行查询,当你有区块浏览器并能获得该方法编译后的值建议使用这个。第二种是根据合约地址和abi方法名进行查询,当你找不到自己方法名编译后的值时可以用这个。
需要注意的是BSC,TRON链等出于某些原因,禁止了直接通过这些方法查询日志,必须使用官方的接口才行。