Hardhat Configuration: Tooling for Smart Contracts
We configure Hardhat for projects where development speed and deployment reliability are critical. Incorrect configuration leads to hours wasted debugging tests, repeated deployments, and lost data. Our experience shows that proper Hardhat setup immediately enables incremental compilation, parallel tests, and idempotent deployment. Result: CI/CD knows what to do without manual instructions. In one project, configuration took 3 days, and the time saved on repeated deployments was 70%.
Imagine: you write a smart contract, compile, deploy to a testnet, test — and repeat dozens of times a day. Every configuration mistake costs time and money. Incorrect Hardhat settings can lead to contract bugs, 15-20% higher gas, and even loss of funds. We configure Hardhat so development is fast and deployment is secure.
Basic Configuration
Minimum hardhat.config.ts for a production project:
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "@openzeppelin/hardhat-upgrades";
import "hardhat-deploy";
import "hardhat-contract-sizer";
const config: HardhatUserConfig = {
solidity: {
version: "0.8.24",
settings: {
optimizer: { enabled: true, runs: 200 },
viaIR: true,
},
},
networks: {
hardhat: {
forking: { url: process.env.ALCHEMY_MAINNET_URL! },
chainId: 1,
},
polygon: {
url: process.env.ALCHEMY_POLYGON_URL!,
accounts: [process.env.DEPLOYER_PRIVATE_KEY!],
gasPrice: "auto",
},
},
gasReporter: {
enabled: process.env.REPORT_GAS === "true",
currency: "USD",
coinmarketcap: process.env.CMC_API_KEY,
},
};
viaIR: true is important for contracts with "Stack too deep" errors — Solidity documentation recommends it for complex contracts. Without the IR compiler, this error often occurs, but compilation time increases by 30-50%. We ensure the configuration covers all typical scenarios.
Plugins That Actually Matter
| Plugin | Purpose | When mandatory |
|---|---|---|
| hardhat-deploy | Manage deployments: named accounts, fixtures, tagging | When working with multiple networks |
| hardhat-contract-sizer | Check bytecode size (EIP-170) | Before mainnet deployment |
| @nomicfoundation/hardhat-toolbox | Meta-plugin: ethers, waffle, chai-matchers, verify | Always (replaces 6 separate plugins) |
| @openzeppelin/hardhat-upgrades | UUPS/Transparent Proxy: storage layout check | When using proxies |
hardhat-deploy — idempotent deployments with support for named accounts, fixtures, and tagging. Deploy scripts store artifacts in deployments/ and are idempotent: re-running does not redeploy already deployed contracts. Indispensable when working with multiple networks.
hardhat-contract-sizer — checks contract size. EIP-170 limits bytecode to 24576 bytes. Hitting this limit unexpectedly on mainnet deployment is unpleasant. The plugin shows size after each compilation.
@nomicfoundation/hardhat-toolbox — meta-plugin that includes hardhat-ethers, hardhat-waffle, hardhat-chai-matchers, hardhat-network-helpers, hardhat-verify. One dependency instead of six.
@openzeppelin/hardhat-upgrades — if the project uses UUPS or Transparent Proxy. The plugin checks storage compatibility before upgrade deployment: if the new contract violates storage layout, you learn about it before losing data on mainnet.
Production Configuration
Production configuration differs from development: enable optimizer with runs: 200, fork mainnet for tests, enable gas reporter. Use hardhat-deploy to manage deployments — it cuts repeated deployment time by 5x.
How to Speed Up Hardhat Tests?
Slow tests are often caused by improper fixtures. The loadFixture pattern from hardhat-network-helpers allows snapshotting the network state after deployment and reverting to it before each test instead of redeploying. Comparison: without loadFixture (redeploy) — 5 minutes for 200 tests, with loadFixture — 30 seconds. 10x faster.
async function deployTokenFixture() {
const [owner, alice, bob] = await ethers.getSigners();
const Token = await ethers.getContractFactory("MyToken");
const token = await Token.deploy(ethers.parseEther("1000000"));
return { token, owner, alice, bob };
}
it("transfers tokens", async () => {
const { token, alice } = await loadFixture(deployTokenFixture);
});
Benefits of hardhat-deploy
This plugin provides idempotency: re-running does not create duplicate contracts. Named accounts (via hardhat.config.ts) avoid hardcoding addresses. Tagging allows deploying only changed contracts. As a result, deployment becomes predictable and reproducible.
| Criteria | Manual deployment | hardhat-deploy |
|---|---|---|
| Idempotency | No — duplicates on re-run | Yes — safe to re-run |
| Named accounts | Hardcoded addresses | Via config |
| Tagging | No — deploy everything | Only changed contracts |
| Time for 3 networks | ~2 hours | ~25 minutes |
Integrating Hardhat with CI/CD
GitHub Actions for automatic test execution and verification:
- name: Run tests
run: npx hardhat test --network hardhat
env:
ALCHEMY_MAINNET_URL: ${{ secrets.ALCHEMY_URL }}
- name: Verify contract
run: npx hardhat verify --network polygon ${{ steps.deploy.outputs.address }}
env:
POLYGONSCAN_API_KEY: ${{ secrets.POLYGONSCAN_KEY }}
Verification in CI requires constructor arguments to be deterministic or saved as deployment artifacts. hardhat-deploy automatically saves arguments in deployments/polygon/ContractName.json.
What's Included
- Full Hardhat configuration tailored to your project: network settings, optimizer, plugins.
- Writing deploy scripts using hardhat-deploy.
- Test integration with loadFixture and coverage setup.
- CI/CD: configuring GitHub Actions for automatic testing and verification.
- Documentation on using the environment.
- 90 days of support after delivery.
Estimated Timeline
Hardhat configuration for a typical project takes 2 to 5 days depending on contract complexity and number of networks. Cost is calculated individually after evaluating the scope of work. We'll evaluate your project in one business day — contact us. Get a consultation on Hardhat setup.
Our team has 5 years of experience in Ethereum and related L2 development, 50+ successful mainnet deployments. Certified developers ensure stability and security of the configuration.







