How to automate a headache-free deployment with Hardhat Ignition
Hardhat Ignition is a declarative system for deploying smart contracts on Ethereum. It enables you to define smart contract instances you…
Hardhat Ignition is a declarative system for deploying smart contracts on Ethereum. It enables you to define smart contract instances you want to deploy, and any operation you want to run on them. By taking over the deployment and execution, Hardhat Ignition lets you focus on your project instead of getting caught up in the deployment execution details. It’s a better end-to-end deployment experience. To learn more, check out our announcement post.
Let’s get started and look into how you can automate a simple deployment using Hardhat Ignition.
Installation
We’re going to quickly install Hardhat, set up a new project, and install Hardhat Ignition. Skip to the next section if you know how to do this already!
Open a terminal and execute the following commands to set up an NPM project with Hardhat:
mkdir hardhat-ignition-tutorial/
cd hardhat-ignition-tutorial
npm init
npm install --save-dev hardhat
Then run npx hardhat init
, select “Create a TypeScript project” and “yes” in the following steps. Our Hardhat project is now ready, and we’re going to install Hardhat Ignition next. Run:
npm install --save-dev @nomicfoundation/hardhat-ignition
Finally, open the hardhat.config.ts
file and add this line at the top to enable the plugin:
import "@nomicfoundation/hardhat-ignition";
Creating your contract
Paste the following code into contracts/Rocket.sol
:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract Rocket {
string public name;
string public status;
constructor(string memory _name) {
name = _name;
status = "ignition";
}
function launch() public {
status = "lift-off";
}
}
It contains a simple smart contract called Rocket
, featuring a launch
function that we'll call after deployment.
Creating your first module
In Hardhat Ignition, deployments are expressed through Ignition Modules. These modules are defined in JavaScript/Typescript and let you outline and describe the system that you want to deploy.
Modules are declared in JavaScript or Typescript files inside of ignition/modules
. Let's create that folder structure:
mkdir ignition
mkdir ignition/modules
And paste the following code into a ignition/modules/Apollo.ts
. We'll explain it in a moment.
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
export default buildModule("Apollo", (m) => {
const apollo = m.contract("Rocket", ["Saturn V"]);
m.call(apollo, "launch", []);
return { apollo };
});
The first aspect to note is that modules are created by calling the buildModule
function, which requires a module ID and a callback function. Our module will be identified as "Apollo"
.
The callback function is where the module definition actually happens. The m
parameter being passed into the callback is an instance of a ModuleBuilder
, which is an object with methods to define and configure your smart contract instances.
When we call these ModuleBuilder
methods, they create a Future
object, which represents the result of an execution step that Hardhat Ignition needs to run to deploy a contract instance or interact with an existing one.
This doesn't execute anything against the network, it simply represents it internally. After the Future
is created, it gets registered within the module, and the method returns it.
In our module, we created two Future
objects by calling the contract
and call
methods. The initial one instructs Hardhat Ignition to deploy a Rocket
contract instance, specifying "Saturn V"
as the only constructor parameter. The second one indicates that we intend to execute the launch
function of the deployed Rocket
instance, with no arguments provided.
Finally, we return the Future
object representing the Rocket
contract instance, to make it accessible to other modules and tests as well.
Deploying it
Now that our module definition is ready, let's deploy it to a local Hardhat node. Let's start by spinning up a local node:
npx hardhat node
Next, in a separate terminal in the root of your Hardhat project, run:
npx hardhat ignition deploy ignition/modules/Apollo.ts --network localhost
Hardhat Ignition will execute every Future
that we defined in the right order, and display the results:
Hardhat Ignition 🚀
Deploying [ Apollo ]
Batch #1
Executed Apollo#Rocket
Batch #2
Executed Apollo#Rocket.launch
[ Apollo ] successfully deployed 🚀
Deployed Addresses
Apollo#Rocket - 0x5fbdb2315678afecb367f032d93f642f64180aa3
An ignition/deployments/chain-31337
folder will have been created. It contains all the details about your deployment. Hardhat Ignition uses this data to recover from errors, resume a modified deployment, and more.
That's all it takes to define and execute a deployment using Hardhat Ignition!
Check it out
For an in-depth guide on everything you can express with modules, see Creating Ignition Modules on our documentation site. We designed this tool for sophisticated users, which means there’s a lot more that is possible.
We’d love to hear your feedback, so give it a try! Here are some useful links:
If you like Hardhat Ignition, please star the repo on Github, and let us know what you think!