So I'm trying to fork the mainnet using hardhat, impersonate a Dai whale, and transfer its Dai to a hardhat wallet for testing a smart contract, but I'm running into problems.

My code looks like this:

hardhat.config network section:

hardhat: {
      forking: {
        url: process.env.MAINNET_URL || "",

(same as hardhat docs) I tried infura and alchemy urls, same result. I use npx hardhat node to fork the mainnet

I have a script called fundAccount thats supposed to impersonate an account and transfer its Dai balance to a hardhat wallet that looks like this: (I run it with node scripts/fundAccount.js)

const DaiABI = require("../abi/DaiABI.json")
const { ethers } = require("hardhat");
const hre = require("hardhat");

const daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"

async function main() {
  const accountToInpersonate = "0x6F6C07d80D0D433ca389D336e6D1feBEA2489264"
  const accountToFund = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"

  await hre.network.provider.request({
    method: "hardhat_impersonateAccount",
    params: [accountToInpersonate],
  const signer = await ethers.getSigner(accountToInpersonate)

  const daiContract = new ethers.Contract(daiAddress, DaiABI, signer)
  const daiBalance = await daiContract.balanceOf(accountToInpersonate)
  console.log("whale dai balance", daiBalance / 1e18)

  console.log("transfering to", accountToFund)

  await daiContract.connect(signer).transfer(accountToFund, daiBalance)
  const accountBalance = await daiContract.balanceOf(accountToFund)

  console.log("transfer complete")
  console.log("funded account balance", accountBalance / 1e18)

  const whaleBalanceAfter = await daiContract.balanceOf(accountToInpersonate)
  console.log("whale dai balance after", whaleBalanceAfter / 1e18)


  .then(() => process.exit(0))
  .catch((error) => {

My console output looks like this:

enter image description here

so, it looks like it worked, but it doesn't. I know this because I connected the account to my metamask and I can see the 10000 ether (from hardhat) but no Dai shows up. I also tried removing the line that triggers the transfer in my script so it just reads balances and it looks like this:

enter image description here

another thing is I can run the script over and over and get the same result, meaning the whale balance is never emptied, right? Any ideas what I'm doing wrong?


  • 1
    UPDATE: SOLVED still not exactly sure what the problem was, but the things I changed are: in hardhat.config I renamed the network from "hardhat" to "localhost" and added "defaultNetwork: "localhost"" right above "networks" I also ran the script with "npx hardhat run --network localhost scripts/fundAccount.js" I thought i may have had something to do with the RPC url in metamask, but it looks like either "localhost:8545" and "" work the same. If anyone is still able to shed some light on the reason itll help me understand! thanks Oct 3, 2021 at 22:43
  • another update** actually it seems to only work if the network is called hardhat, however when running the deploy and and fundAccount scripts I need to specify localhost as the network??? Oct 4, 2021 at 16:49

4 Answers 4


You're probably not connected to your local node fork.

In hardhat tests, unless you explicitly specify --network localhost, it won't connect to your local fork and will launch a clean test env each run.

Make sure you follow these steps -

  1. Configure hardhat config to fork from a live node URL.
  2. Run npx hardhat node from a shell terminal.
  3. Now to run your hardhat tests npx hardhat test --network localhost.
  4. If you want to use Metamask as well, make sure to connect it to RPC URL http://localhost:8545
  • You don't need to do both 1. and 2.
    – Madbreaks
    Nov 16, 2022 at 22:47

The issues is that you are using ethers.provider which is not pointing to the localhost hardhat chain. once you get the right provider, you can then get the impersonated signer and make transactions.

Step 1. Impersonate a whale's account on localhost

await hre.network.provider.request({
    method: "hardhat_impersonateAccount",
    params: ["0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"],

Step2. Get a provider to localhost where the whale has been impersonated

const provider = ethers.getDefaultProvider("http://localhost:8545");

Step3. Get whale's wallet & make transactions

const signer = await provider.getSigner(
await signer.sendTransaction({
    to: "0x0000000000000000000000000000000000000000",
    value: ethers.utils.parseEther("0.01"),

You run the script via the node script.js command. That creates a new temporary node that resets once you run the command again. To have a persistent effect and actually use the background node you started before, seeing the changes in Metamask too, you should run the script via npx hardhat run script.js


I ran into a similar issue, what fixed it for me was a hardhat.config.js that looked like this (note localhost inside network instead of default hardhat):


module.exports = {
  defaultNetwork: 'localhost',
  networks: {
    localhost: {
      forking: {
        url: "https://eth-mainnet.alchemyapi.io/v2/<your key here>",
        blockNumber: 15023890,

and in my actual script code I setup the provider using the localhost hardhat endpoint:

const provider = new ethers.providers.JsonRpcProvider("");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.