Solidity

如何將 EthFilter 應用於特定地址?

  • January 11, 2019

在 web3.js 中,我們可以應用如下事件過濾器:

this.event = this.Contract.events.MyEvent({
    filter: { address: "0xAccountAddress" },
})

在 Web3J 中,它被翻譯成

EthFilter eventFilter = new EthFilter(
   DefaultBlockParameterName.LATEST,
   DefaultBlockParameterName.LATEST,
   mContract.getContractAddress()
);
eventFilter.addSingleTopic(EventEncoder.encode(Contract.MY_EVENT));

但是,如何filter在上面 web3.js 範例中的事件中傳遞特定地址?

好的,假設您在地址CONTRACT_ADDRESS上部署了一個智能合約,可以觸發不同類型的事件

事件定義:

event GameStarted(bytes32 indexed gameId, address indexed player1, address indexed player2);
event PlayerMoved(bytes32 indexed gameId, address indexed player);
event GameEnded(bytes32 indexed gameId, address indexed player1, address indexed player2);

在交易期間從智能合約觸發事件時,該事件將添加到事件日誌(區塊鏈全域狀態的一部分)中。可以使用一個或多個過濾器(智能合約地址、塊號範圍、主題)查詢事件日誌。

關鍵字indexed意味著事件將被添加到topics事件日誌中呼叫的特殊資料結構中。因此,可以根據這些事件參數查詢事件日誌。

一個事件定義最多接受三個索引參數。

事件的內部結構如下:

  • address:合約的地址(本質上由乙太坊提供);
  • 話題$$ 0 $$: keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")") (canonical_type_of 是一個簡單地返回給定參數的規範類型的函式,例如對於 uint 索引 foo,它會返回 uint256)。如果事件被聲明為匿名,則主題$$ 0 $$沒有生成;
  • 話題$$ n $$: EVENT_INDEXED_ARGS$$ n - 1 $$(EVENT_INDEXED_ARGS 是被索引的一系列 EVENT_ARGS);
  • data : abi_serialise(EVENT_NON_INDEXED_ARGS) (EVENT_NON_INDEXED_ARGS 是一系列未編入索引的 EVENT_ARGS,abi_serialise 是用於從函式返回一系列類型值的 ABI 序列化函式,如上所述)。

來源

讓我們回到 Java 部分,下面的程式碼展示瞭如何從區塊範圍 [ , ]內的智能合約中僅過濾類型為GameStartedwhere的事件:player2=MY_ADDRESS``CONTRACT_ADDRESS``BLOCK_n``BLOCK_m

EthFilter eventFilter = new EthFilter(
   BLOCK_n, // filter: from block
   BLOCK_m, // filter: to block
   CONTRACT_ADDRESS // filter: smart contract address
);
eventFilter.addSingleTopic(EventEncoder.encode(Contract.GameStarted)); // filter: event type (topic[0])
eventFilter.addOptionalTopics(null, null, MY_ADDRESS); // filter: event parameters (gameId: no filter, player1: no filter, player2: filter)

引用自:https://ethereum.stackexchange.com/questions/65372