W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
Solidity 事件在 EVM 的日志記錄功能之上提供了一個抽象。應(yīng)用程序可以通過以太坊客戶端的 RPC 接口訂閱和監(jiān)聽這些事件。
事件是合約的可繼承成員。當(dāng)你調(diào)用它們時,它們會導(dǎo)致參數(shù)存儲在交易日志中——區(qū)塊鏈中的一種特殊數(shù)據(jù)結(jié)構(gòu)。這些日志與合約的地址相關(guān)聯(lián),并入?yún)^(qū)塊鏈中,并在區(qū)塊可訪問時一直存在(從現(xiàn)在開始一直存在,但這可能會隨著 Serenity 而改變)。無法從合約內(nèi)部訪問日志及其事件數(shù)據(jù)(甚至無法從創(chuàng)建它們的合約中訪問)。
可以為日志請求 Merkle 證明,因此如果外部實體提供具有此類證明的合約,它可以檢查日志是否確實存在于區(qū)塊鏈中。你必須提供區(qū)塊頭,因為合約只能看到最后的 256 個區(qū)塊哈希。
您可以將屬性添加indexed到最多三個參數(shù),這會將它們添加到稱為“主題”的特殊數(shù)據(jù)結(jié)構(gòu)中,而不是日志的數(shù)據(jù)部分。一個主題只能包含一個單詞(32 個字節(jié)),因此如果您對索引參數(shù)使用引用類型,則該值的 Keccak-256 哈希值將存儲為主題。
所有沒有該indexed屬性的參數(shù)都被ABI 編碼 到日志的數(shù)據(jù)部分。
主題允許您搜索事件,例如在為某些事件過濾一系列塊時。您還可以按發(fā)出事件的合約地址過濾事件。
例如,下面的代碼使用 web3.jssubscribe("logs") 方法過濾與某個主題與某個地址值匹配的日志:
var options = { fromBlock: 0, address: web3.eth.defaultAccount, topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null] }; web3.eth.subscribe('logs', options, function (error, result) { if (!error) console.log(result); }) .on("data", function (log) { console.log(log); }) .on("changed", function (log) { });
事件簽名的哈希是主題之一,除非您使用說明anonymous符聲明事件。這意味著無法按名稱過濾特定的匿名事件,只能按合約地址過濾。匿名事件的優(yōu)點是部署和調(diào)用成本更低。它還允許您聲明四個索引參數(shù),而不是三個。
筆記
由于事務(wù)日志只存儲事件數(shù)據(jù)而不存儲類型,因此您必須知道事件的類型,包括索引哪個參數(shù)以及事件是否是匿名的,以便正確解釋數(shù)據(jù)。特別是,可以使用匿名事件“偽造”另一個事件的簽名。
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.21 <0.9.0; contract ClientReceipt { event Deposit( address indexed from, bytes32 indexed id, uint value ); function deposit(bytes32 id) public payable { // Events are emitted using `emit`, followed by // the name of the event and the arguments // (if any) in parentheses. Any such invocation // (even deeply nested) can be detected from // the JavaScript API by filtering for `Deposit`. emit Deposit(msg.sender, id, msg.value); } }
JavaScript API 中的使用如下:
var abi = /* abi as generated by the compiler */; var ClientReceipt = web3.eth.contract(abi); var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */); var depositEvent = clientReceipt.Deposit(); // watch for changes depositEvent.watch(function(error, result){ // result contains non-indexed arguments and topics // given to the `Deposit` call. if (!error) console.log(result); }); // Or pass a callback to start watching immediately var depositEvent = clientReceipt.Deposit(function(error, result) { if (!error) console.log(result); });
上面的輸出如下所示(修剪):
{ "returnValues": { "from": "0x1111…FFFFCCCC", "id": "0x50…sd5adb20", "value": "0x420042" }, "raw": { "data": "0x7f…91385", "topics": ["0xfd4…b4ead7", "0x7f…1a91385"] } }
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: