solidity: event机制
以太坊的事件(Event)机制是一种在智能合约中定义和触发事件的方式,用于实现合约与外部世界的通信和提供交易的可追溯性。事件机制可以让智能合约在特定条件满足时触发事件,并将相关信息记录在以太坊区块链上的日志中。
以下是以太坊事件机制的主要特点和使用方法:
-
定义事件:在 Solidity 合约中使用
event
关键字来定义事件。事件的定义包括事件名称和事件参数列表。例如:solidityevent Transfer(address indexed from, address indexed to, uint256 value); ``` 上述示例定义了一个名为 "Transfer" 的事件,包含三个参数:`from`、`to` 和 `value`。
-
触发事件:在合约中的适当位置使用
emit
关键字来触发事件。例如,在转账函数中触发 "Transfer" 事件:solidityfunction transfer(address to, uint256 value) public { // 执行转账逻辑 emit Transfer(msg.sender, to, value); } ``` 通过 `emit` 关键字,合约可以触发事件并传递事件参数的值。
-
事件参数:事件可以包含多个参数,每个参数可以具有不同的类型。事件参数可以用于记录和传递各种信息,如地址、整数、字符串等。事件参数还可以使用
indexed
关键字来标记为索引参数,以便更高效地进行事件过滤和搜索。 -
事件日志:当合约触发事件时,事件及其参数将被记录在以太坊区块链上的事件日志中。事件日志是一种特殊的数据结构,它包含了事件的名称、参数值和其他元数据。事件日志可以通过交易收据(transaction receipt)或以太坊区块链上的事件查询来访问和检索。
-
事件监听:DApp或其他外部系统可以监听合约的事件,以便在事件触发时采取相应的操作。通过监听事件,可以实现实时数据更新、用户界面的反馈、通知和其他与合约交互相关的功能。
以太坊的事件机制为智能合约提供了一种与外部世界通信的机制,使得合约的状态变化和重要事件能够被记录、检索和响应。事件机制在构建去中心化应用程序(DApp)和与智能合约集成的外部系统中非常有用,可以提供更好的用户体验和数据可追溯性。
以太坊的日志(Log)也是上链的,它们会被记录在以太坊区块链上。
当合约触发一个事件并记录日志时,该日志会被包含在合约交易的交易收据(transaction receipt)中,并且该交易将被打包到一个区块中。区块链上的每个节点都会验证和存储这个区块,从而将日志信息永久地记录在区块链中。
通过区块链的去中心化特性,以太坊日志具有以下特点:
-
不可篡改性:一旦日志被记录在区块链上,它们就无法更改或删除。这确保了事件的可追溯性和真实性。
-
可验证性:任何人都可以通过访问以太坊区块链上的交易收据,验证特定合约事件的发生和相关信息。
-
公开透明:以太坊区块链上的日志是公开可见的,任何人都可以查看和分析日志信息。
-
事件驱动的编程:以太坊日志为智能合约提供了事件驱动的编程模型。DApp或其他外部系统可以监听合约的事件,并根据事件触发执行相应的操作。
需要注意的是,以太坊的日志是一种存储数据的机制,而并非用于执行智能合约的代码逻辑。日志通常用于记录合约内部发生的事件和状态变化,以及与外部世界的通信。
我们写个例子来看下event的机制:
合约代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract FallbackLogContract {
event Basiya(string funName, address from, uint256 value, bytes data);
receive() external payable {
emit Basiya("receive", msg.sender, msg.value, "");
}
}
定义了一个接收以太币的函数receive,内部调用一个Basiya的event:
我们给该合约发起1个以太币交易试试:
我们来看下具体的交易以及日志:
[vm]from: 0x5B3...eddC4to: FallbackLogContract.(receive) 0x049...A1Fd3value: 1000000000000000000 weidata: 0xlogs: 1hash: 0x6b7...03df8
status true Transaction mined and execution succeed
transaction hash 0x6b79ee5deb7fa0e6a7ed4e6cbb99476aa36af3ca1e01c8d24ffc1e44fa003df8
block hash 0xaf99efc80bfefb9793678e51bb880aaf0a7fbc8f76ffc6e78862a7990cd9a005
block number 30
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to FallbackLogContract.(receive) 0x0498B7c793D7432Cd9dB27fb02fc9cfdBAfA1Fd3
gas 27927 gas
transaction cost 24284 gas
execution cost 3284 gas
input 0x
decoded input -
decoded output -
logs [
{
"from": "0x0498B7c793D7432Cd9dB27fb02fc9cfdBAfA1Fd3",
"topic": "0xc35d6c22b7aaa1306d99950e95c973a1e0d6e6d6668b2e560df6153bec9e9fbc",
"event": "Basiya",
"args": {
"0": "receive",
"1": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
"2": "1000000000000000000",
"3": "0x",
"funName": "receive",
"from": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
"value": "1000000000000000000",
"data": "0x"
}
}
]
val 1000000000000000000 wei
可以看到logs那边有个event:Basiya, args里面的参数就是我们函数的内容:funName, from, value, data等 以及receive的参数信息