Solidity智能合约事件(event)

Solidity智能合约事件(event)

什么是event

EVM有一个日志功能,用于将数据“写”到智能合约之外的数据结构中。其中一个重要的数据是Solidity事件。事件允许我们“打印”在区块链上的信息,这种方式比在智能合约中保存到公共存储变量更容易搜索,且更省gas费。

当被发送事件(调用)时,会触发参数存储到交易的日志中(一种区块链上的特殊数据结构)。这些日志与合约的地址关联,并记录到区块链中.

Solidity event,在更通用的以太坊和 EVM 中称为logs,Solidity中的事件(event)是EVM上日志的抽象。日志是指事件保存在区块链上的数据。事件强调操作行为,日志强调存储内容。

以太坊中的Events和Logs基本上算是同一个概念。Solidity和web3.js中称为Events,以太坊黄皮书中称为Logs。可以理解为:以太坊通过Logs实现Events(事件)功能。智能合约代码通过LOG 将日志写入区块链中。

事件event有什么作用

事件Event的作用的可以总结为以下几点:

  • 异步获取执行结果
  • 和前端交互
    我们可以通过监听event来做到及时更新前端显示
  • 存储合约数据,相比storage要便宜很多(storage存储的大概价格为:每32字节需要消耗20000Gas,而日志存储价格大概为每字节8Gas)

事件有 3 中主要的使用场景

  • 智能合约给用户的返回值
  • 异常触发
  • 更便宜的数据存储

日志内容位于区块链的什么地方?

日志内容是交易收据(Transaction Receipts)的一部分,整个日志内容,包括Receipts的其它内容会生成一个ReceiptsRoot存储在区块的头部。而完整数据则是链下存储

【重要】以太坊交易获取

以太坊交易信息及event、input、logs、topics等概念机制
参考URL: https://learnblockchain.cn/article/3274

当上述事件在合约中调用后,我们通过其交易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"
  }
}

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。

如何在 Solidity 中使用事件?

solidity中,使用关键字event来定义事件,其中参数列表就是需要保存到区块链上的数据。

  1. 在 solidity 中如何定义事件?
  • 事件在函数外部定义
  • 事件名必须和函数名称有所区分
  • 事件名称必须是大写
  • 为了减少混淆事件名称至少得 2 个字母和函数名称不一样

事件的声明由event关键字开头,然后跟事件名称,括号里面写好事件需要记录的变量类型变量名。以ERC20代币合约的Transfer事件为例:

event Transfer(address indexed from, address indexed to, uint256 value);

在这个事件中,有两种参数:有索引的和无索引的。索引参数也被称为“主题”,是事件中的可搜索参数。
每个事件最多有3个带indexed的变量,Transfer事件共记录了3个变量from,to和value,分别对应代币的转账地址,接收地址和转账数量。同时from和to前面带着indexed关键字,表示很重要,程序可以轻松的筛选出特定转账地址和接收地址的转账事件。

一个事件可以分解为:

  • Address:地址,发出事件的合约或账户的地址当前交易被调用的合约地址
  • Topics:主题,事件的索引参数。
  • Data:数据,事件的非索引参数的ABI编码或“哈希”。由于我们知道合约的ABI(因为我们在Etherscan上验证了合约),我们可以在“Dec”或“Decoded”模式下查看它,或者在其原始的“hex”、“Hexidecimal”或 “Encoded”模式下查看。如果我们没有验证过合约,我们就无法看到解码的版本。
  1. 如何来使用事件
    在函数内部通过 emit 关键词,后面跟上事件的名称和事件所需的参数(如果有的话)。
    如果函数会触发事件,则不能将其定义为view或pure。这是因为触发事件会将数据写入区块链(到日志中)。

  2. 匿名事件
    在 solidity 中事件可以是匿名的。默认情况下所有的事件都会有一个主题,来自定义时候的函数名称。使用 anonymous 来记录一个没有主题的事件。匿名事件也会成为 ABI 的一部分。

event Message(
    address _recipient,
    string _message
) anonymous;

如果事件声明为anonymous,在合约 ABI 中,事件的"anonymous"字段将标记为true。
匿名事件的使用成本更低。但是匿名事件不能通过名称去筛选,只能通过合约地址。

参考

web3.js与智能合约交互监听合约事件
参考URL: https://www.b2bchain.cn/8083.html
web3j开发以太坊过滤器(filter)和智能合约事件(event)
参考URL: https://blog.csdn.net/rejames/article/details/81294638
智能合约Solidity教程-事件和日志(一)
参考URL: https://blog.csdn.net/weixin_34252090/article/details/88720360
[强烈推荐,写的很详细]以太坊交易信息及event、input、logs、topics等概念机制
参考URL: https://learnblockchain.cn/article/3274

相关推荐

  1. Solidity智能合约事件(event)

    2024-06-12 09:28:03       7 阅读
  2. 区块链web3智能合约Solidity学习资源整理

    2024-06-12 09:28:03       19 阅读
  3. Solidity-6-合约

    2024-06-12 09:28:03       22 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-12 09:28:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-12 09:28:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-12 09:28:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-12 09:28:03       18 阅读

热门阅读

  1. 镜像没有包含 shell 导致无法进入容器

    2024-06-12 09:28:03       9 阅读
  2. openssl工具国际/国密签名命令行流程

    2024-06-12 09:28:03       6 阅读
  3. 互联网摸鱼日报(2024-06-11)

    2024-06-12 09:28:03       7 阅读
  4. 安装TensorFlow2.12.0

    2024-06-12 09:28:03       7 阅读
  5. Linux信号基础

    2024-06-12 09:28:03       3 阅读
  6. 介绍 TensorFlow 的基本概念和使用场景。

    2024-06-12 09:28:03       11 阅读
  7. 单例设计模式

    2024-06-12 09:28:03       4 阅读
  8. 计算机网络知识点(一)

    2024-06-12 09:28:03       8 阅读
  9. linux查找生产问题常用命令——参数解释

    2024-06-12 09:28:03       6 阅读
  10. 详细说说机器学习在自然语言处理的应用

    2024-06-12 09:28:03       8 阅读