Hardhat Viem Matchers plugin
This plugin adds an Ethereum-specific matchers assertion library that integrate with viem, making your smart contract tests easy to write and read.
Installation
To install this plugin, run the following command:
npm install --save-dev @nomicfoundation/hardhat-viem-matchers@next
and add the following statements to your hardhat.config.ts
file:
// ...
import viemMatchersPlugin from "@nomicfoundation/hardhat-viem-matchers";
// ...
export default {
// ...
plugins: [
// ...
viemMatchersPlugin,
],
// ...
};
Usage
You don't need to do anything else to use this plugin. Whenever you run your tests with Hardhat, it will automatically add the matchers to the viem
object.
Here is an example of using the balancesHaveChanged
matcher:
const { viem } = await hre.network.connect();
const [bobWalletClient, aliceWalletClient] = await viem.getWalletClients();
await viem.assertions.balancesHaveChanged(
bobWalletClient.sendTransaction({
to: aliceWalletClient.account.address,
value: 3333333333333333n,
}),
[
{
address: aliceWalletClient.account.address,
amount: 3333333333333333n,
},
],
);
Reference
Reverted transactions
Several matchers are included to assert that a transaction reverted, and the reason of the revert.
.revert
Assert that a transaction reverted for any reason, without checking the cause of the revert:
await viem.assertions.revert(token.write.transfer([address, 0n]));
.revertWith
Assert that a transaction reverted with a specific reason string:
await viem.assertions.revertWith(
token.write.transfer([address, 0n]),
"transfer value must be positive",
);
.revertWithCustomError
Assert that a transaction reverted with a specific custom error:
await viem.assertions.revertWithCustomError(
token.write.transfer([address, 0n]),
token,
"InvalidTransferValue",
);
The second argument must be the contract that defines the error. The contract is used to determine the full signature of the expected error. The matcher does not check whether the error was emitted by the contract.
.revertWithCustomErrorWithArgs
Assert that a transaction reverted with a custom error and specific arguments:
await viem.assertions.revertWithCustomErrorWithArgs(
token.write.transfer([address, 0n]),
token,
"InvalidTransferValue",
[0n],
);
Events
.emit
Assert that a transaction emits a specific event:
await viem.assertions.emit(
rocketContract.write.launch(),
rocketContract,
"LaunchEvent",
);
.emitWithArgs
Assert that a transaction emits an event with specific arguments:
await viem.assertions.emitWithArgs(
rocketContract.write.launch(),
rocketContract,
"LaunchEventWithArgs",
["Apollo", "lift-off"],
);
Balance change
These matchers can be used to assert how a given transaction affects the ether balance of a specific address.
.balancesHaveChanged
Assert that a transaction changes the balance of specific addresses:
await viem.assertions.balancesHaveChanged(
bobWalletClient.sendTransaction({
to: aliceWalletClient.account.address,
value: 3333333333333333n,
}),
[
{
address: aliceWalletClient.account.address,
amount: 3333333333333333n,
},
{
address: bobWalletClient.account.address,
amount: -3333333333333333n,
},
],
);