• 查询或解析solidity智能合约事件event或logs日志


    写在前面

    我们经常会遇到查询或访问某个合约的历史log日志,并解析合约地址相关日志,当然也可以是某个用户的地址。

    下面根据案例,讲实际需求和解决方案

    这是一个token合约,我们将获取此token合约的所有转账事件的历史记录

    https://kovan.etherscan.io/address/0x29abca1f656a18d765971b4bad0ce112669e866e#code
    以上链接是源码链接地址;

    我们的需求这样的

    通过web3js获取此token合约的转账事件,并解析此token合约对应的日志

    这是event事件代码

    1. /**
    2. * @dev Emitted when `value` tokens are moved from one account (`from`) to
    3. * another (`to`).
    4. *
    5. * Note that `value` may be zero.
    6. */
    7. event Transfer(address indexed from, address indexed to, uint256 value);

     这是要解析的日志log,下面emit 后面的代码

    1. /**
    2. * @dev Moves tokens `amount` from `sender` to `recipient`.
    3. *
    4. * This is internal function is equivalent to {transfer}, and can be used to
    5. * e.g. implement automatic token fees, slashing mechanisms, etc.
    6. *
    7. * Emits a {Transfer} event.
    8. *
    9. * Requirements:
    10. *
    11. * - `sender` cannot be the zero address.
    12. * - `recipient` cannot be the zero address.
    13. * - `sender` must have a balance of at least `amount`.
    14. */
    15. function _transfer(address sender, address recipient, uint256 amount) internal {
    16. require(sender != address(0), "BEP20: transfer from the zero address");
    17. require(recipient != address(0), "BEP20: transfer to the zero address");
    18. _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
    19. _balances[recipient] = _balances[recipient].add(amount);
    20. //要解析的日志logs
    21. emit Transfer(sender, recipient, amount);
    22. }

     

    解决方案

    首先打开web3js官方文档:web3.eth.Contract — web3.js 1.0.0 documentation

    这里提供了三种直接访问的方案(其它方案这里不阐述)

    分别是:1:once
                   2:events
                   3:getPastEvents

    这里我们以getPastEvents为例详细阐述

    getPastEvents - 读取合约历史事件

    读取合约的历史事件。

    调用:

    myContract.getPastEvents(event[, options][, callback])

    参数:

    • event - String: 事件名,或者使用 "allEvents" 来读取所有的事件
    • options - Object: 用于部署的选项,包含以下字段:
      • filter - Object : 可选,按索引参数过滤事件,例如 {filter: {myNumber: [12,13]}} 表示所有“myNumber” 为12 或 13的事件
      • fromBlock - Number : 可选,仅读取从该编号开始的块中的历史事件。
      • toBlock - Number : 可选,仅读取截止到该编号的块中的历史事件,默认值为"latest"
      • topics - Array : 可选,用来手动设置事件过滤器的主题。如果设置了filter属性和事件签名,那么(topic[0])将不会自动设置
    • callback - Function : 可选的回调参数,触发时其第一个参数为错误对象,第二个参数为历史事件数组

    返回值:

    一个Promise对象,其解析值为历史事件对象数组

    示例代码:

    1. myContract.getPastEvents('MyEvent', {
    2. filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
    3. fromBlock: 0,
    4. toBlock: 'latest'
    5. }, function(error, events){ console.log(events); })
    6. .then(function(events){
    7. console.log(events) // same results as the optional callback above
    8. });
    9. > [{
    10. returnValues: {
    11. myIndexedParam: 20,
    12. myOtherIndexedParam: '0x123456789...',
    13. myNonIndexParam: 'My String'
    14. },
    15. raw: {
    16. data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
    17. topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
    18. },
    19. event: 'MyEvent',
    20. signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
    21. logIndex: 0,
    22. transactionIndex: 0,
    23. transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
    24. blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
    25. blockNumber: 1234,
    26. address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
    27. },{
    28. ...
    29. }]

    我们的代码;

    1. var Web3 = require('web3');
    2. var web3;
    3. var topic=["0x29abca1F656A18D765971B4Bad0cE112669E866e"];
    4. var abi = [{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}];
    5. async function createWeb3(){
    6. try {
    7. web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/v3/097a55226aad462e913bbf6c60ca039e'));
    8. } catch (error) {
    9. console.log(error);
    10. return false;
    11. }
    12. }
    13. // main();
    14. async function main(){
    15. if (await createWeb3() == false) {
    16. console.log('Web3 Create Error'.yellow);
    17. process.exit();
    18. }
    19. var fomo =new web3.eth.Contract(abi,
    20. topic);
    21. fomo.getPastEvents("Transfer",{fromBlock: 0,
    22. toBlock: 'latest'
    23. }, function(error, events){ console.log(events); })
    24. .then(function(events){
    25. console.log(events) // same results as the optional callback above
    26. });
    27. }
    28. main();

    返回结果:
     

    1. [{
    2. address: '0x29abca1F656A18D765971B4Bad0cE112669E866e',
    3. blockHash: '0xfcfc3a30ddd6e7cf792f8f5b0ae34ecce279ef53d8d1fa2803b5e97c40ec7a6e',
    4. blockNumber: 33488693,
    5. logIndex: 0,
    6. removed: false,
    7. transactionHash: '0xba0694b985d51d845ed028062bd272b3b0261f59f93068663fa3e06b45bfbbfc',
    8. transactionIndex: 0,
    9. transactionLogIndex: '0x0',
    10. type: 'mined',
    11. id: 'log_f5d16985',
    12. returnValues: Result {
    13. '0': '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
    14. '1': '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
    15. '2': '100000000000000000000',
    16. from: '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
    17. to: '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
    18. value: '100000000000000000000'
    19. },
    20. event: 'Transfer',
    21. signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    22. raw: {
    23. data: '0x0000000000000000000000000000000000000000000000056bc75e2d63100000',
    24. topics: [Array]
    25. }
    26. }
    27. ]

    其中一下便是我们解析事件和日志的结果

    1. returnValues: Result {
    2. '0': '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
    3. '1': '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
    4. '2': '100000000000000000000',
    5. from: '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
    6. to: '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
    7. value: '100000000000000000000'
    8. },


    关于topics怎么来的怎么计算的请看这篇文章:Web3Js订阅Log示例_北纬32.6的博客-CSDN博客

    以及参考链接:web3.eth.abi — web3.js 1.0.0 documentation

  • 相关阅读:
    动态规划之四边形不等式
    AcWing 383. 观光 题解(最短路)
    靶向多肽cRGD/血管肽Angiopep/细胞穿膜肽-SiO2复合物(TAT-SiO2)
    城市场景车路协同网络需求研究
    Java 面试中遇到的坑
    散列算法比较:MD5、SHA1、SHA256有哪些区别
    大数据技术从业者注意了!使用代理IP时避开这些误区
    物联网-电力编辑器(一)
    巧用自定义注解,一行代码搞定审计日志
    视觉语言跨模态特征语义相似度计算改进--表征空间维度语义依赖感知聚合算法 ACM MM
  • 原文地址:https://blog.csdn.net/weixin_39842528/article/details/126557057