EVM有一个日志功能,用于将数据“写”到智能合约之外的数据结构中。其中一个重要的数据是Solidity事件。事件允许我们“打印”在区块链上的信息,这种方式比在智能合约中保存到公共存储变量更容易搜索,且更省gas费。
当被发送事件(调用)时,会触发参数存储到交易的日志中(一种区块链上的特殊数据结构)。这些日志与合约的地址关联,并记录到区块链中.
Solidity event,在更通用的以太坊和 EVM 中称为logs,Solidity中的事件(event)是EVM上日志的抽象。日志是指事件保存在区块链上的数据。事件强调操作行为,日志强调存储内容。
以太坊中的Events和Logs基本上算是同一个概念。Solidity和web3.js中称为Events,以太坊黄皮书中称为Logs。可以理解为:以太坊通过Logs实现Events(事件)功能。智能合约代码通过LOG 将日志写入区块链中。
事件Event的作用的可以总结为以下几点:
事件有 3 中主要的使用场景
日志内容是交易收据(Transaction Receipts)的一部分,整个日志内容,包括Receipts的其它内容会生成一个ReceiptsRoot存储在区块的头部。而完整数据则是链下存储。
以太坊交易信息及event、input、logs、topics等概念机制
参考URL: https://learnblockchain.cn/article/3274
当上述事件在合约中调用后,我们通过其交易hash获取交易信息。从以太坊得到一条交易信息的方式有两种:
eth_getTransactionByHash 返回的具体信息如下
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528",
"blockNumber": "0xd19505",
"from": "0xb8262c6a2dcabd92a77df1d5bd074afd07fc5829",
"gas": "0x10e3d",
"gasPrice": "0x274daee580",
"maxFeePerGas": "0x2d48ddd9f1",
"maxPriorityFeePerGas": "0x6ccc91d0",
"hash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36",
"input": "0xa9059cbb000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000016512c902",
"nonce": "0x14",
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionIndex": "0x71",
"value": "0x0",
"type": "0x2",
"accessList": [],
"chainId": "0x1",
"v": "0x1",
"r": "0xa1d7455286525df11602aab34e9e8ab21b092e2c7853a0d6beca0dfb2a78b2e8",
"s": "0x75a485b8c378173a829b27a2e55312311fdb33c68ae65f4c74e5f9cc0a748e0d"
}
}
eth_getTransactionReceipt
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528",
"blockNumber": "0xd19505",
"contractAddress": null,
"cumulativeGasUsed": "0x6c847e",
"effectiveGasPrice": "0x274daee580",
"from": "0xb8262c6a2dcabd92a77df1d5bd074afd07fc5829",
"gasUsed": "0xa169",
"logs": [
{
"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000b8262c6a2dcabd92a77df1d5bd074afd07fc5829",
"0x000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7"
],
"data": "0x000000000000000000000000000000000000000000000000000000016512c902",
"blockNumber": "0xd19505",
"transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36",
"transactionIndex": "0x71",
"blockHash": "0xb0d0e3b6c5e59b7b3e7e16701f6d6cb0c3c93487415b03839e88b3f7a241c528",
"logIndex": "0xa0",
"removed": false
}
],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000080000000000000000000000000000000000000000000000000000000000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000004000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000200",
"status": "0x1",
"to": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"transactionHash": "0xae2a33da8396a6bc40e874b0f32b9967113a3dbf071ab1290c44c62d86873d36",
"transactionIndex": "0x71",
"type": "0x2"
}
}
不同于比特币,以太坊作为智能合约平台。每一笔交易作为消息在以太坊虚拟机中执行时,均会获得一个交易回执信息(Receipt)。

getTransaction返回结果中包含input,而getTransactionReceipts返回结果中包含logs。
solidity中,使用关键字event来定义事件,其中参数列表就是需要保存到区块链上的数据。
事件的声明由event关键字开头,然后跟事件名称,括号里面写好事件需要记录的变量类型和变量名。以ERC20代币合约的Transfer事件为例:
event Transfer(address indexed from, address indexed to, uint256 value);
在这个事件中,有两种参数:有索引的和无索引的。索引参数也被称为“主题”,是事件中的可搜索参数。
每个事件最多有3个带indexed的变量,Transfer事件共记录了3个变量from,to和value,分别对应代币的转账地址,接收地址和转账数量。同时from和to前面带着indexed关键字,表示很重要,程序可以轻松的筛选出特定转账地址和接收地址的转账事件。
一个事件可以分解为:
发出事件的合约或账户的地址。 当前交易被调用的合约地址如何来使用事件
在函数内部通过 emit 关键词,后面跟上事件的名称和事件所需的参数(如果有的话)。
如果函数会触发事件,则不能将其定义为view或pure。这是因为触发事件会将数据写入区块链(到日志中)。
匿名事件
在 solidity 中事件可以是匿名的。默认情况下所有的事件都会有一个主题,来自定义时候的函数名称。使用 anonymous 来记录一个没有主题的事件。匿名事件也会成为 ABI 的一部分。
event Message(
address _recipient,
string _message
) anonymous;
如果事件声明为anonymous,在合约 ABI 中,事件的"anonymous"字段将标记为true。
匿名事件的使用成本更低。但是匿名事件不能通过名称去筛选,只能通过合约地址。
web3.js与智能合约交互监听合约事件
参考URL: https://www.b2bchain.cn/8083.html
web3j开发以太坊过滤器(filter)和智能合约事件(event)
参考URL: https://blog.csdn.net/rejames/article/details/81294638
智能合约Solidity教程-事件和日志(一)
参考URL: https://blog.csdn.net/weixin_34252090/article/details/88720360
[强烈推荐,写的很详细]以太坊交易信息及event、input、logs、topics等概念机制
参考URL: https://learnblockchain.cn/article/3274