Blockchain 8 min read

Deploy Precompiled NPM Smart Contract Artifacts with Hardhat & ethers.js

This guide explains why compiling third‑party contracts from node_modules fails and shows a robust method to deploy precompiled artifacts directly using Hardhat and ethers.js, with step‑by‑step code examples for UniswapV3Factory.

Ops Development & AI Practice
Ops Development & AI Practice
Ops Development & AI Practice
Deploy Precompiled NPM Smart Contract Artifacts with Hardhat & ethers.js

Why Direct Compilation Fails

When developers try to compile contracts from npm packages such as @uniswap/v3-core, they encounter a "wall" because the published packages contain only interface definitions and precompiled artifact files (ABI and bytecode), not the original .sol source files. Consequently, ethers.getContractFactory("ContractName") cannot locate bytecode, and importing the source leads to dependency errors.

Solution: Use Precompiled Artifacts Directly

The recommended approach is to bypass Hardhat’s compilation step and import the ready‑made artifact JSON files from node_modules. These artifacts provide everything needed for deployment: the contract’s ABI and bytecode.

Step 1 – Locate the Artifact

Find the JSON file inside the package. For Uniswap V3 core the path is:

@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json

Step 2 – Import the Artifact

In the deployment script, import the file just like a regular Node module:

// scripts/deploy-uniswap.js
const UniswapV3FactoryArtifact = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json");

The UniswapV3FactoryArtifact object now contains abi and bytecode.

Step 3 – Create a ContractFactory with ethers.js

Use the ethers.js ContractFactory constructor to build a factory from the extracted ABI and bytecode:

const { ethers } = require("hardhat");
async function main() {
  const [deployer] = await ethers.getSigners();
  const factoryAbi = UniswapV3FactoryArtifact.abi;
  const factoryBytecode = UniswapV3FactoryArtifact.bytecode;
  const Factory = new ethers.ContractFactory(factoryAbi, factoryBytecode, deployer);
  console.log("Deploying UniswapV3Factory...");
  const factory = await Factory.deploy();
  console.log("Waiting for deployment confirmation...");
  await factory.waitForDeployment();
  console.log("✅ UniswapV3Factory deployed to:", factory.target);
}
main().then(() => process.exit(0)).catch(error => { console.error("❌ Deployment failed:", error); process.exit(1); });

Note that with ethers.js v6 the old .deployed() method is deprecated; use waitForDeployment() and factory.target to obtain the address.

Full Script Example

// scripts/deploy-uniswap.js
const { ethers } = require("hardhat");
const UniswapV3FactoryArtifact = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json");
async function main() {
  console.log("Fetching deployer account...");
  const [deployer] = await ethers.getSigners();
  console.log("Deploying with account:", deployer.address);
  const factoryAbi = UniswapV3FactoryArtifact.abi;
  const factoryBytecode = UniswapV3FactoryArtifact.bytecode;
  console.log("Creating ContractFactory from ABI & bytecode...");
  const Factory = new ethers.ContractFactory(factoryAbi, factoryBytecode, deployer);
  console.log("Deploying UniswapV3Factory...");
  const factory = await Factory.deploy();
  console.log("Waiting for contract deployment...");
  await factory.waitForDeployment();
  console.log("✅ UniswapV3Factory successfully deployed to:", factory.target);
}
main().then(() => process.exit(0)).catch(error => { console.error("❌ Deployment failed:", error); process.exit(1); });

Benefits of This Approach

Robust and Reliable – Uses the officially published bytecode that has been thoroughly tested, avoiding compiler version or optimizer mismatches.

Simple and Efficient – No need for proxy contracts, custom path mappings, or additional Hardhat configuration; the deployment logic stays in the script.

Highly Portable – Works for any third‑party protocol that distributes precompiled artifacts via npm, making it a universal pattern for external dependencies.

By mastering direct artifact deployment, developers can streamline their Hardhat workflow and confidently integrate core DeFi protocols into local testing environments.

deploymentsmart contractsWeb3ArtifactsHardhatethers.jsUniswap
Ops Development & AI Practice
Written by

Ops Development & AI Practice

DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.