CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ethereum-waffle

Advanced framework for testing smart contracts with enhanced chai matchers, mock contracts, and testing utilities.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

provider-testing.mddocs/

Provider & Testing Utilities

Core testing infrastructure for Ethereum Waffle including MockProvider for local blockchain simulation, pre-funded test accounts, fixtures for efficient test setup, and comprehensive call history tracking.

Capabilities

MockProvider

Enhanced Web3Provider designed specifically for testing, providing isolated blockchain environment with pre-funded accounts, call history tracking, and ENS support.

/**
 * Enhanced Web3Provider for testing with isolated blockchain environment
 * @param options - Configuration options for the provider
 */
class MockProvider extends providers.Web3Provider {
  constructor(options?: MockProviderOptions);
  
  /** Get array of pre-funded test wallets */
  getWallets(): Wallet[];
  
  /** Create new empty wallet without ETH balance */
  createEmptyWallet(): Wallet;
  
  /** Clear all recorded contract calls */
  clearCallHistory(): void;
  
  /** Setup ENS domain resolution for testing */
  setupENS(wallet?: Wallet): Promise<void>;
  
  /** Read-only access to all recorded contract calls */
  readonly callHistory: readonly RecordedCall[];
  
  /** ENS instance if setupENS was called */
  readonly ens: ENS | undefined;
}

interface MockProviderOptions {
  ganacheOptions: EthereumProviderOptions;
}

interface RecordedCall {
  readonly address: string | undefined;
  readonly data: string;
}

Usage Examples:

import { MockProvider } from "ethereum-waffle";

// Create provider with default settings
const provider = new MockProvider();
const [wallet, otherWallet] = provider.getWallets();

// Create provider with custom ganache options
const customProvider = new MockProvider({
  ganacheOptions: {
    gasLimit: 8000000,
    gasPrice: 20000000000
  }
});

// Track contract calls
const contract = await deployContract(wallet, contractJson);
await contract.someFunction();

console.log(provider.callHistory); // Array of RecordedCall objects

// Setup ENS for testing
await provider.setupENS(wallet);
const address = await provider.resolveName('test.eth');

Test Fixtures

Efficient test setup system with automatic blockchain snapshotting and restoration, enabling fast test execution by reusing common setup scenarios.

/**
 * Function type for test fixtures that setup testing environment
 * @param wallets - Array of funded wallets for testing
 * @param provider - MockProvider instance
 * @returns Promise resolving to fixture state
 */
type Fixture<T> = (wallets: Wallet[], provider: MockProvider) => Promise<T>;

/**
 * Load a fixture with automatic snapshotting for test isolation
 * @param fixture - Fixture function to execute and cache
 * @returns Promise resolving to fixture result
 */
function loadFixture<T>(fixture: Fixture<T>): Promise<T>;

/**
 * Create custom fixture loader with specific wallets and provider
 * @param overrideWallets - Custom wallets to use instead of defaults
 * @param overrideProvider - Custom provider to use instead of default
 * @returns Fixture loader function
 */
function createFixtureLoader(
  overrideWallets?: Wallet[], 
  overrideProvider?: MockProvider
): <T>(fixture: Fixture<T>) => Promise<T>;

Usage Examples:

import { loadFixture, MockProvider } from "ethereum-waffle";

// Define a fixture
const myFixture: Fixture<{token: Contract, wallet: Wallet}> = async (wallets, provider) => {
  const [wallet] = wallets;
  const token = await deployContract(wallet, ERC20Json, ["Test Token", "TEST"]);
  await token.mint(wallet.address, 1000);
  return { token, wallet };
};

// Use fixture in tests - automatically cached and snapshot restored
it("should transfer tokens", async () => {
  const { token, wallet } = await loadFixture(myFixture);
  // Test logic here - fresh state each time
});

// Create custom fixture loader
const customLoader = createFixtureLoader(customWallets, customProvider);
const result = await customLoader(myFixture);

Default Test Accounts

Pre-configured test accounts with deterministic private keys and substantial ETH balances for consistent testing.

/**
 * Array of 10 pre-funded test accounts with deterministic private keys
 * Each account has balance: '0x1ED09BEAD87C0378D8E6400000000' (10^34 wei)
 */
const defaultAccounts: Array<{
  balance: string;
  secretKey: string;
}>;

Usage Examples:

import { defaultAccounts, MockProvider } from "ethereum-waffle";

// Access account private keys
const privateKey = defaultAccounts[0].secretKey;
const wallet = new Wallet(privateKey);

// Check account balance (same for all 10 accounts)
console.log(defaultAccounts[0].balance); // '0x1ED09BEAD87C0378D8E6400000000'

// Use with custom provider
const provider = new MockProvider();
const wallets = provider.getWallets(); // Uses defaultAccounts automatically

Call History Tracking

System for recording and analyzing contract function calls during testing, useful for verifying interaction patterns and debugging.

/**
 * Tracks and manages contract call history
 */
class CallHistory {
  /** Clear all recorded calls */
  clear(): void;
  
  /** Get array of all recorded calls */
  getCalls(): RecordedCall[];
  
  /** Wrap provider to record calls */
  record(provider: Provider): Provider;
}

Usage Examples:

import { MockProvider } from "ethereum-waffle";

const provider = new MockProvider();
const [wallet] = provider.getWallets();

// Deploy and interact with contract
const contract = await deployContract(wallet, contractJson);
await contract.setValue(42);
await contract.getValue();

// Check call history
console.log(provider.callHistory.length); // 2
console.log(provider.callHistory[0].data); // Encoded setValue call data

// Clear history for next test
provider.clearCallHistory();

Revert String Utilities

Utilities for extracting and handling revert reasons from failed transactions, providing better debugging information during testing.

/**
 * Extract revert reason string from call revert error
 * @param callRevertError - Error object from failed contract call
 * @returns Decoded revert reason string
 */
function decodeRevertString(callRevertError: any): string;

/**
 * Append revert string to transaction receipt for debugging
 * @param etherProvider - Web3Provider instance
 * @param receipt - Transaction receipt to enhance
 */
function appendRevertString(etherProvider: providers.Web3Provider, receipt: any): Promise<void>;

/**
 * Inject revert string decoding capabilities into provider
 * @param provider - Provider to enhance with revert string support
 * @returns Enhanced provider with revert string decoding
 */
function injectRevertString(provider: Provider): Provider;

Usage Examples:

import { decodeRevertString, MockProvider } from "ethereum-waffle";

const provider = new MockProvider();
const [wallet] = provider.getWallets();

try {
  await contract.requireSomething();
} catch (error) {
  const revertReason = decodeRevertString(error);
  console.log("Revert reason:", revertReason); // "Something is required"
}

// Enhance provider with automatic revert string extraction
const enhancedProvider = injectRevertString(provider);

Custom Fixture Loader

Factory function for creating custom fixture loaders with specific wallets and providers, enabling advanced test setup scenarios.

/**
 * Create custom fixture loader with specific wallets and provider
 * @param overrideWallets - Custom wallets to use instead of defaults
 * @param overrideProvider - Custom provider to use instead of default
 * @returns Fixture loader function
 */
function createFixtureLoader(
  overrideWallets?: Wallet[], 
  overrideProvider?: MockProvider
): <T>(fixture: Fixture<T>) => Promise<T>;

Usage Examples:

import { createFixtureLoader, MockProvider } from "ethereum-waffle";

// Create custom wallets
const customWallets = [
  new Wallet("0x1234..."),
  new Wallet("0x5678...")
];

// Create custom provider with specific options
const customProvider = new MockProvider({
  ganacheOptions: {
    gasLimit: 8000000,
    accounts: customWallets.map(w => ({
      balance: "0x1000000000000000000",
      secretKey: w.privateKey
    }))
  }
});

// Create custom fixture loader
const loadCustomFixture = createFixtureLoader(customWallets, customProvider);

// Use in tests
const myFixture = async (wallets, provider) => {
  const [owner, user] = wallets;
  const contract = await deployContract(owner, ContractJson);
  return { contract, owner, user };
};

const { contract, owner, user } = await loadCustomFixture(myFixture);

Revert String Utilities

Enhanced error handling utilities for extracting and analyzing revert reasons from failed transactions.

/**
 * Extract revert reason string from call revert error
 * @param callRevertError - Error object from failed contract call
 * @returns Decoded revert reason string
 */
function decodeRevertString(callRevertError: any): string;

/**
 * Append revert string to transaction receipt for debugging
 * @param etherProvider - Web3Provider instance
 * @param receipt - Transaction receipt to enhance
 * @returns Promise that resolves when revert string is appended
 */
function appendRevertString(etherProvider: providers.Web3Provider, receipt: any): Promise<void>;

/**
 * Inject revert string decoding capabilities into provider
 * @param provider - Provider to enhance with revert string support
 * @returns Enhanced provider with revert string decoding
 */
function injectRevertString(provider: Provider): Provider;

Usage Examples:

import { decodeRevertString, injectRevertString, MockProvider } from "ethereum-waffle";

const provider = new MockProvider();
const [wallet] = provider.getWallets();

// Manual revert string extraction
try {
  await contract.restrictedFunction();
} catch (error) {
  const revertReason = decodeRevertString(error);
  console.log("Transaction failed:", revertReason);
}

// Automatic revert string enhancement
const enhancedProvider = injectRevertString(provider);

// Enhanced provider automatically includes revert strings in error messages
try {
  const contract = new Contract(address, abi, enhancedProvider);
  await contract.failingFunction();
} catch (error) {
  console.log(error.message); // Includes decoded revert reason
}

TestProvider Type

Type definition for providers enhanced with wallet access, compatible with both MockProvider and other test providers.

/**
 * Provider interface with wallet access for testing
 */
type TestProvider = providers.BaseProvider & {
  /** Get array of test wallets */
  getWallets(): Wallet[];
  
  /** Get L1 fee for transaction (Optimism/L2 networks) */
  getL1Fee?(txHash: string): Promise<BigNumber>;
};

Usage Examples:

import { TestProvider, MockProvider } from "ethereum-waffle";

function setupTest(provider: TestProvider) {
  const wallets = provider.getWallets();
  // Test setup logic
}

const mockProvider = new MockProvider();
setupTest(mockProvider); // TypeScript knows MockProvider implements TestProvider

docs

chai-matchers.md

compiler-utilities.md

contract-deployment.md

ens-utilities.md

index.md

mock-contracts.md

optimism-provider.md

provider-testing.md

tile.json