事件日志记录¶
Vyper 可以将事件记录到用户界面以捕获和显示。
日志记录示例¶
此示例取自示例 ERC20 合约,并展示了事件日志记录的基本流程
# Events of the token.
event Transfer:
sender: indexed(address)
receiver: indexed(address)
value: uint256
event Approval:
owner: indexed(address)
spender: indexed(address)
value: uint256
# Transfer some tokens from message sender to another address
def transfer(_to : address, _value : uint256) -> bool:
... Logic here to do the real work ...
# All done, log the event for listeners
log Transfer(msg.sender, _to, _value)
让我们看看它是如何工作的。
我们声明两种事件类型以进行日志记录。这两个事件类似,因为它们都包含两个索引地址字段。索引字段不构成事件数据本身的一部分,但可以被想要捕获事件的客户端搜索。此外,每个事件都包含一个单一数据字段,在本例中分别称为
value
。事件可以包含多个具有任何所需名称的参数。在
transfer
函数中,在我们完成所有必要的工作之后,我们会记录该事件。我们传递三个参数,对应于 Transfer 事件声明的三个参数。
监听事件的客户端将使用诸如 web3.js 之类的库 来声明和处理它们感兴趣的事件。
var abi = /* abi as generated by the compiler */;
var MyToken = web3.eth.contract(abi);
var myToken = MyToken.at("0x1234...ab67" /* address */);
// watch for changes in the callback
var event = myToken.Transfer(function(error, result) {
if (!error) {
var args = result.returnValues;
console.log('value transferred = ', args._amount);
}
});
在此示例中,监听客户端声明了要监听的事件。只要合约发送此日志事件,就会调用回调函数。
声明事件¶
让我们更详细地了解事件声明。
event Transfer:
sender: indexed(address)
receiver: indexed(address)
value: uint256
事件声明看起来类似于结构声明,包含一个或多个传递给事件的参数。典型的事件将包含两种参数
索引参数,监听者可以搜索这些参数。每个索引参数都由
indexed
关键字标识。在这里,每个索引参数都是一个地址。您可以拥有任意数量的索引参数,但索引参数不会直接传递给监听者,尽管监听者中的results 对象中可能提供一些信息(例如发送者)。值参数,这些参数将传递给监听者。您可以拥有任意数量的值参数,并且它们可以具有任意的名称,但每个参数都受到 EVM 的限制,不能超过 32 字节。
也可以创建一个没有参数的事件。在这种情况下,请使用pass
语句
event Foo: pass
记录事件¶
声明事件后,您可以记录(发送)事件。您可以根据需要多次发送事件。请注意,发送的事件不会占用状态存储,因此不会消耗 gas:这使得事件成为保存某些信息的理想方式。但是,缺点是事件对合约不可用,仅对客户端可用。
记录事件是使用log
语句完成的
log Transfer(msg.sender, _to, _amount)
给定的参数的顺序和类型必须与声明事件时使用的参数顺序匹配。