@Patricio Palladino — September 16, 2025 5:00 PM (GMT-3) — Thanks to @Franco Victorio and Hadrien.

<aside> 💡

This should not be considered a fleshed-out design doc, but rather an intro to a problem, a proposed feature to solve it, and a validation that it’s compatible with the way we define and extend types.

</aside>

Context

Hadrien from Open Zeppelin is building a plugin for Hardhat 3, that pre-deploys some contracts whenever you crate a new simulated network.

He wants to expose those contracts as part of the network connection, and wants them to work with Viem or Ethers, depending on the user preferences.

We have a similar situation in hardhat-ignition, where ignition.deploy() returns different types of contracts abstractions if you are using hardhat-ignition-viem or hardhat-ignition-ethers.

This document presents an idea based on Hadrien’s original proposal, that allows you to have a single plugin (e.g. hardhat-ignition) that conditionally changes its behavior based on the presence of other plugins, by loading subplugins conditionally.

This can potentially improve the DX of every plugin that has to deal with the viem/ethers duality, as to the user only has to think about a single plugin.

Proposal

We should extend the plugin system with a concept of “Conditional DependenciesPlugin”s. The core idea of them is that a plugin should be able to declare other plugins to be conditionally loaded, or not, depending on the existence of other plugins.

Note that plugin dependencies aren’t that, as the dependent plugin forces the dependency to be loaded.

The implementation could look something like this:

conditionalDependencies: [
	{
		// The condition should read as:
    //  - If we can resolve all the imports successfully, and they are
    //    plugins that the user already uses (directly or indirectly) in their
    //    config, then we load the dependency, and add it to the list of plugins.
      condition: () => [import("@nomicfoundation/hardhat-ethers")],
      dependency: () => import("./conditional-plugins/ethers.js"),
    },
    {
      condition: () => [import("@nomicfoundation/hardhat-viem")],
      dependency: () => import("./conditional-plugins/viem.js"),
    },
]

The plugin loaded conditionally doesn’t need any special behavior, it’s just a normal plugin. (PS: See open questions)

Type-extensions

One of the key aspects that this feature would need is the possibility of extending a type depending on the presence of a plugin, or at least simulate that behavior.