Events

使用 hardhat + chai 測試合約事件的參數

  • September 30, 2021

我目前正在使用chaihardhat測試ethereum-waffle我的智能合約:

const chai = require('chai')
const hre = require('hardhat')
const { solidity } = require('ethereum-waffle')

chai.use(solidity)

我一直覺得它很好用。

但是,我在測試事件時遇到了一些困難。我目前使用expect( ... ).to.emit( ... ).withArgs( ... )的適用於很多情況,但不是全部。

從測試中獲取以下範例片段:

const destroyResult = await gameContract.attack([4, 0])

// Expect the game to end with the announced winner being owner
expect(destroyResult)
 .to.emit(gameContract, 'GameEnd')
 .withArgs(undefined, owner.address)

在這個例子中,GameEnd 事件有兩個參數:遊戲結束的時間戳和獲勝者的地址(owner.address上圖)。在我的測試中,我只關心測試第二個參數(誰贏得了比賽)。

我嘗試提供undefined時間戳,但這是不可接受的,並導致測試失敗。我需要的是一種只測試事件的第二個參數的方法。

對於我來說,擁有一個可以訪問事件對象的函式也是可以接受的,這樣我就可以執行我喜歡的任何測試。但是我還沒有看到這樣做的任何方法。

任何幫助將不勝感激,謝謝!

這就是我為 ERC20 代幣的 Transfer 事件執行此操作的方式:

通常 :

await expect(tokenInstance.connect(<signer-account>).transfer(<addr-of-receipent>, <amount-BigNumber>))
.to.emit(tokenInstance, 'Transfer').withArgs(<addr-of-signer-account>, <addr-of-receipent>, <amount-BigNumber>);

這就是您如何獲取所有參數並測試所有參數或其中任何一個的方法:

...
const tx = await tokenInstance.connect(<signer-account>).transfer(<addr-of-receipent>, <amount-BigNumber>);
const receipt = await ethers.provider.getTransactionReceipt(tx.hash);
const interface = new ethers.utils.Interface(["event Transfer(address indexed from, address indexed to, uint256 amount)"]);
const data = receipt.logs[0].data;
const topics = receipt.logs[0].topics;
const event = interface.decodeEventLog("Transfer", data, topics);
expect(event.from).to.equal(<addr-of-signer-account>);
expect(event.to).to.equal(<addr-of-receipent>);
expect(event.amount.toString()).to.equal(<amount-BigNumber>.toString());
...

我在這裡假設只會發出一個事件,因此我得到了日誌數組中的第一個元素logs[0]

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