跳至内容
0%

Solidity 中的 events 是什么?

Alchemy team headshot

作者 Alchemy

发布于 2022年10月4日1 分钟阅读

Solidity 事件对智能合约开发者而言至关重要,因为它们允许智能合约对变量进行索引以重建存储状态,有助于自动更新用户界面,并支持对特定变量进行测试。本文将帮助你加深对 Solidity 事件的理解,进一步深入学习 Solidity 编程语言

我们将首先介绍 Solidity 事件,然后给出它们的分类,并提供示例。读完本文后,你将能够为下一个项目创建 Solidity 事件。

什么是 Solidity 中的事件?

在 Solidity 中,事件是智能合约可以触发的已分发信号。 当你调用事件时,参数会被存储在交易的日志中,这是区块链上一种特殊的数据结构。事件会通知外部用户——比如监听中的前端网站或客户端应用程序——区块链上发生了某些事情。

Solidity 中事件与函数有什么区别?

函数和事件都接受参数并可以被调用,但函数会直接修改智能合约,而事件的作用是通知区块链之外的服务,让用户知道发生了某些事情。

Solidity 中的函数允许开发者在智能合约中读取、写入、更改和存储数据。你可以向函数传入参数,也可以在代码中需要的任何地方调用函数。

事件同样接受参数,但这些参数存储在交易日志中,智能合约无法访问该日志。合约数据存放在 State trie 中,而事件数据存储在 Transaction Receipts trie 中,这意味着合约无法读取事件数据。

与函数一样,事件也可以被调用。不过,调用/触发事件使用的是 emit 关键字。这让开发者能够知道某个事件或函数何时被调用。

事件与日志之间是什么关系?

Ethereum 的 Log 数据结构用于存储事件发出的数据。

以太坊虚拟机(EVM)具有日志记录功能,用于将数据(包括 Solidity 事件)写入智能合约之外的结构中。

日志和事件常被视为同义词。事件让你能够以更省 gas 的方式将信息“打印”到日志结构中,因为这些信息不会存储在会占用更多 gas 的存储变量中。事件(或日志)存放在 Transaction Receipts trie 中,智能合约无法访问该结构。

Solidity 中事件是如何被索引的?

Solidity 事件是与 EVM 日志功能对接的接口。 你最多可以为三个参数添加 indexed 属性。这样它们会出现在日志的 topics 结构中,而不是数据部分。当参数没有 indexed 属性时,它们会被 ABI 编码进日志的数据部分。

Solidity 事件类型

Solidity 事件分为两种类型:已索引的和未索引的。

当参数没有 indexed 属性时,它们会被 ABI 编码进日志的数据部分。这些参数构成事件的字节数组。数据会根据其类型进行编码,也可以根据某种模式(schema)进行解码。

已索引的参数也被称为“topics”,是事件中可供搜索的参数。已索引的参数让你能够以这些参数作为过滤条件来搜索相应事件。根据事件是否为匿名事件,你最多可以分别为 4 个或 3 个参数添加 indexed 属性。

Solidity 中事件是如何运作的?

Solidity 事件的生命周期包括声明、触发和注册。

  1. 首先,需要使用 Solidity 中的 event 关键字声明事件类型。
  2. 接下来,使用 emit 关键字触发该事件。
  3. 每当区块链上发生变化时,你的程序会自动记录这一变化并触发该事件。

注意: 在声明之后触发事件,可以让你使用 Web3.js 或 Ethers.js 等库在应用程序中“监听”该事件。

如何在 Solidity 中声明事件?

事件的声明包含事件名称,以及触发事件时你希望保存的参数。

首先,你需要在 Solidity 中声明一个事件。然后,使用 emit 关键字触发该事件。

以下是声明事件的示例:

事件被触发时,会通知外部应用程序区块链上发生了某些变化。

Solidity 中事件是如何被触发的?

事件定义完成后,你可以使用 emit 关键字来触发该事件。事件被触发后,传入的参数会被存储在交易日志中。

以下语法展示了如何在 Solidity 中使用 emit:

如何在 Solidity 中监听事件

事件被触发后,你可以通过订阅来捕获这些事件,从而对其进行监听,可以使用 ethers.js。此后,应用程序,或任何连接到 Ethereum JSON-RPC API 的程序,都可以监听这些事件并作出相应处理。

Solidity 事件示例

以下示例代码定义并触发了一个用于转账的事件。此代码适用于以太坊转账应用程序,在转账发生时触发该事件。你还可以添加额外的代码,让事件在触发时更新用户界面,以显示转账已完成。

定义并触发 Transfer 事件的 Solidity 代码示例
定义并触发 transfer 事件

下一个示例取自 Solidity by Example,创建了一个包含两个参数的事件:发送者地址和字符串消息。触发时,该事件会记录 “Hello World” 和 “Hello EVM”。

包含两个参数(发送方地址和消息字符串)的事件的 Solidity 代码示例
带两个参数的事件

继续学习 Solidity

本文向你介绍了 Solidity 事件,并提供了相关说明和资源,供你在下一个项目中使用。掌握 Solidity 事件后,你将能够更轻松地创建高效的智能合约。

如果你刚接触 Solidity 语言,并期待构建你的第一个智能合约,欢迎报名参加 Alchemy University 免费的、为期 7 周的在线 Solidity 编程课程

Background gradient

构建区块链应用

Alchemy 将最强大的 Web3 开发者产品和工具与资源、社区及专业支持结合在一起。