Hardhat
Optimize BlockSecOps for Hardhat projects. Hardhat is a popular Ethereum development environment with extensive plugin support. BlockSecOps fully supports...
Last updated: January 14, 2026
Hardhat Guide
Optimize BlockSecOps for Hardhat projects.
Overview
Hardhat is a popular Ethereum development environment with extensive plugin support. BlockSecOps fully supports Hardhat project configurations.
Project Structure
Standard Layout
project/
├── contracts/ # Contract sources
│ ├── Token.sol
│ └── Vault.sol
├── test/ # Tests (JS/TS)
│ └── Token.test.js
├── scripts/ # Deployment scripts
│ └── deploy.js
├── node_modules/ # npm dependencies
│ └── @openzeppelin/
├── hardhat.config.js # Configuration
└── package.json
What to Upload
Include:
contracts/- All contract sourcesnode_modules/- Required for dependencieshardhat.config.jsorhardhat.config.tspackage.json- For dependency versions
Optional:
test/- Include for full analysis
Exclude:
artifacts/- Build artifactscache/- Hardhat cachecoverage/- Coverage reportstypechain-types/- Generated types
Configuration
hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
version: "0.8.20",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
paths: {
sources: "./contracts",
tests: "./test",
cache: "./cache",
artifacts: "./artifacts"
}
};
TypeScript Configuration
// hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
const config: HardhatUserConfig = {
solidity: {
version: "0.8.20",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
}
};
export default config;
Multiple Compiler Versions
module.exports = {
solidity: {
compilers: [
{ version: "0.8.20" },
{ version: "0.7.6" },
{ version: "0.6.12" }
],
overrides: {
"contracts/legacy/OldContract.sol": {
version: "0.6.12"
}
}
}
};
Dependency Management
Installing Dependencies
# Install OpenZeppelin
npm install @openzeppelin/contracts
# Install specific version
npm install @openzeppelin/[email protected]
# Install Chainlink
npm install @chainlink/contracts
Common Dependencies
{
"dependencies": {
"@openzeppelin/contracts": "^4.9.0",
"@openzeppelin/contracts-upgradeable": "^4.9.0",
"@chainlink/contracts": "^0.6.0"
},
"devDependencies": {
"hardhat": "^2.19.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0"
}
}
Import Resolution
Standard Imports
// npm package import
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// Relative import
import "./interfaces/IToken.sol";
// Parent directory import
import "../libraries/SafeMath.sol";
Import Path Resolution
Hardhat resolves imports from:
node_modules/(npm packages)- Relative to current file
- Custom paths in config
Creating Upload Archive
Including node_modules
node_modules must be included for dependency resolution:
# Create archive with dependencies
zip -r project.zip \
contracts/ \
node_modules/@openzeppelin/ \
node_modules/@chainlink/ \
hardhat.config.js \
package.json
Selective node_modules
To reduce archive size, include only used packages:
# Include only specific packages
zip -r project.zip \
contracts/ \
node_modules/@openzeppelin/contracts/ \
node_modules/@chainlink/contracts/ \
hardhat.config.js
Using npx to Generate Flat Files
# Flatten a contract (removes import dependencies)
npx hardhat flatten contracts/Token.sol > Token.flat.sol
CI/CD Integration
GitHub Actions
name: Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Compile contracts
run: npx hardhat compile
- name: Create archive
run: |
zip -r project.zip \
contracts/ \
node_modules/@openzeppelin/ \
hardhat.config.js \
package.json
- name: BlockSecOps Scan
env:
BLOCKSECOPS_API_KEY: ${{ secrets.BLOCKSECOPS_API_KEY }}
run: |
CONTRACT_ID=$(curl -s -X POST \
"https://api.blocksecops.com/api/v1/contracts/upload" \
-H "Authorization: Bearer $BLOCKSECOPS_API_KEY" \
-F "[email protected]" | jq -r '.id')
SCAN_ID=$(curl -s -X POST \
"https://api.blocksecops.com/api/v1/scans" \
-H "Authorization: Bearer $BLOCKSECOPS_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"contract_id\": \"$CONTRACT_ID\", \"preset\": \"standard\"}" \
| jq -r '.id')
echo "Scan started: $SCAN_ID"
Hardhat Plugins
Supported Plugins
BlockSecOps works with common Hardhat plugins:
| Plugin | Support |
|---|---|
| @nomicfoundation/hardhat-toolbox | Full |
| @openzeppelin/hardhat-upgrades | Full |
| hardhat-deploy | Full |
| hardhat-gas-reporter | N/A (not needed for scanning) |
Plugin Configuration
// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
require("@openzeppelin/hardhat-upgrades");
module.exports = {
solidity: "0.8.20",
// Plugins auto-configure
};
Upgradeable Contracts
OpenZeppelin Upgrades
// contracts/TokenV1.sol
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract TokenV1 is Initializable, ERC20Upgradeable {
function initialize(string memory name, string memory symbol)
public initializer
{
__ERC20_init(name, symbol);
}
}
BlockSecOps detects and analyzes upgrade patterns for:
- Storage layout issues
- Initializer vulnerabilities
- Proxy implementation issues
Troubleshooting
Compilation Errors
# Clean cache and recompile
npx hardhat clean
npx hardhat compile
# Check for errors
npx hardhat compile --force
Missing Dependencies
# Reinstall all dependencies
rm -rf node_modules
npm install
# Check specific package
npm ls @openzeppelin/contracts
Import Resolution Failures
Verify package is installed:
npm ls @openzeppelin/contractsCheck import path matches package structure:
ls node_modules/@openzeppelin/contracts/token/ERC20/Verify
node_modulesis included in upload
Version Conflicts
# Check for duplicate packages
npm ls
# Fix with specific version
npm install @openzeppelin/[email protected] --save-exact
Best Practices
Archive Creation Script
#!/bin/bash
# create-archive.sh
# Clean build
npx hardhat clean
npx hardhat compile
# Verify build succeeded
if [ $? -ne 0 ]; then
echo "Compilation failed"
exit 1
fi
# Create archive with minimal dependencies
zip -r project.zip \
contracts/ \
node_modules/@openzeppelin/contracts/ \
node_modules/@chainlink/contracts/ \
hardhat.config.js \
package.json \
package-lock.json
echo "Archive created: project.zip"
echo "Size: $(du -h project.zip | cut -f1)"
Reduce Archive Size
# Remove unnecessary files from node_modules
find node_modules -name "*.md" -delete
find node_modules -name "*.ts" -delete
find node_modules -name "test" -type d -exec rm -rf {} +
Example: Full Project Upload
#!/bin/bash
# 1. Install dependencies
npm ci
# 2. Compile to verify
npx hardhat compile
# 3. Create archive
zip -r project.zip \
contracts/ \
node_modules/@openzeppelin/ \
hardhat.config.js \
package.json
# 4. Upload
curl -X POST "https://api.blocksecops.com/api/v1/contracts/upload" \
-H "Authorization: Bearer $BLOCKSECOPS_API_KEY" \
-F "[email protected]"
Next Steps
- Foundry Guide - Foundry integration
- Import Resolution - Dependency troubleshooting
- CI/CD Overview - Pipeline setup