Events

本节是《Solidity by Example》的中文翻译与深入讲解,专为零基础或刚接触区块链开发的小白朋友打造。我们将通过"示例 + 解说 + 提示"的方式,带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。

Solidity 是以太坊等智能合约平台使用的主要编程语言,就像写网页要用 HTML 和 JavaScript,写智能合约就需要会 Solidity。

如果你从没写过区块链代码也没关系,只要你了解一点点编程概念,比如"变量""函数""条件判断",我们就能从最简单的例子开始,一步步建立你的 Solidity 编程思维。

Events

事件

事件允许在以太坊区块链上记录日志。事件的一些用途包括:

  • 监听事件并更新用户界面
  • 作为一种廉价的存储方式

什么是 Solidity 事件?

在 Solidity 中,事件(Events)是智能合约与外部世界(如前端应用或链下服务)通信的机制,用于记录特定操作或状态变化到区块链的日志(logs)。

  • 比喻:事件像合约发出的广播信号,通知外界"某事发生了",前端或链下服务可以监听这些信号并做出响应(如更新界面)。

  • 事件数据存储在区块链的日志中,成本远低于修改 storage 变量,是高效的链上记录方式。

  • 事件的用途

    • 监听事件并更新用户界面:
      • 前端(如 DApp)通过 Web3.js 或 Ethers.js 监听事件,实时更新页面显示(如显示转账记录)。
      • 比喻:像餐厅服务员喊"订单完成",前台收到信号更新订单状态。
    • 廉价存储:
      • 事件数据存储在区块链的交易日志(logs)中,Gas 成本远低于 storage 变量(约 375 Gas 每 32 字节 vs. 20,000+ Gas 写 storage)。
      • 适合记录历史数据(如交易记录、状态变化),但不能直接在合约内读取。
      • 比喻:像在账本上记笔记,便宜但不能直接翻回去查(需链下工具)。
javascript 复制代码
// SPDX-License-Identifier: MIT
// 使用 MIT 许可证,允许自由使用、修改和分发代码。

pragma solidity ^0.8.26;
// 指定 Solidity 编译器版本,必须为 0.8.26 或更高(但低于 0.9.0)。

contract Event {
    // 定义一个名为 Event 的智能合约,展示事件的定义和触发。

    // Event declaration
    // Up to 3 parameters can be indexed.
    // Indexed parameters help you filter the logs by the indexed parameter
    // 事件声明
    // 最多可以有 3 个参数被索引(indexed)。
    // 被索引的参数有助于通过该参数过滤日志。
    event Log(address indexed sender, string message);
    // 定义一个 AscII text
    // 定义一个事件 Log,包含两个参数:
    // - sender:address 类型,标记为 indexed(索引),可通过该参数高效过滤日志。
    // - message:string 类型,未索引,仅存储在日志数据中。
    // indexed 参数存储在日志的 topics 中,方便链下工具(如 Web3.js)按 sender 过滤事件。
    // 最多 3 个参数可标记为 indexed(Solidity 限制)。
    // 事件本身不消耗 storage,仅记录在交易日志中。

    event AnotherLog();
    // 定义一个无参数的事件 AnotherLog。
    // 无参数事件仅记录事件发生(无额外数据),适合简单通知场景。
    // 不带 indexed 参数,日志仅包含事件签名。

    function test() public {
        // 定义一个公共函数 test,用于触发事件。
        // public:可被外部和内部调用。
        // 不标记为 pure 或 view,因为触发事件会写入区块链日志,消耗 Gas。

        emit Log(msg.sender, "Hello World!");
        // 触发 Log 事件,记录:
        // - sender:调用者的地址(msg.sender,索引参数)。
        // - message:"Hello World!"(非索引参数)。
        // 事件数据写入交易日志,链下可监听。

        emit Log(msg.sender, "Hello EVM!");
        // 再次触发 Log 事件,记录:
        // - sender:调用者的地址(msg.sender,索引参数)。
        // - message:"Hello EVM!"(非索引参数)。

        emit AnotherLog();
        // 触发 AnotherLog 事件,无参数,仅记录事件发生。
        // 适合简单状态通知(如"某操作完成")。
    }
}

Event 合约展示如何定义和触发事件:

  • 定义两个事件:Log(带参数,部分索引)和 AnotherLog(无参数)。
  • 使用 test 函数触发事件,记录调用者地址和消息到区块链日志。
  • 演示事件的基本用法和 indexed 参数的作用。

事件的本质

  • 事件是 Solidity 合约的日志记录机制,将数据写入区块链的交易日志,供链下工具(如前端、分析服务)读取和处理。
  • 比喻:
    • 事件如餐厅的公告板,记录"某人点了什么菜"(Log(sender, message)),前端可读取并显示给用户。
    • indexed 参数像公告板上的分类标签(如按用户地址排序),便于快速查找。
    • 事件不像 storage 变量(昂贵的账本),而是廉价的"便签",记录后不可更改或直接查询。
  • 核心功能:
    • 记录操作:如记录转账、状态更新等,供链下工具(如 DApp)监听。
    • 高效存储 :比修改 storage 变量便宜,适合保存历史记录。
    • 链下交互 :通过 indexed 参数高效过滤日志(如按 sender 查找事件)。

代码功能

  • 事件 Log
    • 记录调用者地址(senderindexed)和消息(message)。
    • indexed 参数 sender 存储在日志的 topics 中,方便按地址过滤。
    • message 存储在日志的 data 字段,成本低但过滤效率较低。
  • 事件 AnotherLog
    • 无参数,仅记录事件发生,适合简单通知(如"操作完成")。
  • 函数 test
    • 触发三次事件:两次 Log(带不同消息)一次 AnotherLog
    • 模拟合约操作(如用户交互)并记录到区块链日志。

事件的注意事项

  • 索引参数(indexed):

    • 最多 3 个 indexed 参数,存储在 topics,方便链下过滤(如按 sender 查找)。
    • 非索引参数存储在 data,成本低但过滤效率较低。
    • 选择合适的 indexed 参数(如地址、ID),避免浪费 topics。
  • Gas 成本:

    • 触发事件约 375 Gas 每 topic(事件签名 + 索引参数),data 每字节约 8 Gas。
    • storage 修改(20,000+ Gas)便宜,适合记录历史数据。
    • 复杂参数(如长字符串)增加 Gas,尽量精简 data 字段。
  • 安全性:

    • 事件仅记录日志,不影响合约逻辑,需确保触发条件正确。

    • 结合错误处理(如require、revert)验证输入:

      javascript 复制代码
      function deposit() public payable {
          require(msg.value > 0, "No value sent");
          emit Deposit(msg.sender, msg.value);
      }
    • 使用修饰器(如onlyOwner)限制敏感事件触发(参考历史对话):

      javascript 复制代码
      modifier onlyOwner() {
          require(msg.sender == owner, "Not owner");
          _;
      }
      function logAdminAction() public onlyOwner {
          emit Log(msg.sender, "Admin action");
      }
  • 链下交互:

    • 事件不可在合约内直接读取,需链下工具(如 Web3.js、Ethers.js)处理。
    • 确保事件参数清晰(如 indexed sender 便于过滤),便于 DApp 使用。
相关推荐
Menger_Wen2 分钟前
【金融机器学习】第三章:收益预测——Bryan Kelly, 修大成(中文翻译)
人工智能·python·机器学习·区块链·模型·量化
运维开发王义杰3 分钟前
解构未来金融:深入剖析DeFi与去中心化交易所(DEX)的技术架构
金融·去中心化·区块链
boyedu15 小时前
Web3.0与元宇宙:区块链驱动的数字新生态解析
web3·区块链·元宇宙
清 晨16 小时前
Web3与区块链如何革新网络安全——走在前沿
web安全·web3·区块链·facebook·tiktok·instagram·clonbrowser
boyedu18 小时前
数字美元与全球支付革命:稳定币的兴起与全球金融格局的重塑
金融·区块链·数字货币·加密货币
Ashlee_code19 小时前
稳定币技术全解:从货币锚定机制到区块链金融基础设施
java·人工智能·游戏·金融·架构·自动化·区块链
终有zy19 小时前
震惊:全面拆解dapp上线三天、 规则漏洞导致资金全部损失
区块链·智能合约
芒果量化19 小时前
okx量化 - python操作合约交易示例1-开源代码
区块链
舒克起飞了19 小时前
Solidity——速通学习
区块链
威哥说编程19 小时前
揭秘区块链的共识革命:Casper协议的背景、发展、机制与潜在风险
c#·区块链