Templates and automation for initializing and configuring Hardhat projects. Use when setting up new Hardhat projects or adding Hardhat to existing codebases.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
scripts/init-hardhat.shtemplates/deploy-script.jstemplates/hardhat.config.jstemplates/hardhat.config.tsThis skill provides templates, scripts, and best practices for setting up Hardhat-based Solidity projects.
Use this skill when:
Prerequisites: Node.js and npm/yarn/pnpm must be installed
Before using this skill, reference the framework-detection skill to:
# Initialize new Hardhat project
npm init -y
npm install --save-dev hardhat
npx hardhat init
# Or with yarn
yarn init -y
yarn add --dev hardhat
npx hardhat init
Hardhat creates this structure:
project/
├── hardhat.config.js # Configuration
├── .env # Environment variables
├── package.json # Dependencies
├── contracts/ # Contract source files
│ └── Lock.sol # Example contract
├── test/ # Test files
│ └── Lock.js # Example test
├── scripts/ # Deployment scripts
│ └── deploy.js # Example script
└── ignition/ # Hardhat Ignition (deployment modules)
See ./templates/hardhat.config.js for JavaScript configuration template.
Key Configuration Sections:
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();
module.exports = {
solidity: {
version: "0.8.30",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
hardhat: {},
sepolia: {
url: process.env.SEPOLIA_RPC_URL || "",
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []
}
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY
}
};
See ./templates/hardhat.config.ts for TypeScript configuration template.
TypeScript Configuration:
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "dotenv/config";
const config: HardhatUserConfig = {
solidity: "0.8.30",
networks: {
sepolia: {
url: process.env.SEPOLIA_RPC_URL || "",
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []
}
}
};
export default config;
See ./templates/.env.example for complete environment variable template.
Essential Variables:
# RPC URLs
MAINNET_RPC_URL=
SEPOLIA_RPC_URL=
# Private Keys (NEVER commit actual keys)
PRIVATE_KEY=
# Etherscan API Keys
ETHERSCAN_API_KEY=
# Gas Settings
GAS_PRICE=
Includes all essential plugins:
npm install --save-dev @nomicfoundation/hardhat-toolbox
Includes:
@nomicfoundation/hardhat-ethers - Ethers.js integration@nomicfoundation/hardhat-chai-matchers - Chai matchers for testing@nomicfoundation/hardhat-verify - Contract verificationhardhat-gas-reporter - Gas usage reportingsolidity-coverage - Code coverage@typechain/hardhat - TypeScript types for contracts# Contract verification
npm install --save-dev @nomicfoundation/hardhat-verify
# Gas reporting
npm install --save-dev hardhat-gas-reporter
# Code coverage
npm install --save-dev solidity-coverage
# OpenZeppelin Upgrades
npm install --save-dev @openzeppelin/hardhat-upgrades
networks: {
mainnet: {
url: process.env.MAINNET_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 1
},
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 11155111
},
arbitrum: {
url: process.env.ARBITRUM_RPC_URL,
accounts: [process.env.PRIVATE_KEY],
chainId: 42161
}
}
solidity: {
version: "0.8.30",
settings: {
optimizer: {
enabled: true,
runs: 10000
},
viaIR: true
}
}
solidity: {
compilers: [
{
version: "0.8.30",
settings: {
optimizer: { enabled: true, runs: 200 }
}
},
{
version: "0.8.20",
settings: {
optimizer: { enabled: true, runs: 200 }
}
}
]
}
gasReporter: {
enabled: process.env.REPORT_GAS === "true",
currency: "USD",
coinmarketcap: process.env.COINMARKETCAP_API_KEY,
outputFile: "gas-report.txt",
noColors: true
}
# OpenZeppelin Contracts
npm install @openzeppelin/contracts
# OpenZeppelin Upgrades Plugin
npm install --save-dev @openzeppelin/hardhat-upgrades
# Ethers.js (usually included with hardhat-toolbox)
npm install ethers
# Chai for testing
npm install --save-dev chai
# Dotenv for environment variables
npm install --save-dev dotenv
See ./scripts/init-hardhat.sh for automated setup.
Usage:
# Basic initialization
./scripts/init-hardhat.sh
# With project name
./scripts/init-hardhat.sh my-project
# With TypeScript
./scripts/init-hardhat.sh my-project --typescript
What the script does:
When adding Hardhat to an existing Foundry project:
# Initialize npm project
npm init -y
# Install Hardhat
npm install --save-dev hardhat
npx hardhat init # Choose "Create an empty hardhat.config.js"
// hardhat.config.js
module.exports = {
paths: {
sources: "./src", // Use Foundry's src dir
tests: "./test", // Shared test dir
cache: "./cache_hardhat", // Separate cache
artifacts: "./artifacts"
},
solidity: "0.8.30"
};
# Hardhat
artifacts/
cache/
cache_hardhat/
node_modules/
coverage/
coverage.json
typechain-types/
# Foundry
out/
lib/
# Environment
.env
.env.local
# Install OpenZeppelin via npm (for Hardhat)
npm install @openzeppelin/contracts
# Foundry can reference node_modules
# Add to foundry.toml:
# libs = ["node_modules", "lib"]
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("MyContract", function () {
let myContract;
let owner;
beforeEach(async function () {
[owner] = await ethers.getSigners();
const MyContract = await ethers.getContractFactory("MyContract");
myContract = await MyContract.deploy();
});
it("Should work correctly", async function () {
// Test implementation
expect(await myContract.someFunction()).to.equal(expectedValue);
});
});
import { expect } from "chai";
import { ethers } from "hardhat";
import { MyContract } from "../typechain-types";
describe("MyContract", function () {
let myContract: MyContract;
beforeEach(async function () {
const MyContract = await ethers.getContractFactory("MyContract");
myContract = await MyContract.deploy();
});
it("Should work correctly", async function () {
expect(await myContract.someFunction()).to.equal(expectedValue);
});
});
# Run all tests
npx hardhat test
# Run specific test
npx hardhat test test/MyContract.test.js
# With gas reporting
REPORT_GAS=true npx hardhat test
# With coverage
npx hardhat coverage
⚠️ CRITICAL: Never store production private keys in .env files!
Install the Ledger plugin:
npm install --save-dev @nomicfoundation/hardhat-ledger
Configure in hardhat.config.js:
require("@nomicfoundation/hardhat-ledger");
module.exports = {
networks: {
mainnet: {
url: process.env.MAINNET_RPC_URL,
ledgerAccounts: [
"0xYourLedgerAddress"
]
}
}
};
Deploy with Ledger:
npx hardhat run scripts/deploy.js --network mainnet
Hardhat 2.x+ includes built-in support for secure configuration variables:
# Set a configuration variable (prompts for value, stores encrypted)
npx hardhat vars set PRIVATE_KEY
# List all configuration variables
npx hardhat vars list
# Delete a variable
npx hardhat vars delete PRIVATE_KEY
Use in hardhat.config.js:
const { vars } = require("hardhat/config");
module.exports = {
networks: {
sepolia: {
url: vars.get("SEPOLIA_RPC_URL"),
accounts: [vars.get("PRIVATE_KEY")]
}
}
};
This stores encrypted values in your home directory and prompts for decryption when needed.
Similar to Foundry's cast wallet, provides encrypted keystore management:
npm install --save-dev hardhat-keystore
Configure in hardhat.config.js:
require("hardhat-keystore");
module.exports = {
networks: {
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: {
mnemonic: keystore.getMnemonic(),
// or
privateKey: keystore.getPrivateKey("deployer")
}
}
}
};
npm install --save-dev hardhat-secure-accounts
Creates encrypted keystore files:
# Create new encrypted account
npx hardhat accounts:create
# Import existing private key
npx hardhat accounts:import --name deployer
Use in scripts:
const { getSecureAccount } = require("hardhat-secure-accounts");
async function main() {
const signer = await getSecureAccount("deployer");
// Use signer for deployment
}
Prompt for private key at runtime (doesn't store on disk):
const readline = require("readline");
async function getPrivateKey() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question("Enter private key: ", (answer) => {
rl.close();
resolve(answer);
});
});
}
async function main() {
const privateKey = await getPrivateKey();
const wallet = new ethers.Wallet(privateKey, ethers.provider);
// Use wallet for deployment
}
⚠️ Use ONLY for local development or testnet testing with non-production keys!
require("dotenv").config();
module.exports = {
networks: {
sepolia: {
url: process.env.SEPOLIA_RPC_URL,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []
}
}
};
If using .env:
// scripts/deploy.js
const hre = require("hardhat");
async function main() {
const MyContract = await hre.ethers.getContractFactory("MyContract");
const myContract = await MyContract.deploy();
await myContract.waitForDeployment();
console.log("MyContract deployed to:", await myContract.getAddress());
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
# Deploy to local network
npx hardhat run scripts/deploy.js
# Deploy to Sepolia with hardware wallet (RECOMMENDED for production)
npx hardhat run scripts/deploy.js --network sepolia
# (Ledger will prompt for approval)
# Deploy to Sepolia with Hardhat vars (RECOMMENDED for all deployments)
# First time: npx hardhat vars set PRIVATE_KEY
npx hardhat run scripts/deploy.js --network sepolia
# Development only: with .env private key
npx hardhat run scripts/deploy.js --network sepolia
# Verify contract
npx hardhat verify --network sepolia DEPLOYED_CONTRACT_ADDRESS
# Use npx
npx hardhat compile
# Or install globally (not recommended)
npm install -g hardhat
# Clear cache and reinstall
rm -rf node_modules package-lock.json
npm install
# Ensure correct import paths
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
# Check RPC URL in .env
# Test with curl
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
$SEPOLIA_RPC_URL
| Task | Command | Notes |
|---|---|---|
| Init project | npx hardhat init | Creates new project |
| Add dependency | npm install <package> | Uses npm |
| Compile | npx hardhat compile | Compiles contracts |
| Test | npx hardhat test | Runs tests |
| Coverage | npx hardhat coverage | Test coverage |
| Gas report | REPORT_GAS=true npx hardhat test | Gas usage |
| Deploy | npx hardhat run scripts/deploy.js | Run deployment |
| Verify | npx hardhat verify | Verify on Etherscan |
| Clean | npx hardhat clean | Clean artifacts |
This skill provides the following templates:
./templates/hardhat.config.js - JavaScript configuration./templates/hardhat.config.ts - TypeScript configuration./templates/.env.example - Environment variables template./templates/deploy-script.js - Deployment script templateThis skill provides the following scripts:
./scripts/init-hardhat.sh - Automated project initializationNext Steps After Setup:
hardhat.config.js for your networks.env.example to .env and fill in valuesnpm installcontracts/test/npx hardhat test to verify setup