Repository navigation
Upgrade Hardhat to V3 - #120
Merged
Merged
Conversation
…ules Hardhat 3 requires the project to be an ES module and drops the plugin set the repo used. hardhat-deploy v2 is a rewrite on rocketh that needs Hardhat 3, so the two upgrades happen together. Dependencies: - hardhat 2 -> ^3.16.0, which passes the 14 day minimumReleaseAge. - hardhat-deploy 1 -> ^2.0.26, plus rocketh and @rocketh/deploy. The deploy scripts only call deploy, so the repo needs no other rocketh extension. - @nomicfoundation/hardhat-toolbox -> hardhat-toolbox-mocha-ethers. pnpm installs the plugins that the toolbox declares as peer dependencies, so package.json lists only hardhat-ethers and hardhat-verify, which the repo imports directly. - solidity-coverage goes, because Hardhat 3 has coverage built in (hardhat test --coverage). - typechain goes, because hardhat-typechain bundles it. - ts-node -> tsx, since ts-node needs a loader flag under ESM. - @api3/contracts 42 -> ^43.0.0, the first release with the Hardhat 3 network, chain descriptor and verify config (hardhatConfig.v3). Scripts: - compile -> build, and hardhat.build.config.ts goes away. It differed from hardhat.config.ts only by leaving out the networks, and the Hardhat 3 network config from @api3/contracts needs no environment variables to load. - --parallel moves into the config. - verify-vendor-contracts runs with tsx. It does not use the Hardhat runtime. ES module conversion: - eslint.config.js becomes eslint.config.cjs so it keeps loading as CommonJS. - .solcover.js goes with solidity-coverage. - __dirname -> import.meta.dirname in scripts/tag-and-release.ts. - relative imports in src get the .js extensions that Node's ES module resolution requires. pnpm-workspace.yaml gets allowBuilds entries for @parcel/watcher and esbuild, which come in with Hardhat 3 and tsx. The ignore files list generated/, which holds the hardhat-deploy v2 typed artifacts. These are build output, the same as typechain-types. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The config moves to defineConfig with the toolbox and hardhat-deploy in the plugins array. networks, chainDescriptors and verify come from the Hardhat 3 exports of @api3/contracts, which replace the etherscan() and networks() helpers that were shaped for Hardhat 2. evmVersion is pinned to "paris". Hardhat 2 forced it whenever it was unset, and Hardhat 3 leaves the choice to solc, which picks a newer default for 0.8.27. The default and production profiles hold the same compilers. "hardhat deploy" and verifyContract() build with production, and "hardhat build" with default, so a difference between the two would make the verified bytecode differ from the tested one. The two @api3/contracts interfaces that the contracts import are listed in npmFilesToBuild. Hardhat 2 generated TypeChain types for them and the package exports those types, and Hardhat 3 builds npm sources only when they are listed. With them in the build, typechain-types has the same files and index.ts has the same exports as the published 0.3.0 package. Compared with a Hardhat 2 build of the same sources, every contract has the same creation and runtime bytecode once the CBOR metadata is stripped. The metadata hash differs, because Hardhat 3 names project sources "project/contracts/..." and solc hashes the source names into the metadata. .solcover.js skipFiles moves to coverage.skipFiles, and --parallel moves to test.mocha.parallel. dotenv stays: the @api3/contracts helpers read MNEMONIC, the RPC URLs and the Etherscan key from process.env when the config loads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hardhat 3 no longer exports ethers from the hardhat module. Each network connection carries its own ethers and network helpers, so each test file opens one connection at the top and takes both from it. The test files do not import from each other, so they do not need a shared connection. networkHelpers is taken under the name helpers, so the existing helpers.loadFixture and helpers.time call sites are untouched. @nomicfoundation/hardhat-ethers no longer exports ./signers, so HardhatEthersSigner comes from ./types. No matcher changes are needed: the tests use none of the matchers whose signature changed. 71 tests pass, the same as on Hardhat 2. "hardhat test --coverage" leaves out the mock and vendor contracts, as .solcover.js did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rocketh/config.ts holds the deployer account. There were never any named accounts here, and the deployer was always the first unnamed account, so it is index 0, which resolves against eth_accounts of the network provider. Only the deploy extension is wired in, because the scripts do not call read or execute and deploy no proxies.
Each script keeps its steps: deploy a mock on a local network or read the address from the environment, check it, derive the deployment name from the constructor arguments, deploy, verify. The deployment names do not change: getDeploymentName receives the same values, and the PriceCappedApi3ReaderProxyV1 name on a local network is the same as on Hardhat 2.
The local network check compared against the network names hardhat and localhost. Hardhat 3 calls its built-in in-memory network default, so the check is now default or localhost.
run('verify:verify') is gone, since a v2 deploy script gets no task runner. rocketh/utils.ts calls verifyContract from hardhat-verify instead, with the provider that @api3/contracts gives for the chain ("other" is Blockscout, as in the Hardhat 3 chain descriptors). A chain with no verification API is skipped with a message.
hardhat-deploy v1 waited for 5 confirmations as part of the deployment, so that the block explorer knew the contract by the time it was verified. rocketh reads the confirmation count only from a per-chain config, so rocketh/utils.ts waits for the 5 confirmations before it verifies a new deployment.
The deploy scripts give hardhat-deploy their default export, so the ESLint override for deploy/ turns off import-x/no-default-export. The scripts no longer export an anonymous function, so the override drops unicorn/no-anonymous-default-export.
The typed artifacts come from generated/, and the arguments are typed against their ABIs, so the mock values become bigint where the ABI takes a bigint.
On the default network, all five scripts deploy and skip verification. Against hyperliquid with an empty account, the Product script reads both proxies and gives the same deployment name as the ProductApi3ReaderProxyV1_5883d33e record in dapp-management, then fails on the deploy transaction for lack of funds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Hardhat 3 verify config from @api3/contracts reads one ETHERSCAN_API_KEY for every chain that Etherscan serves, so the per-network key names go. Blockscout chains need no key. The config note names the Hardhat 3 helpers: networks, chainDescriptors and verify, from hardhat-config-v3.ts. hardhat-deploy v2 records keep the constructor arguments ABI-encoded in argsData and have no args field. hardhat-deploy v2 asks to confirm the gas price before it sends transactions to a live network, and --skip-prompts turns that off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deploy scripts were added to the package in 1e749ab (#52) without a named consumer. No api3dao repository references the published deploy folder, and the one consumer of the package, dapp-management, has deploy scripts of its own and imports only getDeploymentName and the Solidity sources. After the move to hardhat-deploy v2, the scripts import ../rocketh/*.js and ../generated/artifacts/index.js, and the package publishes neither, so the published copies could not run anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #45
Moves the repo to Hardhat 3, and with it to hardhat-deploy v2, which needs Hardhat 3. The network, chain descriptor and verify config come from
hardhatConfig.v3in@api3/contracts43.0.0, the first release that has it.For consumers of the package:
"type": "module"), so a CommonJSrequirebreaks. The one consumer I found, dapp-management, already uses ES module imports ofgetDeploymentNameand the.solpaths, which work unchanged.deploy/is no longer published. The v2 scripts importrocketh/andgenerated/, which the package does not ship, so the published copies could not run anyway.For deploying: the README covers the changes. One
ETHERSCAN_API_KEYnow serves every Etherscan chain, and hardhat-deploy v2 asks you to confirm the gas price on a live network unless you pass--skip-prompts. The verification step inrocketh/utils.tshas not run against a real explorer yet, so the first live deployment will be its first run.Notable detail:
evmVersionis pinned toparis. Hardhat 2 forced it, and Hardhat 3 leaves the choice to solc, which would change the bytecode.