Migrating from Truffle to Hardhat: Practical Guide

Migrating from Truffle to Hardhat: A Practical Guide

As the Ethereum development ecosystem evolves, Hardhat has emerged as a powerful alternative to Truffle, offering enhanced performance, extensibility, and a modern plugin system. This guide will walk you through a thorough, step-by-step migration of an existing Truffle project to Hardhat, complete with configuration tweaks, test adaptation, deployment scripts, and best practices.

1. Prerequisites

  • Node.js v14 and npm or Yarn installed
  • An existing Truffle project with contracts/, migrations/, and test/ directories
  • Familiarity with JavaScript/TypeScript and basic CLI usage
  • API keys for networks (Infura, Alchemy, etc.)

2. Overview: Truffle vs Hardhat

Feature Truffle Hardhat
Development Network Built-in Ganache Hardhat Network (in-process, fast)
Testing Mocha Chai Mocha Chai Waffle
Plugins Truffle plugins 70 official/community plugins
Debugging Limited console logs Console.sol stack traces

3. Initial Setup

  1. Navigate to your project root and remove Truffle artifacts:
    rm -rf build/ contracts/Migrations.sol
  2. Install Hardhat:
    npm install --save-dev hardhat
  3. Initialize Hardhat in interactive mode:
    npx hardhat

    Select “Create a basic sample project” to scaffold config, scripts/, contracts/, and test/ folders.

4. Configuring hardhat.config.js

Replace the generated config with:

require(@nomiclabs/hardhat-waffle)
require(@nomiclabs/hardhat-etherscan)
require(dotenv).config()

module.exports = {
  solidity: 0.8.9,
  defaultNetwork: hardhat,
  networks: {
    hardhat: {},
    ropsten: {
      url: process.env.ROPSTEN_RPC_URL,
      accounts: [process.env.DEPLOYER_PRIVATE_KEY]
    }
  },
  etherscan: {
    apiKey: process.env.ETHERSCAN_API_KEY
  }
}

Tip: Use dotenv to manage secrets.

5. Migrating Contracts

  • Move contracts/ from Truffle to Hardhat project.
  • Ensure each contract imports hardhat/console.sol for debugging:
  • import hardhat/console.sol
  • Remove context-specific artifacts (e.g., Truffle’s artifacts.require).

6. Adapting Tests

Hardhat defaults to Waffle matchers, but you can continue with Chai assertions.

  • Update imports:
    const { ethers } = require(hardhat)
  • Replace:
    const instance = await MyContract.deployed()

    with:

    const MyContract = await ethers.getContractFactory(MyContract)
    const instance = await MyContract.deploy()

7. Deployment Scripts

Hardhat uses scripts/ instead of migrations/. Example deploy.js:

async function main() {
  const [deployer] = await ethers.getSigners()
  console.log(Deploying contracts with:, deployer.address)

  const Token = await ethers.getContractFactory(Token)
  const token = await Token.deploy(My Token, MTK, 18, ethers.utils.parseEther(1000000))
  console.log(Token deployed to:, token.address)
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error)
    process.exit(1)
  })

8. Plugins Integrations

9. Front-End Integration

If you use Truffle Contract, switch to @ethersproject or ethers.js:

import { ethers } from ethers
const provider = new ethers.providers.Web3Provider(window.ethereum)
const contract = new ethers.Contract(address, abi, provider.getSigner())

10. Continuous Integration

Add in your CI config (GitHub Actions example):

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install
        run: npm install
      - name: Compile  Test
        run: npx hardhat test

11. Troubleshooting Tips

  • Stack traces: Enable via --verbose or Hardhat’s solidity.debug setting.
  • Forking Mainnet: Use hardhat.networks.hardhat.forking.url for live state tests.
  • Cache issues: Run npx hardhat clean to reset artifacts.

Conclusion

Migrating from Truffle to Hardhat unlocks improved performance, superior debugging, and an ever-growing plugin ecosystem. By following this guide, you’ll modernize your workflow, reduce gas costs, and streamline contract development and deployment.

References


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *