or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

artifact-management.mdconfiguration.mdhook-system.mdindex.mdnetwork-management.mdplugin-system.mdsolidity-build-system.mdtask-management.mdutilities.md
tile.json

hook-system.mddocs/

Hook System

Hardhat's hook system provides an event-driven architecture for plugin lifecycle management and extensibility, allowing plugins to register handlers for various system events with type safety and proper context management.

Capabilities

Hook Manager

Central interface for hook registration and execution.

interface HookManager {
  /** Add a hook handler for a specific hook */
  addHookHandler<T extends keyof HardhatHooks>(
    hookName: T,
    handler: HookHandler<T>
  ): void;
  
  /** Run a hook with arguments */
  runHook<T extends keyof HardhatHooks>(
    hookName: T,
    ...args: Parameters<HardhatHooks[T]>
  ): Promise<any>;
  
  /** Check if a hook has handlers */
  hasHandlers<T extends keyof HardhatHooks>(hookName: T): boolean;
  
  /** Get all registered hook names */
  getHookNames(): string[];
}

type HookHandler<T extends keyof HardhatHooks> = HardhatHooks[T];

Usage Examples:

import { hooks } from "hardhat";

// Add a configuration hook handler
hooks.addHookHandler("config.resolveUserConfig", async (userConfig, context) => {
  // Modify user configuration before it's processed
  return {
    ...userConfig,
    paths: {
      ...userConfig.paths,
      sources: "./custom-contracts"
    }
  };
});

// Add HRE initialization hook
hooks.addHookHandler("hre.initialized", async (hre, context) => {
  console.log(`HRE initialized for network: ${hre.network.name}`);
});

// Run a hook manually
await hooks.runHook("hre.beforeTaskRun", taskName, taskArgs);

Hook Categories

Complete hook system with all available hook categories and their specific hooks.

interface HardhatHooks {
  /** Configuration-related hooks */
  config: ConfigHooks;
  
  /** User interruption handling hooks */
  userInterruptions: UserInterruptionHooks;
  
  /** Configuration variable resolution hooks */
  configurationVariables: ConfigurationVariableHooks;
  
  /** Hardhat Runtime Environment lifecycle hooks */
  hre: HardhatRuntimeEnvironmentHooks;
}

Configuration Hooks

Hooks for customizing configuration resolution and processing.

interface ConfigHooks {
  /** Called when resolving user configuration */
  resolveUserConfig: (
    userConfig: HardhatUserConfig,
    context: ConfigHookContext
  ) => Promise<HardhatUserConfig>;
  
  /** Called after configuration is fully resolved */
  configResolved: (
    config: HardhatConfig,
    context: ConfigHookContext
  ) => Promise<void>;
  
  /** Called when configuration validation occurs */
  validateConfig: (
    config: HardhatConfig,
    context: ConfigHookContext
  ) => Promise<void>;
}

interface ConfigHookContext {
  /** Path to the configuration file */
  configPath?: string;
  
  /** Global options passed to Hardhat */
  globalOptions: GlobalOptions;
}

HRE Lifecycle Hooks

Hooks for Hardhat Runtime Environment lifecycle events.

interface HardhatRuntimeEnvironmentHooks {
  /** Called when HRE is initialized */
  initialized: (
    hre: HardhatRuntimeEnvironment,
    context: HookContext
  ) => Promise<void>;
  
  /** Called before a task is run */
  beforeTaskRun: (
    taskName: string,
    taskArguments: TaskArguments,
    context: HookContext
  ) => Promise<void>;
  
  /** Called after a task completes successfully */
  afterTaskRun: (
    taskName: string,
    taskArguments: TaskArguments,
    result: any,
    context: HookContext
  ) => Promise<void>;
  
  /** Called when a task fails */
  taskFailed: (
    taskName: string,
    taskArguments: TaskArguments,
    error: Error,
    context: HookContext
  ) => Promise<void>;
  
  /** Called before HRE is destroyed */
  beforeDestroy: (
    hre: HardhatRuntimeEnvironment,
    context: HookContext
  ) => Promise<void>;
}

Configuration Variable Hooks

Hooks for customizing configuration variable resolution.

interface ConfigurationVariableHooks {
  /** Called when resolving a configuration variable */
  resolve: (
    variable: ConfigurationVariable,
    context: ConfigVarHookContext
  ) => Promise<string | undefined>;
  
  /** Called to validate a resolved configuration variable */
  validate: (
    variable: ConfigurationVariable,
    value: string,
    context: ConfigVarHookContext
  ) => Promise<boolean>;
  
  /** Called when configuration variable resolution fails */
  resolutionFailed: (
    variable: ConfigurationVariable,
    error: Error,
    context: ConfigVarHookContext
  ) => Promise<void>;
}

interface ConfigVarHookContext {
  /** The HRE instance */
  hre: HardhatRuntimeEnvironment;
  
  /** Additional context data */
  data?: any;
}

User Interruption Hooks

Hooks for handling user interruptions and graceful shutdown.

interface UserInterruptionHooks {
  /** Called when user interruption is detected */
  interrupted: (
    interruption: UserInterruption,
    context: HookContext
  ) => Promise<void>;
  
  /** Called before cleanup begins */
  beforeCleanup: (
    interruption: UserInterruption,
    context: HookContext
  ) => Promise<void>;
  
  /** Called after cleanup completes */
  afterCleanup: (
    interruption: UserInterruption,
    context: HookContext
  ) => Promise<void>;
}

interface UserInterruption {
  /** Type of interruption */
  type: "SIGINT" | "SIGTERM" | "uncaughtException" | "unhandledRejection";
  
  /** Interruption signal or error */
  signal?: NodeJS.Signals;
  error?: Error;
  
  /** Timestamp when interruption occurred */
  timestamp: Date;
}

Hook Context

Context object passed to most hook handlers providing access to HRE functionality.

type HookContext = Omit<HardhatRuntimeEnvironment, "tasks">;

interface HookContextWithTasks extends HookContext {
  tasks: TaskManager;
}

Hook Registration Patterns

Common patterns for registering hooks in plugins.

Usage Examples:

// In a plugin file
import type { HardhatPlugin } from "hardhat/types";

const plugin: HardhatPlugin = {
  id: "my-plugin",
  hookHandlers: {
    config: () => import("./hook-handlers/config.js"),
    hre: () => import("./hook-handlers/hre.js"),
    configurationVariables: () => import("./hook-handlers/config-vars.js")
  },
  npmPackage: "my-hardhat-plugin"
};

// In hook-handlers/config.js
export async function resolveUserConfig(userConfig, context) {
  return {
    ...userConfig,
    // Add plugin-specific configuration
    myPlugin: {
      enabled: true,
      customPath: "./my-plugin"
    }
  };
}

export async function configResolved(config, context) {
  console.log(`Configuration resolved for ${context.configPath}`);
}

// In hook-handlers/hre.js
export async function initialized(hre, context) {
  // Add custom properties to HRE
  hre.myPluginApi = {
    doSomething: () => console.log("Plugin functionality")
  };
}

export async function beforeTaskRun(taskName, taskArgs, context) {
  if (taskName === "compile") {
    console.log("About to compile contracts");
  }
}

Hook Execution Order

Hook handlers are executed in the order they were registered, allowing plugins to depend on each other's modifications.

interface HookExecutionInfo {
  /** Order in which the hook was registered */
  registrationOrder: number;
  
  /** Plugin that registered the hook */
  pluginId: string;
  
  /** Whether the hook is async */
  isAsync: boolean;
}