back

2025-08-22

Foundry vs Hardhat — Why Foundry won

Dev tooling

It's 2 AM. Fourth coffee. A Hardhat test suite has been running for 47 minutes.

200 tests. Core AMM functionality. Every CI run takes nearly an hour. Every small change means waiting. Waiting to know if the code works. Waiting to ship.

This was the reality for many Solidity developers before Foundry. The same test suite, migrated to Foundry with identical coverage, runs in 3 minutes and 12 seconds.

That's not an optimization. That's a different category.

The framework graveyard

Ethereum development tooling has a short and violent history.

Truffle was the original. Launched in 2015, it was the first real framework for smart contract development. By 2020, when Consensys acquired the Truffle Suite, it claimed 1.3 million developers and 8.5 million downloads.

Then it died. In September 2023, Consensys announced the sunset of Truffle and Ganache. End of an era. The engineering team moved to MetaMask.

Hardhat filled the vacuum. Built by Nomic Foundation, it offered better debugging, a plugin ecosystem, and modern JavaScript tooling. For a few years, it was the standard.

But Hardhat made the same mistake Truffle made. It got comfortable.

Enter Foundry

In December 2021, Paradigm quietly released Foundry.

The project came from Georgios Konstantopoulos, now CTO and General Partner at Paradigm. Before joining the firm, he was a sought-after researcher and engineer, known for deep technical work on Ethereum infrastructure. Portfolio companies kept mentioning his name.

Foundry was designed as a "portable, fast, and modular toolkit" to address pain points in existing tools—not just Hardhat, but also Dapptools, the earlier Haskell-based framework that pioneered some of Foundry's ideas but never achieved mainstream adoption.

The toolkit is not one tool but four:

  • Forge — the testing and compilation engine
  • Cast — CLI for blockchain interactions and on-chain queries
  • Anvil — local Ethereum node for development
  • Chisel — interactive Solidity REPL

The thesis was simple: smart contract developers should not need to master JavaScript to test Solidity code. As Konstantopoulos put it, "You write tests, you learn Solidity."

What began as an internal tool evolved into one of the most used open source projects in crypto. Alongside Reth and Alloy, Foundry has attracted over 1,000 unique open source contributors. Major protocols—Uniswap, Optimism, Base, Worldcoin—now build with it. Teams like Alchemix switched entirely, citing speed and the ability to write everything in Solidity as game-changers.

Why Foundry won

Foundry did not win because of marketing. It won because it solved real problems that Hardhat ignored.

Speed

The numbers are stark.

In benchmark tests, Foundry compiles and runs tests in 1.44 seconds. Hardhat takes 5.17 seconds. With caching, Foundry drops to 0.45 seconds. Hardhat takes 3.98 seconds.

For large projects, the gap widens dramatically. Benchmarks show Foundry running tests up to 20x faster than Hardhat in some scenarios. Compiling large libraries like OpenZeppelin takes around 9 seconds in Foundry versus 15 seconds in Hardhat.

This matters more now than ever. Post-Merge Ethereum and the rise of L2s have made protocols more complex. More contracts. More tests. More iterations. A framework that scales poorly with large test suites becomes a bottleneck.

The difference comes from architecture. Hardhat runs on Node.js. Every test deploys a local blockchain and uses ethers.js to communicate with contracts. Multiple network calls per test.

Foundry runs natively. Written in Rust. Tests execute directly on an embedded EVM. No JavaScript runtime. No network overhead. Just execution.

Solidity-native testing

With Hardhat, testing Solidity means writing JavaScript.

describe("Token", function () {
  it("should transfer tokens", async function () {
    const [owner, addr1] = await ethers.getSigners();
    await token.transfer(addr1.address, 50);
    expect(await token.balanceOf(addr1.address)).to.equal(50);
  });
});

With Foundry, testing Solidity means writing Solidity.

function testTransfer() public {
    token.transfer(addr1, 50);
    assertEq(token.balanceOf(addr1), 50);
}

No async/await. No ethers.js. No context switching between languages. No BigInt errors from JavaScript's awkward handling of large numbers.

This matters more than syntax. When tests are in Solidity, you think in Solidity. You catch type errors at compile time. You understand gas costs intuitively. You stay in one mental model.

As one developer put it: "It just clicks better in the workflow." Many developers learned JavaScript just to test their contracts. Foundry made that unnecessary.

Built-in fuzz testing

Fuzz testing generates random inputs to find edge cases your unit tests miss. It's one of the most effective techniques for finding vulnerabilities in smart contracts.

Hardhat does not have built-in fuzzing. You need external tools, complex setup, workarounds.

Foundry has native fuzzing. Any test function with parameters becomes a fuzz test automatically. By default, it runs 256 iterations with random inputs.

function testWithdraw(uint256 amount) public {
    vm.assume(amount > 0 && amount <= balance);
    vault.withdraw(amount);
    assertEq(vault.balance(), balance - amount);
}

One team reported running fuzz tests 256 times, executing over 100x faster than equivalent Hardhat setups.

For security-critical code, this is not optional. It's essential.

Cheatcodes

Foundry ships with cheatcodes—special functions that manipulate blockchain state during tests.

vm.prank(address) makes the next call appear to come from a different address. Essential for testing access control.

vm.warp(timestamp) changes the block timestamp. Critical for testing time-dependent logic like vesting or expiration.

vm.deal(address, amount) sets an address's ETH balance. Useful for simulating users with funds.

vm.createSelectFork(url, blockNumber) forks a live network at a specific block. Test against real DeFi protocol state.

Achieving equivalent control in Hardhat requires juggling multiple plugins, complex setup code, and often hacky workarounds. In Foundry, it's built in.

What Hardhat missed

Hardhat is not a bad tool. It has a robust plugin ecosystem, extensive documentation, and a large community. Many production teams still use it.

But Hardhat made strategic mistakes that opened the door for Foundry.

It stayed in JavaScript land

Hardhat bet that Solidity developers would always be willing to learn JavaScript. That was true when there was no alternative.

Once Foundry offered Solidity-native testing, the JavaScript requirement became a liability. Developers who came to crypto for smart contracts did not want to master a second language for testing.

Some developers hate the fact that they have to master another language to test their Solidity contracts. Foundry eliminated that friction.

Plugin dependency instead of core features

Hardhat's plugin ecosystem is both its strength and weakness.

Need fuzzing? Find a plugin. Need better gas reporting? Find a plugin. Need fork testing? Find a plugin.

This works until it doesn't. Plugins have different maintainers, different update cycles, different compatibility guarantees. Coordinating across plugins adds cognitive overhead.

Foundry built the important features into the core. Fuzzing, forking, gas reporting, cheatcodes—all native. One tool. One source of truth.

Performance was never prioritized

Node.js is not fast. It was never going to be fast. Every test in Hardhat pays the JavaScript runtime tax.

Paradigm chose Rust for Foundry specifically because performance matters for developer experience. Fast feedback loops change behavior. Slow feedback loops create friction.

Hardhat could have invested in performance. It did not.

Security tooling as afterthought

Smart contracts secure real money. Testing is not just about correctness—it's about security.

Fuzz testing, invariant testing, and formal verification are not nice-to-haves. They are essential for production code.

Hardhat treated advanced testing as something the ecosystem could provide. Foundry treated it as core functionality that every developer needs.

The hybrid reality

To be fair, Foundry has not completely replaced Hardhat.

Many teams use both. Foundry for fast testing and contract development. Hardhat for scripting, deployment, and JavaScript integration. Some developers run Foundry for unit and fuzz tests, then switch to Hardhat for integration testing and deployments.

Foundry is not perfect. Some developers hit "Stack too deep" errors in complex test setups. Forking can be quirky with certain chains. The learning curve for cheatcodes takes time.

Hardhat's plugin ecosystem still matters for certain workflows. If you're building a full-stack dapp with heavy frontend integration, Hardhat's JavaScript foundation can be an advantage. For complex operations like ZK proofs, Hardhat's error handling is more mature.

But for pure smart contract development—especially security-focused work—Foundry has become the default. If you're a Solidity-focused developer grinding on protocol code, Foundry wins. If you're full-stack with JavaScript everywhere, Hardhat still has a place.

The bigger lesson

Foundry won because it understood what Solidity developers actually needed.

Not more plugins. Not more JavaScript abstractions. Not incremental improvements.

They needed speed. They needed to stay in one language. They needed security tooling built in.

Paradigm built Foundry because they build protocols. They felt the pain firsthand. They knew what was missing.

This is the pattern for dev tools that win: built by practitioners who experience the problem daily, focused on the things that actually matter, unwilling to compromise on fundamentals.

Hardhat had the ecosystem advantage. Foundry had the insight.

Insight won.