#hardhat-viem-assertions
This plugin adds an Ethereum-specific assertions library that integrate with viem, making your smart contract tests easy to write and read.
#Installation
This plugin is part of the Viem Hardhat Toolbox. If you are using that toolbox, there's nothing else you need to do.
To install this plugin, run the following command:
npm install --save-dev @nomicfoundation/hardhat-viem-assertions
In your hardhat.config.ts
file, import the plugin and add it to the plugins
array:
import hardhatViemAssertions from "@nomicfoundation/hardhat-viem-assertions";
export default {
plugins: [hardhatViemAssertions],
};
#Usage
You don't need to do anything else to use this plugin. The viem
object added by the hardhat-viem plugin is expanded with an assertions
property that contains the assertions library.
Here is an example of using the balancesHaveChanged
assertion:
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 assertions are included to check 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 assertion 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],
);
This assertion can take predicate functions to match some of the arguments:
await viem.assertions.revertWithCustomErrorWithArgs(
contract.read.revertWithCustomErrorWithUintAndString([1n, "test"]),
contract,
"CustomErrorWithUintAndString",
[(arg: bigint) => arg === 1n, "test"],
);
import { anyValue } from "@nomicfoundation/hardhat-toolbox-viem/predicates";
await viem.assertions.revertWithCustomErrorWithArgs(
contract.read.revertWithCustomErrorWithUintAndString([1n, "test"]),
contract,
"CustomErrorWithUintAndString",
[1n, anyValue],
);
#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"],
);
This assertion can take predicate functions to match some of the arguments:
await viem.assertions.emitWithArgs(
contract.write.emitTwoUints([1n, 2n]),
contract,
"WithTwoUintArgs",
[1n, (arg: bigint) => arg >= 2],
);
import { anyValue } from "@nomicfoundation/hardhat-toolbox-viem/predicates";
await viem.assertions.emitWithArgs(
contract.write.emitTwoUints([1n, 2n]),
contract,
"WithTwoUintArgs",
[anyValue, 2n],
);
#Balance change
These assertions can be used to check 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,
},
],
);