or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

argument-utilities.mdbalance-matchers.mdbignumber-support.mdevent-matchers.mdindex.mdpanic-codes.mdrevert-matchers.mdvalidation-matchers.md
tile.json

tessl/npm-nomicfoundation--hardhat-chai-matchers

Ethereum-specific Chai assertion matchers for smart contract testing in Hardhat development environment.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@nomicfoundation/hardhat-chai-matchers@2.1.x

To install, run

npx @tessl/cli install tessl/npm-nomicfoundation--hardhat-chai-matchers@2.1.0

index.mddocs/

Hardhat Chai Matchers

Hardhat Chai Matchers extends the Chai assertion library with Ethereum-specific capabilities for smart contract testing. It provides specialized matchers for testing transaction reverts, event emissions, balance changes, and Ethereum-specific data validation, making smart contract tests more readable and comprehensive.

Package Information

  • Package Name: @nomicfoundation/hardhat-chai-matchers
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @nomicfoundation/hardhat-chai-matchers

Core Imports

// Import the plugin in your Hardhat configuration
require("@nomicfoundation/hardhat-chai-matchers");

// Import utilities for argument matching
import { anyValue, anyUint } from "@nomicfoundation/hardhat-chai-matchers/withArgs";

// Import panic codes for revert testing  
import { PANIC_CODES } from "@nomicfoundation/hardhat-chai-matchers/panic";

Basic Usage

import { expect } from "chai";
import { ethers } from "hardhat";

// After importing the plugin, new matchers are available on Chai expectations
describe("Token Contract", function () {
  it("should transfer tokens", async function () {
    const [owner, recipient] = await ethers.getSigners();
    const Token = await ethers.getContractFactory("Token");
    const token = await Token.deploy(1000000);

    // Test successful transfer and event emission
    await expect(token.transfer(recipient.address, 1000))
      .to.emit(token, "Transfer")
      .withArgs(owner.address, recipient.address, 1000);

    // Test balance changes
    await expect(token.transfer(recipient.address, 500))
      .to.changeTokenBalance(token, recipient, 500);
  });

  it("should handle reverts", async function () {
    // Test transaction reverts with specific reasons
    await expect(token.transfer(ethers.ZeroAddress, 1000))
      .to.be.revertedWith("Cannot transfer to zero address");

    // Test custom error reverts
    await expect(token.transferFrom(owner.address, recipient.address, 1000))
      .to.be.revertedWithCustomError(token, "InsufficientAllowance");
  });
});

Architecture

Hardhat Chai Matchers is built around extending Chai's assertion interface with Ethereum-specific matchers:

  • Chai Extensions: All matchers extend the global Chai.Assertion interface via TypeScript declaration merging
  • Async Matchers: Most matchers return AsyncAssertion promises for testing transaction results
  • Chainable Interface: Some matchers like .emit() and .revertedWithCustomError() support chaining with .withArgs()
  • Integration Layer: Seamless integration with Hardhat, ethers.js, and Chai testing framework

Capabilities

Transaction Revert Testing

Comprehensive matchers for testing different types of transaction failures including generic reverts, reason strings, custom errors, and panic conditions.

interface Assertion {
  reverted: AsyncAssertion;
  revertedWith(reason: string | RegExp): AsyncAssertion;
  revertedWithoutReason(): AsyncAssertion;
  revertedWithPanic(code?: any): AsyncAssertion;
  revertedWithCustomError(contract: { interface: any }, customErrorName: string): CustomErrorAssertion;
}

Transaction Revert Testing

Event Emission Testing

Matchers for verifying that transactions emit specific events with expected arguments, supporting complex event validation scenarios.

interface Assertion {
  emit(contract: any, eventName: string): EmitAssertion;
}

interface EmitAssertion extends AsyncAssertion {
  withArgs(...args: any[]): AsyncAssertion;
}

Event Emission Testing

Balance Change Testing

Matchers for testing ETH and ERC-20 token balance changes during transaction execution, supporting both single and multiple account scenarios.

interface Assertion {
  changeEtherBalance(account: any, balance: any, options?: any): AsyncAssertion;
  changeEtherBalances(accounts: any[], balances: any[] | ((changes: bigint[]) => boolean), options?: any): AsyncAssertion;
  changeTokenBalance(token: any, account: any, balance: any): AsyncAssertion;
  changeTokenBalances(token: any, accounts: any[], balances: any[] | ((changes: bigint[]) => boolean)): AsyncAssertion;
}

Balance Change Testing

Data Validation

Matchers for validating Ethereum-specific data formats including addresses, private keys, and hex strings.

interface Assertion {
  hexEqual(other: string): void;
  properPrivateKey: void;
  properAddress: void;
  properHex(length: number): void;
}

Data Validation

Argument Matching Utilities

Helper functions for flexible argument matching in event and error testing scenarios.

function anyValue(): boolean;
function anyUint(i: any): boolean;

Argument Matching Utilities

BigNumber Support

Enhanced comparison operators that support ethers BigInt and other BigNumber types alongside regular JavaScript numbers.

interface NumericComparison {
  within(start: any, finish: any, message?: string): Assertion;
}

// Enhanced operators: equal, above, below, least, most, closeTo
// All support BigInt/BigNumber comparisons automatically

BigNumber Support

Panic Codes

Constants and utilities for testing Solidity panic conditions and arithmetic errors.

const PANIC_CODES: {
  ASSERTION_ERROR: 0x1;
  ARITHMETIC_OVERFLOW: 0x11;
  DIVISION_BY_ZERO: 0x12;
  ENUM_CONVERSION_OUT_OF_BOUNDS: 0x21;
  INCORRECTLY_ENCODED_STORAGE_BYTE_ARRAY: 0x22;
  POP_ON_EMPTY_ARRAY: 0x31;
  ARRAY_ACCESS_OUT_OF_BOUNDS: 0x32;
  TOO_MUCH_MEMORY_ALLOCATED: 0x41;
  ZERO_INITIALIZED_VARIABLE: 0x51;
};

Panic Codes

Types

interface AsyncAssertion extends Assertion, Promise<void> {}

interface EmitAssertion extends AsyncAssertion {
  withArgs(...args: any[]): AsyncAssertion;
}

interface CustomErrorAssertion extends AsyncAssertion {
  withArgs(...args: any[]): AsyncAssertion;
}