Solidity

過濾事件總是返回主題

  • October 25, 2022

我的契約中有一個事件:

event CreatedUnfinishedRandomSVG(uint256 indexed tokenId, address nftOwner, uint256[] randomWords);

在我的 JS 腳本中,我僅在發出與此 tokenId 匹配的事件時才嘗試執行一些程式碼。這就是我過濾此事件的方式(安全帽、乙太幣、合約稱為 RandomSvg):

// Get contract object so we can get address
 let randomSVGObject = await get("RandomSVG");
 let randomSvgAddress = randomSVGObject.address;

 // Get the RandomSVG contract factory
 const randomSvgFactory = await ethers.getContractFactory("RandomSVG");
 const randomSvgInterface = randomSvgFactory.interface;

 // Get signer
 const accounts = await hre.ethers.getSigners();
 const signer = accounts[0];

 // Create a new randomSVG Contract instance
 const randomSvg = new ethers.Contract(
   randomSvgAddress,
   randomSvgInterface,
   signer
 );

.... call function on RandomSvg that emits the below event....

// Filter for event
const events = randomSvg.filters.CreatedUnfinishedRandomSVG(tokenId);

以上,tokenId取自交易收據中的一個事件。this 的值始終為 1,並且我已經檢查過合約中再也沒有tokenId’ 了(例如 2、3、4 等,創建 的程式碼tokenId只被呼叫一次)。

當我執行它並列印events時,我得到以下輸出:

{"address":"0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9","topics":["0x26cb4155602d63931f31f118192ad576866bf5df054834c85516a4273134bd1e","0x0000000000000000000000000000000000000000000000000000000000000001"]}

據我了解,topics數組中的第一個元素是事件簽名的雜湊(https://docs.ethers.io/v5/concepts/events/#events-solidity)。以下元素是索引參數,所以在這種情況下,它tokenId等於 1。0x0000000000000000000000000000000000000000000000000000000000000001等於 1,所以這是有道理的。

但是,如果我在我的 JS 腳本中執行它:

const events = randomSvg.filters.CreatedUnfinishedRandomSVG(9999);

我明白了:

{"address":"0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9","topics":["0x26cb4155602d63931f31f118192ad576866bf5df054834c85516a4273134bd1e","0x000000000000000000000000000000000000000000000000000000000000270f"]}

如果我們將主題 ( 0x000000000000000000000000000000000000000000000000000000000000270f) 的第一個元素轉換為十進制數,我們得到 9999。這對我來說毫無意義……

我的 JS 程式碼聲明我想過濾等於 9999CreatedUnfinishedRandomSVG的事件。tokenId由於沒有等於 9999的事件CreatedUnfinishedRandomSVG,所以tokenId這肯定應該返回 null 嗎?

這使得無法確定是否存在具有特定索引值的事件,因為無論tokenId您傳遞什麼進行過濾,您總是會得到結果???

這是什麼原因?為什麼會這樣?我如何確定是否已發出具有特定值的事件?

附加資訊:

如果我執行:

const events = randomSvg.filters.CreatedUnfinishedRandomSVG();

我得到:

{"address":"0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9","topics":["0x26cb4155602d63931f31f118192ad576866bf5df054834c85516a4273134bd1e"]}

這只是主題雜湊…

有了這個:

// Filter for event
const events = randomSvg.filters.CreatedUnfinishedRandomSVG(tokenId);

您還沒有過濾事件,而只是製作過濾器(這是您看到的對象)。

要過濾來自區塊鏈的實際實時事件:

const filter = randomSvg.filters.CreatedUnfinishedRandomSVG(tokenId);
provider.on(filter, (log, event) => {
   console.log(log)
   // ...
})

而是顯示收據中的事件:

const tx = ...   // our transaction
const receipt = await tx.wait();
for (let i=0; i<receipt.logs.length; i++) {
       if (receipt.logs[i].address == filter.address) {
           if (receipt.logs[i].topics[0] == filter.topics[0]) {
               console.log(receipt.logs[i])
           }
       }
   }

我不認為有過濾這些的方法,但沒有什麼是你不能通過嵌套一些ifs 來做的!

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