Contract Event
合約 Event
當 Function 涉及改變合約狀態時,通常會 emit event, 讓鏈下系統知道發生了什麼事情。
為什麼智能合約需要 Event?如果只用 storage 儲存資料有什麼問題?
如果沒有 Event 只能看到 Storage 的最終結果,看不到過程與意圖。例如交易所要如何知道有錢打進來,如果沒有 Event 的話就必須不斷的向鏈上詢問目前的餘額狀態,就算知道餘額還需要知道是從哪個地址打進來的。所以 Evnet 就是一個能夠快速及方便搜尋的設計
如果只用 storage 儲存資料有什麼問題?
Storage 會記錄目前的狀態,只能知道結果,如果用 Storage 儲存 Event 資料會過於龐大。
Event 最多可以有幾個 indexed 參數?為什麼有這個限制?
Event 最多可以有3個 Indexed 參數,emit event 之後,為了方便查詢會變成 log 並放進 Receipt ,架構會是
1 | { |
Indexed 參數會放在 Topics,之後節點會把事件的 Contract Address 以及所有 Topics丟進一個 2048 bits(256 bytes)的 Bloom filter 裡。這個 Bloom filter 會同時存在於每一筆 Receipt 以及區塊 header(logsBloom 欄位),用來做快速初篩,查詢事件時,先用相同方式把想找的 Address / Topic hash 成 3 個 bit 位置,檢查這幾個 bit 在 Bloom 裡是不是都為 1,如果有任一個是 0,就可以直接確認,這個區塊絕對沒有我要的 log,不用把整個區塊下載回來逐筆掃描,就跳過。如果都為 1,則可能有,這時才進一步載入該區塊的所有 receipts,對 logs 做查詢。由於 Bloom filter 的長度有限,如果開放太多 indexed 會失去查詢的效果。
Topic[0] 是什麼?Event “Transfer(address,address,uint256)” 的 topic[0] 如何計算?
topics[0]是function signature 經過keccak256 不包含參數名稱,不加空格。
1 | keccak256(Transfer(address,address,uint256)) == a9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b |
Indexed 和 Non-Indexed 參數有什麼不同?分別存在哪裡?
Indexed 儲存在 topics ,由於 Bloom filter 的關係只能放四個。
Non-Indexed 放在 Data,無法查詢。
如何快速過濾特定合約的特定事件?
計算 Topic0 -> 計算 Indexed ->用 Bloom 快速排除不相關 block -> 對可能有的 Block ,掃 Transaction Receipts 的 logs
Etherscan 如何知道 Event 的參數名稱?它從哪裡取得這些資訊?
透過合約ABI,從 Verify Contract拿到資訊
如果沒有ABI?
沒有ABI可以透過下面這個網站收尋 Event-Signatures