Hardhat plugin that integrates Hardhat Ignition with ethers.js for declarative smart contract deployment
npx @tessl/cli install tessl/npm-nomicfoundation--hardhat-ignition-ethers@3.0.0Hardhat Ignition Ethers is a Hardhat plugin that integrates Hardhat Ignition with ethers.js, enabling developers to use ethers.js contract instances directly with Hardhat Ignition's declarative smart contract deployment system. The plugin extends network connections with an ignition property that includes a deploy method, allowing users to deploy Ignition modules and receive ethers contract instances for deployed contracts.
npm install --save-dev @nomicfoundation/hardhat-ignition-ethersimport hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers";For CommonJS:
const hardhatIgnitionEthers = require("@nomicfoundation/hardhat-ignition-ethers");Type imports for usage:
import type { EthersIgnitionHelper } from "@nomicfoundation/hardhat-ignition-ethers";
import type {
ChainType,
DefaultChainType,
NetworkConnection
} from "hardhat/types/network";
import type {
IgnitionModule,
IgnitionModuleResult,
DeploymentParameters,
DeployConfig,
StrategyConfig
} from "@nomicfoundation/ignition-core";
import type { Contract } from "ethers";Configure the plugin in your Hardhat configuration:
import hardhatIgnitionEthers from "@nomicfoundation/hardhat-ignition-ethers";
export default {
plugins: [hardhatIgnitionEthers],
};Deploy Ignition modules with ethers contract instances:
import { network } from "hardhat";
import { buildModule } from "@nomicfoundation/ignition-core";
// Define an Ignition module
const CounterModule = buildModule("Counter", (m) => {
const counter = m.contract("Counter");
return { counter };
});
// Deploy and get ethers contract instance
const { ignition } = await network.connect();
const { counter } = await ignition.deploy(CounterModule);
// Use the ethers contract instance
await counter.inc();
console.log(await counter.x());The plugin is built around these key components:
ignition property to network connections via type extensionsThe main plugin export that integrates with Hardhat's plugin system.
interface HardhatPlugin {
id: "hardhat-ignition-ethers";
dependencies: () => Promise<any>[];
hookHandlers: {
network: () => Promise<Partial<NetworkHooks>>;
};
npmPackage: "@nomicfoundation/hardhat-ignition-ethers";
}
declare const hardhatIgnitionEthersPlugin: HardhatPlugin;
export default hardhatIgnitionEthersPlugin;Extends Hardhat's NetworkConnection interface to include the ignition helper and re-exports types from dependencies.
// Re-export all types from dependencies for convenience
export type * from "@nomicfoundation/hardhat-ignition";
export type * from "@nomicfoundation/hardhat-ethers";
// Extend NetworkConnection interface
declare module "hardhat/types/network" {
interface NetworkConnection<
ChainTypeT extends ChainType | string = DefaultChainType
> {
ignition: EthersIgnitionHelper;
}
}The core interface providing deployment functionality with ethers integration.
interface EthersIgnitionHelper {
type: "ethers";
/**
* Deploys the given Ignition module and returns the results as ethers contract instances
* @param ignitionModule - The Ignition module to deploy
* @param options - Deployment configuration options
* @returns Promise resolving to ethers contract instances for each contract in the module
*/
deploy<
ModuleIdT extends string,
ContractNameT extends string,
IgnitionModuleResultsT extends IgnitionModuleResult<ContractNameT>,
StrategyT extends keyof StrategyConfig = "basic"
>(
ignitionModule: IgnitionModule<ModuleIdT, ContractNameT, IgnitionModuleResultsT>,
options?: {
parameters?: DeploymentParameters | string;
config?: Partial<DeployConfig>;
defaultSender?: string;
strategy?: StrategyT;
strategyConfig?: StrategyConfig[StrategyT];
deploymentId?: string;
displayUi?: boolean;
}
): Promise<IgnitionModuleResultsTToEthersContracts<ContractNameT, IgnitionModuleResultsT>>;
}Maps Ignition module results to ethers contract instances.
type IgnitionModuleResultsTToEthersContracts<
ContractNameT extends string,
IgnitionModuleResultsT extends IgnitionModuleResult<ContractNameT>
> = {
[contract in keyof IgnitionModuleResultsT]: IgnitionModuleResultsT[contract] extends
| NamedArtifactContractDeploymentFuture<ContractNameT>
| NamedArtifactContractAtFuture<ContractNameT>
? TypeChainEthersContractByName<ContractNameT>
: Contract;
};
/**
* Placeholder type for TypeChain support (currently maps to ethers Contract)
*/
type TypeChainEthersContractByName<ContractNameT> = Contract;Essential types imported from dependencies for complete API definition.
// These types are imported from their respective packages:
// - IgnitionModule, IgnitionModuleResult, DeploymentParameters, DeployConfig, StrategyConfig from @nomicfoundation/ignition-core
// - NamedArtifactContractDeploymentFuture, NamedArtifactContractAtFuture from @nomicfoundation/ignition-core
// - Contract from ethers
// - ChainType, DefaultChainType, NetworkConnection from hardhat/types/network
// - HardhatPlugin from hardhat/types/pluginsimport { network } from "hardhat";
import { buildModule } from "@nomicfoundation/ignition-core";
const SimpleModule = buildModule("Simple", (m) => {
const token = m.contract("Token", ["My Token", "MTK"]);
return { token };
});
const { ignition } = await network.connect();
const { token } = await ignition.deploy(SimpleModule);
// token is now an ethers Contract instance
console.log(`Token deployed at: ${token.address}`);
const name = await token.name();
console.log(`Token name: ${name}`);import { network } from "hardhat";
import { buildModule } from "@nomicfoundation/ignition-core";
const { ignition } = await network.connect();
// Deploy with custom parameters and configuration
const result = await ignition.deploy(MyModule, {
parameters: {
initialSupply: "1000000",
tokenName: "Advanced Token"
},
config: {
gasPrice: "20000000000",
timeout: 300000
},
defaultSender: "0x1234567890123456789012345678901234567890",
strategy: "basic",
deploymentId: "my-custom-deployment",
displayUi: true
});const ComplexModule = buildModule("Complex", (m) => {
const token = m.contract("Token", ["Test Token", "TEST"]);
const exchange = m.contract("Exchange", [token]);
const tokenAt = m.contractAt("Token", token, { id: "TokenReference" });
return { token, exchange, tokenAt };
});
const { token, exchange, tokenAt } = await ignition.deploy(ComplexModule);
// All returned values are ethers Contract instances
await token.mint(await token.owner(), "1000");
await exchange.setToken(token.address);
console.log(await tokenAt.balanceOf(await token.owner()));The plugin throws HardhatError instances for various failure scenarios:
import { HardhatError } from "@nomicfoundation/hardhat-errors";
try {
const result = await ignition.deploy(MyModule);
} catch (error) {
if (error instanceof HardhatError) {
console.log(`Deployment failed: ${error.message}`);
}
}These packages must be installed alongside the plugin:
hardhat: ^3.0.0@nomicfoundation/hardhat-ethers: ^4.0.0@nomicfoundation/hardhat-ignition: ^3.0.2@nomicfoundation/ignition-core: ^3.0.2ethers: ^6.14.0@nomicfoundation/hardhat-verify: ^3.0.0 (for contract verification)