import "dotenv/config"; import hardhatEthers from "@nomicfoundation/hardhat-ethers"; import hardhatNetworkHelpers from "@nomicfoundation/hardhat-network-helpers"; import hardhatNodeTestRunner from "@nomicfoundation/hardhat-node-test-runner"; import hardhatVerify from "@nomicfoundation/hardhat-verify"; const { ALCHEMY_KEY = "", INFURA_KEY = "", MAINNET_RPC_URL = "", SEPOLIA_RPC_URL = "", PRIVATE_KEY = "", ETHERSCAN_API_KEY = "", FORK_BLOCK = "", SOLC_PATH = "", } = process.env; /** * RPC URL for a chain: an explicit *_RPC_URL wins, otherwise one is built from * whichever provider key is in .env (Alchemy first, then Infura). */ function rpcUrl(chain, explicit) { if (explicit) return explicit; if (ALCHEMY_KEY) return `https://eth-${chain}.g.alchemy.com/v2/${ALCHEMY_KEY}`; if (INFURA_KEY) return `https://${chain}.infura.io/v3/${INFURA_KEY}`; // Nothing configured. Kept as an obviously-broken URL so the failure names // itself instead of silently forking an empty chain. return "https://rpc-not-configured.invalid"; } export const MAINNET_RPC = rpcUrl("mainnet", MAINNET_RPC_URL); export const SEPOLIA_RPC = rpcUrl("sepolia", SEPOLIA_RPC_URL); export const RPC_CONFIGURED = Boolean(ALCHEMY_KEY || INFURA_KEY || MAINNET_RPC_URL); const accounts = PRIVATE_KEY ? [PRIVATE_KEY] : []; export default { plugins: [ hardhatEthers, hardhatNetworkHelpers, hardhatNodeTestRunner, hardhatVerify, ], solidity: { profiles: { default: { version: "0.8.26", settings: { optimizer: { enabled: true, runs: 200 } }, // Escape hatch for offline / air-gapped builds: point SOLC_PATH at a // local soljson.js (e.g. node_modules/solc/soljson.js) and Hardhat // skips the compiler download entirely. ...(SOLC_PATH ? { path: SOLC_PATH } : {}), }, }, }, networks: { // Plain in-process chain. Used by test/local.test.js, which deploys its own // Manifold creator — no RPC, no keys, no network. hardhat: { type: "edr-simulated", chainType: "l1", }, // In-process chain with the gas caps lifted, for measuring what rendering // actually costs. Every other network enforces EIP-7825's 16,777,216 gas // per-transaction cap, which stops the measurement long before the // renderer does. Used by test/render.test.js and scripts/render-ceiling.js. probe: { type: "edr-simulated", chainType: "l1", allowUnlimitedContractSize: true, blockGasLimit: 5_000_000_000, transactionGasCap: false, }, // Mainnet fork. Used by test/fork.test.js against the real CLGSM contract. // Set FORK_BLOCK in .env to pin it — runs get faster and reproducible. forked: { type: "edr-simulated", chainType: "l1", forking: { url: MAINNET_RPC, ...(FORK_BLOCK ? { blockNumber: Number(FORK_BLOCK) } : {}), }, }, // `npx hardhat node` (optionally with --network forked), for exercising the // scripts end to end against a chain that survives between commands. localhost: { type: "http", chainType: "l1", url: "http://127.0.0.1:8545", accounts: "remote", }, sepolia: { type: "http", chainType: "l1", url: SEPOLIA_RPC, chainId: 11155111, accounts, }, mainnet: { type: "http", chainType: "l1", url: MAINNET_RPC, chainId: 1, accounts, }, }, verify: { etherscan: { apiKey: ETHERSCAN_API_KEY, enabled: Boolean(ETHERSCAN_API_KEY), }, }, };