当前位置: 首页 > news >正文

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)。
      • 适合记录历史数据(如交易记录、状态变化),但不能直接在合约内读取。
      • 比喻:像在账本上记笔记,便宜但不能直接翻回去查(需链下工具)。
// 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)验证输入:

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

      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 使用。
http://www.dtcms.com/a/292153.html

相关文章:

  • UE5 UI scaleBox 缩放框
  • 基于开源AI智能名片链动2+1模式与S2B2C商城小程序的淘宝新店引流与好评优化策略研究
  • 现在希望用git将本地文件crawler目录下的文件更新到远程仓库指定crawler目录下,命名相同的文件本地文件将其覆盖
  • Elastic Cloud 简化版:GCP Marketplace
  • 【LeetCode数据结构】栈和队列的应用——用队列实现栈问题、用栈实现队列问题详解
  • Leetcode力扣解题记录--第73题(矩阵置零)
  • ecflow服务的搭建,源码编译方式
  • Gerrit多仓库对应多邮箱配置办法
  • Stirling PDF本地PDF编辑器:cpolar内网穿透实验室第628个成功挑战
  • Apache Ignite 索引(Indexes)定义和使用
  • 【运维】SGLang服务器参数配置详解
  • Vue开发常用库(含npm安装命令)
  • IPv4枯竭时代:从NAT技术到IPv6的演进之路
  • C++函数 vs Go函数
  • C++ 中重载函数右值引用和左值引用匹配的优先级
  • 【机器学习】第四章 回归算法
  • 主流开源LLM架构对比与突破·
  • 控制器(Controller)模块的架构与工作流程 -OpenExo
  • Azure可靠性架构指南:构建云时代的高可用系统
  • Java函数指南:从Function到BiFunction的深度解析
  • 电商项目_秒杀_架构及核心
  • 【Linux】进程概念
  • 以Java程序员角度理解MCP
  • 项目复盘核心要点
  • SQL Server 查询优化
  • Vue 脚手架基础特性
  • 前端自动化埋点:页面模块级行为跟踪与问题定位系统​​的技术设计方案
  • 浏览器地址栏输入URL回车后白屏分析
  • 【Web APIs】JavaScript 节点操作 ④ ( 节点操作案例 - 下拉菜单案例 )
  • Java+Vue构建的固定资产内控管理系统,融合移动端便捷与后台管理强大功能,模块完备,提供全量源码,轻松实现资产智能管控