# A Hardhat FAQ If you have more questions, remember to join [our Discord server](https://hardhat.org/discord/)! ## Error saying "Missing trie node" _tl;dr: you are forking and not using an [archive node](https://ethereum.stackexchange.com/questions/82664/how-can-i-tell-if-a-node-i-am-using-is-a-full-archive-node)_. When you fork a Network with Hardhat, you are forking it from a given block number. If you don't specify one, the latest block will be used (minus N, where N is chosen to prevent reorgs messing with the fork). Hardhat will use the node to fetch the data it needs. When you ask for data in a node, you are asking about the data _at some specific block_. If you are forking from the latest block, then you'll be able to get this data **even if the node you are using is not an archive node**. But after some minutes, this block you forked will become old enough for the node to stop having historical information about it, and you'll start getting the "Missing trie node". To fix this, use an archive node or a provider like [Alchemy](https://www.alchemy.com/). ## Error saying "function call to a non-contract account" If you get this error in Hardhat: ``` Transaction reverted: function call to a non-contract account ``` It means that your transaction is (at some point) making a call to an address that is not a contract. There are two common scenarios where this happen. ### Wrong argument A simple example of how this could happen is if you have these two contracts: ```solidity contract Foo { function f() public {} } contract FooCaller { function callFoo(Foo foo) public { foo.f(); } } ``` And you execute this code: ```js const [signer] = await ethers.getSigners(); const Foo = await ethers.getContractFactory("Foo"); const foo = await Foo.deploy(); await foo.deployed(); const FooCaller = await ethers.getContractFactory("FooCaller"); const fooCaller = await FooCaller.deploy(); await fooCaller.deployed(); await fooCaller.callFoo(signer.address); ``` In this case, you'll get this error: ``` Error: Transaction reverted: function call to a non-contract account at FooCaller.callFoo (contracts/Foo.sol:7) ``` Did you catch the mistake? The last line of the script uses `signer.address` instead of `foo.address`. Notice that the stack trace tells you exactly in which line the error was (`contracts/Foo.sol:7`). In this example is pretty obvious that that was the problematic line, but in more complex projects the stack trace should point you in the right direction. ### Wrong network Another common cause for this error is to assume that some contract exists when it doesn't. Typically this happens because you are accidentally using the wrong network. For example, maybe you are using Hardhat's [forking mode](https://hardhat.org/guides/mainnet-forking.html), but you are forking the wrong network. If you are forking from a specific block number, it can also be the case that you are using an old block number and the contract you expect to exist hasn't been deployed yet. ## Getting tokens after forking mainnet If you want to fund your accounts with some token (for example DAI) after forking mainnet, there are two things you can try. One is to impersonate an account that has that token, and either use that address or send tokens from it to one of your test accounts. For example: ```js const [signer] = await ethers.getSigners() // impersonate account; replace with an address that actually has your token const addressWithTokens = "0x49a77c5703e877759307175756E6EFDb3669ed77" await network.provider.send("hardhat_impersonateAccount", [addressWithTokens]) const impersonatedSigner = await ethers.getSigner(addressWithTokens) // create the token instance const token = await ethers.getContractAt("ERC20", tokenAddress) // connect it to the impersonated signer and send it to your signer await token.connect(impersonatedSigner).transfer(signer.address, "1000000000000000000") ``` This assumes that the impersonated account has enough ETH to make the transfer. You can send ETH to it first if you want, but keep in mind that if the account is a contract, then it might not accept receiving ETH. Alternatively, since the test accounts start with 1000 ETH each, you can use any on-chain exchange to swap that ether for the token you want. How to do that depends on what exchange you want to use. ## Stubbing/mocking If you want to test a contract that depends on other contract, but you don't own the latter contract (or you do but you want to test the first contract in isolation), you need to either stub or mock that dependency. _If you are not sure about the difference between a stub and a mock, check [this StackOverflow question](https://stackoverflow.com/questions/3459287/whats-the-difference-between-a-mock-stub)_ ### Stubbing If the contract you are testing receives its dependency in some way, you can write a stub contract and use that in your tests. It would be something like this: ```solidity contract ContractToTest { Dependency dependency; constructor (Dependency _dependency) { dependency = _dependency; } function functionToTest() public { // uses `dependency.f` somehow } } contract StubDependency { uint fakeValue; constructor (uint _fakeValue) { fakeValue = _fakeValue; } function f() public returns (uint) { return fakeValue; } } ``` And then in your tests you would deploy `StubDependency` and use that address when you deploy your instance of `ContractToTest` ### Mocking There are two libraries you can use to mock a contract. The first one is [Waffle](https://ethereum-waffle.readthedocs.io/en/latest/mock-contract.html). To use this, you should install and use [hardhat-waffle](https://hardhat.org/plugins/nomiclabs-hardhat-waffle.html) and then make sure that you use `deployMockContract` from the waffle instance in the [Hardhat Runtime Environment](https://hardhat.org/advanced/hardhat-runtime-environment.html): ``` const { waffle } = require("hardhat") const { deployMockContract } = waffle ``` Don't import `deployMockContract` from `@ethereum-waffle/mock-contract` as the Waffle's docs do. The second library you can use is [smock](https://github.com/ethereum-optimism/smock). Check its docs to learn how to use it. ### `hardhat_setCode` This is an advanced method and you should only use it if none of the previous options work for you. The `hardhat_setCode` RPC method lets you change the bytecode of an address while preserving its storage. So you could write a stub contract, get its bytecode (for example, by just deploying it and getting the resulting code, or using the compilation output), and then replace the contract your contract depends on with the stubbed bytecode. This could be useful if you are using [mainnet forking](https://hardhat.org/guides/mainnet-forking.html) and use some existing contract. ## `npx hardhat` doesn't initialize a project This usually means you are already inside a Hardhat project, possibly without realizing it. This happens because there's a `hardhat.cofnig.js` file in an upper directory. To find out where that file is, run `npx hardhat --verbose`. You'll get a log like this: ``` $ npx hardhat --verbose hardhat:core:config Loading Hardhat config from /path/to/some/hardhat.config.js +0ms ... ``` Notice that the first line is telling you the location of the config file that Hardhat is using. ## Estimate the gas cost of a contract deployment (ethers.js) Assuming a `Greeter` contract that expects a string in its constructor, and that you are using the `@nomiclabs/hardhat-ethers` plugin: ```js const Greeter = await ethers.getContractFactory("Greeter") const deployTx = Greeter.getDeployTransaction("hello") const estimatedGas = await ethers.provider.estimateGas(deployTx) console.log(estimatedGas.toString()) // 496906 ``` ## The project cannot be compiled (HH606) Your project has a group of files that cannot be compiled with _any_ version of the solidity compiler. This usually means that you need to either upgrade or downgrade one of your dependencies, or you need to change the pragma version of one of your contracts. Hardhat support for multiple compilers means that you can compile different groups of Solidity files with different compilers. A classic example is having two directories, `contracts/v1` and `contracts/v2`, where the contracts in `v1` need, say, solc v0.6.6, and contracts in `v2` need solc v0.7.8. But in some scenarios, you might have a contract with pragma version `^0.7.0` that imports a contract with `^0.6.0`. **This can never be compiled**. Pragma versions indicate which subset of the compiler versions can be used, and if two pragma versions don't intersect (like in this example), then the files cannot be compiled. Period. If the `^0.6.0` file comes from a dependency, one possible fix is to upgrade that dependency (assuming newer versions use a newer version of solidity). Alternatively, you might need to downgrade the pragma versions of the contracts in your project. ## Tests timeout during forking If you are using the forking feature and your tests are too slow, you might need to **pin the bock number** you are forking from: ```js networks: { hardhat: { forking: { url: "...", blockNumber: 12345 // some block number } } } ``` Keep in mind that this only works if you are using an [archive node](https://ethereum.org/en/developers/docs/nodes-and-clients/#archive-node). After you pin the block number, run your tests a couple of times. Each successive run should be faster than the previous one. The reason this is necessary is related to the way forking works. When you use forking, Hardhat will fetch every piece of data it needs from the node you are forking from. This means that a lot of requests will be done, and if your node is not close to you, then the sum of all the roundtrips will be high. This also means that an **alternative solution is to have a local archive node in your local network**. Pinning the block number makes your tests run faster because, when you do it, Hardhat will cache each request on disk. That's the reason why the second (and successive) test runs should be faster, since each one should need to fetch less remote data. ## Passing arguments to a script You can't pass extra arguments to a script when you use the `run` task. That is, if you have a script like this: ```javascript const someValue = process.argv[2] doSomething(someValue, network.name) ``` You won't be able to pass the value by doing `npx hardhat run script.js "theValue"`, because that argument will be interpreted as if it was passed to the `run` task, not to the script. The workaround is to run the script directly, but if you do that you'll have to require the Hardhat Runtime Environment explicitly. The previous script would become: ```javascript const hre = require("hardhat") const someValue = process.argv[2] doSomething(someValue, hre.network.name) ``` And then you run by doing `node script.js "theValue"`. But this means that you can no longer use Hardhat params, like `--network`. To configure things like that, you can use environment variables: ```bash HARDHAT_NETWORK=mainnet node script.js "theValue" ```