跳转至

17.Events

事件

Events allow logging to the Ethereum blockchain. Some use cases for events are:

  • Listening for events and updating user interface
  • A cheap form of storage
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

contract Event {
    // Event declaration
    // Up to 3 parameters can be indexed.
    // Indexed parameters helps you filter the logs by the indexed parameter
    event Log(address indexed sender, string message);
    event AnotherLog();

    function test() public {
        emit Log(msg.sender, "Hello World!");
        emit Log(msg.sender, "Hello EVM!");
        emit AnotherLog();
    }
}

事件是能方便地调用以太坊虚拟机日志功能的接口。应用程序可以通过以太坊客户端的 RPC 接口订阅和监听这些事件。

重点:记录区块链的日志,可以使用状态变量,也可以使用事件 Event,但 Event 使用的 gas 费比状态变量低。

原则:改变状态变量时,一定要触发事件。

Event 语法

事件的定义:使用 event 关键字来定义一个事件 Event,语法如下:

event EventName(<parameter list>);

事件的触发:只能使用 emit 关键字来触发事件 Event,语法如下:

emit EventName(<parameter list>);

四种事件定义方式

  1. 不带参数的 event
  2. 带参数的 event
  3. 带参数名的 event
  4. 带 indexed 参数名的 event
  5. 这种事件也被称为索引事件
  6. 语法:event EventName(TypeName indexed varibleName....);
  7. 事件中 indexed 标记过的参数,可以在链外进行搜索查询。
  8. 一个事件中 indexed 标记过的参数最多有 3 个。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract Event {
    // 普通 event
    event Log1(address, string);

    // 带名字的 event
    event Log2(address ads, string msg);

    // 带 indexed 的event
    event Log3(address indexed ads, string msg);

    // indexed 在一个事件内使用次数不能超过3次
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed amount
    );

    function log1() external {
        emit Log1(msg.sender, "Log111");
    }

    function log2() external {
        emit Log2(msg.sender, "Log222");
    }

    function log3() external {
        emit Log3(msg.sender, "Log333");
    }

    function transfer(address _to, uint256 amount) external {
        emit Transfer(msg.sender, _to, amount);
    }
}

不带参数的 event

[
    {
        "from": "0x7874d94b8f9E2a28FCceCE404666C984f33a82b8",
        "topic": "0x1732d0c17008d342618e7f03069177d8d39391d79811bb4e706d7c6c84108c0f",
        "event": "Log1",
        "args": {}
    }
]

带参数的 event

[
    {
        "from": "0x7874d94b8f9E2a28FCceCE404666C984f33a82b8",
        "topic": "0x54010eb0426bdddd13273086604fca7ba750a84093c6839732d954056646e81b",
        "event": "Log2",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "Log222"
        }
    }
]

带参数名的 event

[
    {
        "from": "0x7874d94b8f9E2a28FCceCE404666C984f33a82b8",
        "topic": "0x940879bf2d29cdfe8084f2f033d2168f5859a6e10530b61fb84dc1c5ddc9ca40",
        "event": "Log3",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "Log333",
            "ads": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "msg": "Log333"
        }
    }
]

带 indexed 参数名的 event

[
    {
        "from": "0xfB72aAdB17a855D27A68B565ee0a84CB30A387e4",
        "topic": "0xf485c071883274befba21423da7f60203f9df753bf614bca26c4763ed4b240fb",
        "event": "Log4",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "Log444",
            "ads": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "msg": "Log444"
        }
    }
]
[
    {
        "from": "0xfB72aAdB17a855D27A68B565ee0a84CB30A387e4",
        "topic": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "event": "Transfer",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "2": "1",
            "from": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "to": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "amount": "1"
        }
    }
]

案例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

contract Event {
    // 事件是合约与外部世界通信的一种方式,通过发出日志条目来与外部应用程序进行通信。
    // 一个event中indexed最多标注三个
    // indexed关键字表示sender参数将包含在日志条目的索引部分中,这使得更容易搜索特定事件。

    event Log(string message, uint256 val);

    // 两个参数:一个名为sender的索引地址和一个名为val的无符号整数。
    event IndexedLog(address indexed sender, uint256 val);

    /**
    函数发出了两个事件:
    Log事件,消息为“foo”,值为1234,
    IndexedLog事件,带有发送方地址和值789。
    **/
    function example() external {
        emit Log("foo", 1234);
        emit IndexedLog(msg.sender, 789);
    }

    event Message(address indexed _from, address indexed _to, string message);

    // 函数发出了一个Message事件,带有发送方地址、接收方地址和消息字符串。
    function sendMessage(address _to, string calldata message) external {
        emit Message(msg.sender, _to, message);
    }
}