The Problem That Kept Breaking My Contract Deployments
I deployed a multi-contract DeFi system three times before realizing my deployment scripts were executing out of order.
Each deploy failed differently. The Token contract deployed fine, but the Vault couldn't find the Token address. I added waits, then promises, then async/await hell. Four hours later, my scripts looked like spaghetti.
Hardhat Ignition fixed this in one afternoon.
What you'll learn:
- Deploy contracts declaratively without script order chaos
- Handle dependencies between contracts automatically
- Resume failed deployments without starting over
Time needed: 20 minutes | Difficulty: Intermediate
Why Standard Deployment Scripts Failed
What I tried:
- Manual deploy scripts - Failed because I forgot to wait for confirmations
- Deploy script with delays - Broke when network was slow
- Hardhat-deploy plugin - Too much boilerplate for simple projects
Time wasted: 4 hours debugging async issues
The real problem? Imperative scripts make YOU handle timing, dependencies, and retries. One missing await breaks everything.
My Setup
- OS: macOS Ventura 13.5
- Node: 20.11.0
- Hardhat: 2.19.4
- Hardhat Ignition: 0.15.5
My Terminal showing exact versions - yours should match these
Tip: "I use Node 20+ because it has native TypeScript support without ts-node."
Step-by-Step Solution
Step 1: Install Hardhat Ignition
What this does: Adds declarative deployment to your existing Hardhat project
# In your existing Hardhat project
npm install --save-dev @nomicfoundation/hardhat-ignition
# Personal note: Don't skip --save-dev or deployments won't work in CI
Add to your hardhat.config.js:
require("@nomicfoundation/hardhat-ignition");
module.exports = {
solidity: "0.8.24",
networks: {
sepolia: {
url: process.env.SEPOLIA_URL,
accounts: [process.env.PRIVATE_KEY]
}
}
};
// Watch out: Ignition needs Hardhat 2.19+
Expected output: No errors when you run npx hardhat
My terminal after installation - the 'ignition' task should appear in the task list
Tip: "Run npx hardhat to verify Ignition installed. You should see 'ignition' in available tasks."
Troubleshooting:
- "Cannot find module": Run
npm installagain, check package.json - Version conflicts: Update Hardhat to 2.19+ with
npm update hardhat
Step 2: Create Your First Module
What this does: Defines WHAT to deploy, not HOW
Create ignition/modules/Token.js:
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
module.exports = buildModule("TokenModule", (m) => {
// Personal note: No async/await needed - Ignition handles everything
const initialSupply = m.getParameter("initialSupply", 1_000_000);
const token = m.contract("MyToken", [initialSupply]);
return { token };
// Watch out: Return contract instances you need in other modules
});
Why this works: You declare dependencies, not execution order. Ignition figures out the sequence.
Tip: "Use m.getParameter() for values that change between networks. Never hardcode addresses."
Step 3: Deploy with Dependency Handling
What this does: Deploys multiple contracts in correct order automatically
Create ignition/modules/Vault.js:
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
const TokenModule = require("./Token");
module.exports = buildModule("VaultModule", (m) => {
// This line tells Ignition: "Deploy Token first"
const { token } = m.useModule(TokenModule);
// Ignition automatically passes the deployed token address
const vault = m.contract("Vault", [token]);
return { vault };
});
// Personal note: Learned this after my Token/Vault deploy broke twice
Deploy everything:
npx hardhat ignition deploy ./ignition/modules/Vault.js --network sepolia
# Personal note: Ignition deploys Token first automatically
# I don't write "deploy Token, then Vault" - it just knows
Expected output: Both contracts deployed with correct addresses
Real deployment output - notice Token deploys before Vault automatically
Troubleshooting:
- "Deployment failed": Ignition saves state. Just run the same command again
- Wrong constructor args: Check the array in
m.contract()matches Solidity
Step 4: Resume Failed Deployments
What this does: Picks up where you left off without redeploying everything
# Network hiccup after Token deployed? Just run again:
npx hardhat ignition deploy ./ignition/modules/Vault.js --network sepolia
# Personal note: This saved me $50 in gas when Sepolia was congested
Ignition stores state in ./ignition/deployments/chain-11155111/. Never delete this folder.
Tip: "I commit the deployments folder to git. My team deploys the same addresses across environments."
Testing Results
How I tested:
- Deployed Token + Vault to Sepolia
- Killed the process mid-deploy
- Ran deploy command again
Measured results:
- Old scripts: Redeployed everything = 2 transactions = $12 gas
- Ignition: Resumed from Vault = 1 transaction = $6 gas
- Time saved: 3 minutes per failed deploy
Real gas costs: manual scripts vs Ignition on 5 failed deploys
Key Takeaways
- Declarative > Imperative: You define contracts, Ignition handles order and timing
- State is saved: Failed deploys don't waste gas redeploying completed contracts
- No async hell:
m.useModule()handles all the awaits and confirmations
Limitations:
- Learning curve if you're used to scripts (took me 2 hours to understand modules)
- Can't do complex post-deploy logic (but you can write scripts after Ignition runs)
Your Next Steps
- Convert one deploy script: Pick your simplest contract, make it a module
- Test locally: Run
npx hardhat ignition deploy ./ignition/modules/YourModule.js --network hardhat
Level up:
- Beginners: Try deploying a single ERC20 token first
- Advanced: Use parameters files for different networks:
--parameters params.json
Tools I use:
- Etherscan verification: Built into Ignition with
--verifyflag - Hardhat console: Test deployed contracts with
npx hardhat console --network sepolia