事件 event
本章学习 Solidity
事件 event
的定义和使用方法。
在 Solidity
中,事件(event
)是智能合约的一种通知机制,用于向外部程序或其它合约通知某个事件的发生。
触发一个事件后,相关数据就会存储到区块链的收据中,并与交易关联,记录在区块链上,以便外部应用监听和处理。
事件常常用于调试合约、追踪交易和数据统计等场景。比如:区块浏览器会使用 ERC20
代币合约的事件,对交易数据进行统计。
1. 定义语法
在 Solidity
代码中,使用 event
关键字来定义一个事件,语法如下:
event event-name(<parameter list>);
例如,在 ERC20
代币合约中,定义了一个用来记录转账的事件。
event Transfer(address indexed from, address indexed to, uint256 value);
其中,事件名称为 Transfer
,事件中包含 3 个参数:from
、to
、value
,分别代表转出者地址、接收者地址和转账金额。
2. 使用方法
在 Solidity
代码中,使用 emit
关键字来触发事件,语法如下:
emit event-name(<parameter list>);
例如,触发 ERC20
代币合约中的 Transfer
事件。
emit Transfer(0xAb...b2, 0x4B...db, 1000);
以下,我们使用一个完整的合约范例来展示事件的定义和使用方法。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Event { mapping (address => uint256) balances; // 定义转账事件 event Transfer(address indexed from, address indexed to, uint256 value); // 构造函数,设置合约部署者的余额无限大 constructor() { balances[msg.sender] = type(uint256).max; } // 由调用者账户转账到 `to` 地址 function tranfer(address to, uint256 value) external { // 转账操作 balances[msg.sender] -= value; balances[to] += value; // 触发转账事件 emit Transfer(msg.sender, to, value); } }
我们把合约代码复制到 Remix
,进行编译,并部署到区块链上:
我们输入参数 to
的地址,比如 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02d,再输入转账数量 1000,点击 transact
按钮,就会在右下方输出执行结果。
执行结果显示,产生了 1 条事件日志,我们可以继续查看详情。
3. indexed
在 Solidity
中,使用 emit
触发的事件中,有一种特殊形式称为索引事件,语法如下:
event event-name(type-name indexed parameter-name,...);
例如,在 ERC20
代币合约中,定义了一个用来记录转账的索引事件。
event Transfer(address indexed from, address indexed to, uint256 value);
外部应用程序可以根据 indexed
标记过的参数进行高效的过滤和搜索事件。比如,可以应用于以下场景:
- 过滤事件
通过索引参数,外部应用程序可以过滤感兴趣的事件。例如,根据发送者或接收者地址过滤特定用户的交易事件。
- 高效搜索
通过索引参数,外部应用程序可以快速搜索具有特定属性或条件的事件。例如,按照特定金额范围搜索交易事件。
注意:
1. 没有使用 indexed
标记过的参数,不能作为过滤或者搜索的字段。
2. 一个事件中 indexed
标记的参数最多有 3 个。
3. 记录区块链的日志,也可以使用状态变量,但事件耗费的 gas
要低。