Hardhat's task system provides an extensible architecture for defining, overriding, and executing development operations with argument parsing, validation, and type safety.
Creates new task definitions with description, arguments, and action functions.
/**
* Creates a builder to define a new task
* @param id - Task identifier (string or array of strings)
* @param description - Optional task description
* @returns NewTaskDefinitionBuilder for chaining configuration
*/
function task(
id: string | string[],
description?: string
): NewTaskDefinitionBuilder;
interface NewTaskDefinitionBuilder {
/** Add a positional argument to the task */
addPositionalParam<T extends ArgumentType>(
name: string,
description?: string,
defaultValue?: ArgumentTypeToValueType[T],
type?: T,
isOptional?: boolean
): NewTaskDefinitionBuilder;
/** Add an optional parameter to the task */
addOptionalParam<T extends ArgumentType>(
name: string,
description?: string,
defaultValue?: ArgumentTypeToValueType[T],
type?: T
): NewTaskDefinitionBuilder;
/** Add a required parameter to the task */
addParam<T extends ArgumentType>(
name: string,
description?: string,
defaultValue?: ArgumentTypeToValueType[T],
type?: T
): NewTaskDefinitionBuilder;
/** Add a flag parameter (boolean) to the task */
addFlag(name: string, description?: string): NewTaskDefinitionBuilder;
/** Set the action function for the task */
setAction<ArgsT extends TaskArguments>(
action: NewTaskActionFunction<ArgsT>
): NewTaskDefinitionBuilder;
}Usage Examples:
import { task } from "hardhat/config";
// Simple task
task("hello", "Prints hello world")
.setAction(async (taskArgs, hre) => {
console.log("Hello, World!");
});
// Task with parameters
task("deploy", "Deploy a contract")
.addParam("contract", "The contract name to deploy")
.addOptionalParam("network", "The network to deploy to", "localhost")
.addFlag("verify", "Verify the contract after deployment")
.setAction(async (taskArgs, hre) => {
console.log(`Deploying ${taskArgs.contract} to ${taskArgs.network}`);
if (taskArgs.verify) {
console.log("Will verify after deployment");
}
});Overrides existing task definitions while preserving the ability to call the original implementation.
/**
* Creates a builder to override an existing task
* @param id - Task identifier to override
* @returns TaskOverrideDefinitionBuilder for chaining configuration
*/
function overrideTask(
id: string | string[]
): TaskOverrideDefinitionBuilder;
interface TaskOverrideDefinitionBuilder {
/** Set the override action function */
setAction<ArgsT extends TaskArguments>(
action: OverrideTaskActionFunction<ArgsT>
): TaskOverrideDefinitionBuilder;
}
type OverrideTaskActionFunction<
TaskArgumentsT extends TaskArguments = TaskArguments
> = (
taskArguments: TaskArgumentsT,
hre: HardhatRuntimeEnvironment,
runSuper: (taskArguments?: TaskArgumentsT) => Promise<any>
) => any;Usage Examples:
import { overrideTask } from "hardhat/config";
// Override the compile task
overrideTask("compile")
.setAction(async (taskArgs, hre, runSuper) => {
console.log("Running custom preprocessing...");
// Call the original compile task
const result = await runSuper(taskArgs);
console.log("Post-processing compiled contracts...");
return result;
});Creates empty task placeholders that can be implemented by plugins.
/**
* Creates an empty task definition
* @param id - Task identifier
* @param description - Required task description
* @returns EmptyTaskDefinitionBuilder
*/
function emptyTask(
id: string | string[],
description: string
): EmptyTaskDefinitionBuilder;
interface EmptyTaskDefinitionBuilder {
/** Add parameters to the empty task */
addParam<T extends ArgumentType>(
name: string,
description?: string,
defaultValue?: ArgumentTypeToValueType[T],
type?: T
): EmptyTaskDefinitionBuilder;
}Manages task execution and provides access to task definitions.
interface TaskManager {
/** Execute a task by name with optional arguments */
run(taskName: string, taskArguments?: TaskArguments): Promise<any>;
/** Get a task definition by name */
get(taskName: string): TaskDefinition | undefined;
/** Check if a task exists */
exists(taskName: string): boolean;
/** Get all available task names */
getTaskNames(): string[];
}Usage Examples:
import { tasks } from "hardhat";
// Run a task programmatically
await tasks.run("compile");
// Run with arguments
await tasks.run("deploy", { contract: "MyToken", network: "goerli" });
// Check if task exists
if (tasks.exists("verify")) {
await tasks.run("verify", { contract: "0x123..." });
}Complete task definition structure including metadata and execution details.
interface TaskDefinition {
readonly name: string;
readonly description?: string;
readonly action: TaskActionFunction;
readonly isSubtask: boolean;
readonly paramDefinitions: { [paramName: string]: ParamDefinition };
readonly positionalParamDefinitions: PositionalParamDefinition[];
}
interface ParamDefinition {
name: string;
shortName?: string;
type: ArgumentType;
description?: string;
defaultValue?: any;
isOptional: boolean;
isFlag: boolean;
isVariadic: boolean;
}
interface PositionalParamDefinition {
name: string;
type: ArgumentType;
description?: string;
defaultValue?: any;
isOptional: boolean;
isVariadic: boolean;
}Type definitions for task argument handling and validation.
type TaskArguments = Record<string, any>;
type NewTaskActionFunction<
TaskArgumentsT extends TaskArguments = TaskArguments
> = (taskArguments: TaskArgumentsT, hre: HardhatRuntimeEnvironment) => any;
type TaskActionFunction = (
taskArguments: TaskArguments,
hre: HardhatRuntimeEnvironment,
runSuper?: (taskArguments?: TaskArguments) => Promise<any>
) => any;