gm guys, I have a question about the InheritanceSubmission on the basecamp contract: I performed the following steps to deploy my contracts using Hardhat's Ignition:

  • I deployed the Salesperson and EngineerManager contracts in the same ignition and recorded both contract numbers.
  • I created another ignition module to deploy the InheritanceSubmission, passing the addresses of the previously deployed Salesperson and EngineerManager contracts.
  • I executed the Hardhat ignition command to deploy the InheritanceSubmission contract, but...

Although my InheritanceSubmissionModule only deploys the InheritanceSubmissionModule, it also redeployed the Salesperson and EngineerManager contracts. So, I'm wondering if there's a way to deploy all three contracts in the same ignition module. Ideally, after deploying the Salesperson and EngineerManager contracts, I could get the contract numbers of both and pass these numbers as parameters to the InheritanceSubmission. Alternatively, I want to know how to prevent Hardhat from redeploying my Salesperson and EngineerManager contracts when I try to deploy only the InheritanceSubmission contract.

Here is the link of the excercise in case you want to check

Edit: add ignition scripts:

salesperson and engineermanager contracts:

import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

const salesPersonHourlyRate = 20;
const salesPersonIdNumber = 55555;
const salesPersonManagerId = 12345;

const emAnnualSalary = 200000;
const emIdNumber = 54321;
const emManagerId = 11111;

const InheritanceModule = buildModule("InheritanceModule", (m) => {
  const hourlyRate = m.getParameter("hourlyRate", salesPersonHourlyRate);
  const managerId = m.getParameter("managerId", salesPersonManagerId);
  const idNumber = m.getParameter("IdNumber", salesPersonIdNumber);

  const annualSalary = m.getParameter("annualSalary", emAnnualSalary);
  const idNumberEm = m.getParameter("IdNumber", emIdNumber);
  const managerIdEm = m.getParameter("managerId", emManagerId);

  const salesPerson = m.contract("Salesperson", [

  const engineerManager = m.contract("EngineeringManager", [

  return { salesPerson, engineerManager };

export default InheritanceModule;

InheritanceSubmitionModule Contract

import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

const salespersonContract = "0x7E969c14eeCcB542d11f0cAA533dE30A097d82eC";
const enginnerManagerContract = "0xFCb006323675EE6fAfd3f74934DbB6C8E856a883";

const InheritanceSubmitionModule = buildModule(
  (m) => {
    const salespersonAddress = m.getParameter(
    const engineerManagerAddress = m.getParameter(

    const inheritanceSubmition = m.contract("InheritanceSubmission", [

export default InheritanceSubmitionModule;
  • Can you share your deploy script ? Commented Apr 7 at 8:43
    – Jean
    Commented Apr 7 at 10:14
  • Thanks @Jean. Do you have any restrictions to achieve that via ignition module only? Or, are you open to using hardhat script as well? Commented Apr 7 at 10:17

3 Answers 3


Hardhat Ignition doesn't seem to provide a way (yet) to retrieve the contract addresses directly after deployment, particularly because it creates Future artifacts corresponding to the contracts during deployment.

However, with a general Hardhat Script, you can achieve the same easily.

You can just create a script folder, and create deploy.js file inside the same. Then, you can simply copy-paste this code in the deploy.js file:

const { ethers } = require("hardhat");
const fs = require('fs');

async function main() {
    // Initialize an empty object to store deployed contract addresses
    let deployedContracts = {};

    // Check if the 'deployed-contracts.json' file exists
    if (fs.existsSync('deployed-contracts.json')) {

        // If the file exists, read its contents and parse the JSON data
        const data = fs.readFileSync('deployed-contracts.json', 'utf8');

        deployedContracts = JSON.parse(data);

        // Get the factory of the 'InheritanceSubmission' contract
        InheritanceSubmission = await ethers.getContractFactory("InheritanceSubmission");
    else {
        // If the file does not exist, deploy 'Salesperson' and 'EngineeringManager' contracts
        let salesPerson, engineeringManager;

        // Deploy the 'Salesperson' contract
        const salesPersonContractFactory = await ethers.getContractFactory("Salesperson");

        const salesPersonContract = await salesPersonContractFactory.deploy(); // Pass constructor params (if any)

        // Get the address of the deployed 'Salesperson' contract
        salesPerson = await salesPersonContract.getAddress()

        // Deploy the 'EngineeringManager' contract
        const engineeringManagerContractFactory = await ethers.getContractFactory("EngineeringManager");

        const engineeringManagerContract = await engineeringManagerContractFactory.deploy(); // Pass constructor params (if any)

        // Get the address of the deployed 'EngineeringManager' contract
        engineeringManager = await engineeringManagerContract.getAddress();

        // Store the addresses of the deployed contracts in 'deployedContracts' object
        deployedContracts = {
            salesPerson: salesPerson,
            engineeringManager: engineeringManager

        // Write the 'deployedContracts' object to 'deployed-contracts.json' file
        fs.writeFileSync('deployed-contracts.json', JSON.stringify(deployedContracts, null, 2));

        console.log("Salesperson and EngineeringManager contracts have been deployed and their contract addresses have been saved to deployed-contracts.json");


    // Deploy the 'InheritanceSubmission' contract with the addresses of 'Salesperson' and 'EngineeringManager' contracts
    const inheritanceSubmissionContractFactory = await ethers.getContractFactory("InheritanceSubmission");

    const inheritanceSubmissionContract = await inheritanceSubmissionContractFactory.deploy(deployedContracts.salesPerson, deployedContracts.engineeringManager);

    // Print the address of the deployed 'InheritanceSubmission' contract
    console.log("InheritanceSubmission contract has been deployed at", await inheritanceSubmissionContract.getAddress());

    // Print the addresses of 'Salesperson' and 'EngineeringManager' contracts stored in 'InheritanceSubmission' contract
    console.log("SalesPerson:", await inheritanceSubmissionContract.salesPerson())

    console.log("EngineeringManager:", await inheritanceSubmissionContract.engineeringManager())

    .then(() => process.exit(0))
    .catch(error => {

Then, execute the script using this command:

npx hardhat run scripts/deploy.js --network hardhat

P.S. You can change the network from hardhat to any other network as specified in your hardhat.config.js.


I just tested this in recent versions (and actually reported it to the team because it is not clear in the docs) and it works:

module.exports = buildModule("SampleModule", (m) => {
  // case 1: A contractAt future being used as an address argument.
  const contract = m.contract(
    "MyOwnedERC20", [], {id: "MyOwnedERC20_1"}
  const contract2 = m.contractAt(
    "MyOwnedERC20", "0x5fbdb2315678afecb367f032d93f642f64180aa3", {id: "MyOwnedERC20_2"}
  m.call(contract, "transferOwnership", [contract2])

  // case 2: A contract future being used as an address argument.
  const contract3 = m.contract(
      "MyOwnedERC20", [], {id: "MyOwnedERC20_3"}
  const contract4 = m.contract(
      "MyOwnedERC20", [], {id: "MyOwnedERC20_4"}
  m.call(contract3, "transferOwnership", [contract4]);

There's an explanation: contracts are address-resolvable futures, and are allowed as arguments when... anything, actually: either calling methods or invoking a constructor.

Just in case, I'm testing with the hardhat-ignition version coming from hardhat 2.22.5.

  • Yeah, I think the docs of hardhat-ignition are pretty unclear. Commented Jun 19 at 17:01

After some attempts, here is the solution :

First, import your other modules with useModule into the contract you want to link the others to :

const otherModule = m.useModule(OtherModule);

Then, in the contract deployment contructor args, just set otherModule.artifact where you want to get your address populated.

Almost impossible to guess that move from documentation. You're welcome :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.