Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 51 additions & 17 deletions hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,87 @@
/**
* @fileoverview Hardhat configuration file.
* Configures Solidity compiler, enables mainnet forking for testing,
* and sets up network details for development environments.
* * Pre-requisites:
* - Environment variable MAINNET_PROVIDER_URL (e.g., Alchemy/Infura node URL)
* - Environment variable DEV_ETH_MNEMONIC (24-word development mnemonic)
*/

// Load Hardhat plugins
require('@nomiclabs/hardhat-web3');
require('@nomiclabs/hardhat-ethers');
const ethers = require('ethers');
require('@nomiclabs/hardhat-ethers');
// No need to require 'ethers' globally; Hardhat provides it.

// --- CONFIGURATION VARIABLES ---
const providerUrl = process.env.MAINNET_PROVIDER_URL;
const developmentMnemonic = process.env.DEV_ETH_MNEMONIC;

if (!providerUrl) {
console.error('Missing JSON RPC provider URL as environment variable `MAINNET_PROVIDER_URL`\n');
process.exit(1);
}

if (!developmentMnemonic) {
console.error('Missing development Ethereum account mnemonic as environment variable `DEV_ETH_MNEMONIC`\n');
process.exit(1);
}

/**
* Generates an array of private keys from a mnemonic phrase.
* This function is necessary for network configurations (like 'localhost')
* that explicitly require private keys rather than a mnemonic.
* @param {string} mnemonic - The 12/24-word seed phrase.
* @param {number} numberOfPrivateKeys - The number of keys to generate (default 20).
* @returns {string[]} An array of generated private keys.
*/
function getPrivateKeysFromMnemonic(mnemonic, numberOfPrivateKeys = 20) {
const result = [];
// Use Hardhat's internal Ethers dependency (accessible via 'ethers' helper in global scope if needed)
// Since this is in the config file, we rely on the previously required '@nomiclabs/hardhat-ethers' for 'ethers' to be available.
const { ethers } = require("hardhat"); // Safely access Ethers within Hardhat environment

for (let i = 0; i < numberOfPrivateKeys; i++) {
result.push(ethers.Wallet.fromMnemonic(mnemonic, `m/44'/60'/0'/0/${i}`).privateKey);
// CRITICAL FIX: Ensure the private key derivation is correct and results are returned.
const wallet = ethers.Wallet.fromMnemonic(mnemonic, `m/44'/60'/0'/0/${i}`);
result.push(wallet.privateKey);
}
return result; // CRITICAL FIX: Must return the array of keys.
}

// --- HARDHAT EXPORT CONFIG ---
module.exports = {
// Solidity Compiler Settings
solidity: {
version: '0.8.6',
settings: {
optimizer: {
enabled: true,
runs: 1000
runs: 1000 // A higher run count is generally better for production-ready code.
}
}
},

// Network Configuration
networks: {
// 1. hardhat (Default in-memory local network with Mainnet Forking)
hardhat: {
// Input validation is handled implicitly by Hardhat when accessing 'providerUrl'.
// Hardhat will throw a clear error if 'providerUrl' is undefined upon forking attempt.
forking: {
url: providerUrl,
url: providerUrl || "", // Use empty string if undefined; let Hardhat throw the error.
enabled: providerUrl !== undefined, // Explicitly control forking
},
// Gas settings optimized for local development/testing
gasPrice: 0,
initialBaseFeePerGas: 0,
loggingEnabled: false,
// Use the mnemonic directly for account management (Hardhat's preferred way)
accounts: {
mnemonic: developmentMnemonic,
},
chainId: 1, // metamask -> accounts -> settings -> networks -> localhost 8545 -> set chainId to 1
// Chain ID must be 1 for Mainnet forking to be seamless with Metamask
chainId: 1,
},

// 2. localhost (External local network, often started via 'npx hardhat node')
localhost: {
url: 'http://localhost:8545',
accounts: getPrivateKeysFromMnemonic(developmentMnemonic),
// Get array of private keys derived from the mnemonic for the external node.
// This requires the external node (e.g., 'hardhat node' command) to be started
// with the same mnemonic/accounts.
accounts: developmentMnemonic
? getPrivateKeysFromMnemonic(developmentMnemonic)
: [], // Fallback to empty array if mnemonic is missing
}
},
};