您的位置:首页 > 财经 > 金融 > 怎么在拼多多上开网店卖东西_代理网店加盟_百度推广销售_企业网站关键词优化

怎么在拼多多上开网店卖东西_代理网店加盟_百度推广销售_企业网站关键词优化

2025/3/10 17:04:44 来源:https://blog.csdn.net/cljdsc/article/details/145528410  浏览:    关键词:怎么在拼多多上开网店卖东西_代理网店加盟_百度推广销售_企业网站关键词优化
怎么在拼多多上开网店卖东西_代理网店加盟_百度推广销售_企业网站关键词优化

文章目录

  • 一、事件
    • 1.1 声明事件
    • 1.2 触发事件
    • 1.3 indexed
  • 二、 EVM日志 `Log`
    • 2.1 主题 `topics`
    • 2.2 数据 `data`
  • 三、演示
    • 3.1 代码示例
    • 3.2 `Remix`演示
    • 3.3 在Etherscan上查询事件
  • 四、总结

这一讲,我们用转账ERC20代币为例来介绍 Solidity中的事件( event)。

一、事件

Solidity 中,事件(event)是智能合约的一种通知机制,用于向外部程序或其它合约通知某个事件的发生。

触发一个事件后,相关数据就会存储到区块链的收据中,并与交易关联,记录在区块链上,以便外部应用监听和处理。

事件常常用于调试合约、追踪交易和数据统计等场景。比如:区块浏览器会使用 ERC20 代币合约的事件,对交易数据进行统计。

Solidity中的事件(event)是EVM上日志的抽象,它具有两个特点:

  • 响应:应用程序(ethers.js)可以通过RPC接口订阅和监听这些事件,并在前端做响应。
  • 经济:事件是EVM上比较经济的存储数据的方式,每个大概消耗2,000 gas;相比之下,链上存储一个新变量至少需要20,000 gas

1.1 声明事件

事件的声明由event关键字开头,接着是事件名称,括号里面写好事件需要记录的变量类型和变量名。

Solidity 代码中,使用 event 关键字来定义一个事件,语法如下:

event event-name(<parameter list>);

例如,在 ERC20 代币合约中,定义了一个用来记录转账的事件。

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

我们可以看到,Transfer事件共记录了3个变量fromtovalue,分别对应代币的转账地址,接收地址和转账数量,其中fromto前面带有indexed关键字,他们会保存在以太坊虚拟机日志的topics中,方便之后检索。

1.2 触发事件

我们可以在函数里释放事件。在下面的例子中,每次用_transfer()函数进行转账操作的时候,都会释放Transfer事件,并记录相应的变量。

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 {// balances是一个mapping,将address映射到一个uint256(无符号整数)。这个映射存储每个地址的余额。具体来说,契约会记录每个地址的代币数量。mapping (address => uint256) balances;// constructor()是合约的构造函数,当合约部署时会自动调用。// 表示约定部署时,部署者(msg.sender)的余额被设置为uint256类型的顶点(type(uint256).max)。这个顶点为2^256 - 1,代表了一个几乎无限的余额。constructor() {balances[msg.sender] = type(uint256).max;}// 定义Transfer转账事件event Transfer(address indexed from, address indexed to, uint256 value);// 由指定的from地址转账到to地址function transfer(address from,address to, uint256 value) external {// 转账操作balances[from] -=  value; // from地址减去转账数量balances[to] += value;// 触发转账事件// 调用emit Transfer(...)触发Transfer事件,记录近期信息。这个事件会被链上日志记录下来,以后查询和监听。emit Transfer(from, to, value);}
}

我们把合约代码复制到 Remix,进行编译,并部署到区块链上:

在这里插入图片描述

我们输入参数fromto 的地址,比如 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4和0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97,再输入转账数量 666,点击 transact 按钮,就会在右下方输出执行结果。

执行结果显示,产生了 1 条事件日志,我们可以继续查看详情。

在这里插入图片描述

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 要低。

二、 EVM日志 Log

以太坊虚拟机(EVM)用日志Log来存储Solidity事件,每条日志记录都包含主题topics和数据data两部分。

在这里插入图片描述

2.1 主题 topics

日志的第一部分是主题数组,用于描述事件,长度不能超过4。它的第一个元素是事件的签名(哈希)。对于上面的Transfer事件,它的事件哈希就是:

keccak256("Transfer(address,address,uint256)")//0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef

除了事件哈希,主题还可以包含至多3indexed参数,也就是Transfer事件中的fromto

indexed标记的参数可以理解为检索事件的索引“键”,方便之后搜索。每个 indexed 参数的大小为固定的256比特,如果参数太大了(比如字符串),就会自动计算哈希存储在主题中。

这里其实会引入一个新的问题,根据Solidity的官方文档, 对于非值类型的参数(如arrays, bytes, strings), Solidity不会直接存储,而是会将Keccak-256哈希存储在主题中,从而导致数据信息的丢失。这对于某些依赖于链上事件的DAPP(跨链,用户注册等等)来说,可能会导致事件检索困难,需要解析哈希值。

2.2 数据 data

事件中不带 indexed的参数会被存储在 data 部分中,可以理解为事件的“值”。data 部分的变量不能被直接检索,但可以存储任意大小的数据。因此一般 data 部分可以用来存储复杂的数据结构,例如数组和字符串等等,因为这些数据超过了256比特,即使存储在事件的 topics 部分中,也是以哈希的方式存储。另外,data 部分的变量在存储上消耗的gas相比于 topics 更少。

三、演示

3.1 代码示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract Events {// 定义_balances映射变量,记录每个地址的持币数量mapping(address => uint256) public _balances;// 定义Transfer event,记录transfer交易的转账地址,接收地址和转账数量event Transfer(address indexed from, address indexed to, uint256 value);// 定义_transfer函数,执行转账逻辑function _transfer(address from,address to,uint256 amount) external {_balances[from] = 10000000; // 给转账地址一些初始代币_balances[from] -=  amount; // from地址减去转账数量_balances[to] += amount; // to地址加上转账数量// 释放事件emit Transfer(from, to, amount);}
}

3.2 Remix演示

Event.sol 合约为例,编译部署。

然后调用 _transfer 函数。

在这里插入图片描述

点击右侧的交易查看详情,可以看到日志的具体内容。

在这里插入图片描述

3.3 在Etherscan上查询事件

我们尝试用_transfer()函数在Sepolia测试网络上转账100代币,可以在Etherscan上查询到相应的tx:网址。

点击Logs按钮,就能看到事件明细:

在这里插入图片描述
Topics里面有三个元素,[0]是这个事件的哈希,[1][2]是我们定义的两个indexed变量的信息,即转账的转出地址和接收地址。Data里面是剩下的不带indexed的变量,也就是转账数量。

四、总结

这一讲,我们介绍了如何使用和查询Solidity中的事件。很多链上分析工具包括NansenDune Analysis都是基于事件工作的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com