Skip to content

Commit

Permalink
Merge pull request #3572 from NomicFoundation/add-reset-helper
Browse files Browse the repository at this point in the history
Add a new 'reset' network helper
  • Loading branch information
fvictorio committed Jan 13, 2023
2 parents 371b1f7 + 8a4ad9d commit 9ad5132
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-humans-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomicfoundation/hardhat-network-helpers": patch
---

Added a new 'reset' network helper
10 changes: 10 additions & 0 deletions docs/src/content/hardhat-network-helpers/docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,13 @@ Sets the PREVRANDAO value of the next block.
Parameters:

- `prevRandao`: The new PREVRANDAO value to use.

## Other helpers

### `reset([url], [blockNumber])`

Resets the Hardhat Network. The result of calling this method depends on which arguments are provided:

- If a `url` and a `blockNumber` are passed, the network will be reset to a forked state using that URL and block number.
- If no `blockNumber` is provided, the network will be reset to a forked state using the latest block number that can be forked with a low probability of being reorged.
- If the function is called without arguments, the network will be reset to a local, non-forked state.
Original file line number Diff line number Diff line change
Expand Up @@ -102,33 +102,22 @@ Once you've got a local instance of the mainnet chain state, setting that state

## Resetting the fork

You can manipulate forking during runtime to reset back to a fresh forked state, fork from another block number or disable forking by calling `hardhat_reset`:
You can reset the network with the [`reset`](</hardhat-network-helpers/docs/reference#reset([url],-[blocknumber])>) network helper:

```ts
await network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: "https://eth-mainnet.alchemyapi.io/v2/<key>",
blockNumber: 14390000,
},
},
],
});
```js
const helpers = require("@nomicfoundation/hardhat-network-helpers");

await helpers.reset(url, blockNumber);
```

You can disable forking by passing empty params:
Both the `url` and the `blockNumber` can be different to the ones that are currently being used by the fork.

To reset the network to a local, non-forked state, call the helper without any arguments:

```ts
await network.provider.request({
method: "hardhat_reset",
params: [],
});
await helpers.reset();
```

This will reset Hardhat Network, starting a new instance in the state described [here](../reference/#initial-state).

## Using a custom hardfork history

If you're forking an unusual network, and if you want to execute EVM code in the context of a historical block retrieved from that network, then you will need to configure Hardhat Network to know which hardforks to apply to which blocks. (If you're forking a well-known network, Hardhat Network will automatically choose the right hardfork for the execution of your EVM code, based on known histories of public networks, so you can safely ignore this section.)
Expand Down
27 changes: 26 additions & 1 deletion docs/src/content/hardhat-network/docs/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,32 @@ Also note that blocks created via `hardhat_mine` may not trigger new-block event

#### `hardhat_reset`

See the [Mainnet Forking guide](./guides/forking-other-networks.md#resetting-the-fork)
You can manipulate forking during runtime to reset back to a fresh forked state, fork from another block number or disable forking by calling `hardhat_reset`:

```ts
await network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: "https://eth-mainnet.alchemyapi.io/v2/<key>",
blockNumber: 14390000,
},
},
],
});
```

You can disable forking by passing empty params:

```ts
await network.provider.request({
method: "hardhat_reset",
params: [],
});
```

This will reset the Hardhat Network, starting a new instance in the state described [here](#initial-state).

#### `hardhat_setBalance`

Expand Down
39 changes: 39 additions & 0 deletions packages/hardhat-network-helpers/src/helpers/reset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { NumberLike } from "../types";
import { getHardhatProvider, toNumber } from "../utils";

export async function reset(
url?: string,
blockNumber?: NumberLike
): Promise<void> {
const provider = await getHardhatProvider();

if (url === undefined) {
await provider.request({
method: "hardhat_reset",
params: [],
});
} else if (blockNumber === undefined) {
await provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: url,
},
},
],
});
} else {
await provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: url,
blockNumber: toNumber(blockNumber),
},
},
],
});
}
}
1 change: 1 addition & 0 deletions packages/hardhat-network-helpers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export { setStorageAt } from "./helpers/setStorageAt";
export { setNextBlockBaseFeePerGas } from "./helpers/setNextBlockBaseFeePerGas";
export { stopImpersonatingAccount } from "./helpers/stopImpersonatingAccount";
export { takeSnapshot, SnapshotRestorer } from "./helpers/takeSnapshot";
export { reset } from "./helpers/reset";
4 changes: 4 additions & 0 deletions packages/hardhat-network-helpers/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export async function getHardhatProvider(): Promise<EIP1193Provider> {
return hre.network.provider;
}

export function toNumber(x: NumberLike): number {
return Number(toRpcQuantity(x));
}

export function toBigInt(x: NumberLike): bigint {
return BigInt(toRpcQuantity(x));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cache/
58 changes: 58 additions & 0 deletions packages/hardhat-network-helpers/test/helpers/reset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { assert } from "chai";

import * as hh from "../../src";
import { INFURA_URL } from "../setup";
import { useEnvironment } from "../test-utils";

describe("resetWithoutFork", function () {
useEnvironment("simple");

it("should reset the non-forked network", async function () {
assert.equal(await hh.time.latestBlock(), 0);
await hh.mine();
assert.equal(await hh.time.latestBlock(), 1);
await hh.reset();
assert.equal(await hh.time.latestBlock(), 0);
});

it("should reset with a url", async function () {
if (INFURA_URL === undefined) {
this.skip();
}
this.timeout(60000);

// fork mainnet
await hh.reset(INFURA_URL);

const mainnetBlockNumber = await hh.time.latestBlock();

// fork goerli
await hh.reset(INFURA_URL.replace("mainnet", "goerli"));

const goerliBlockNumber = await hh.time.latestBlock();

const blockNumberDelta = Math.abs(mainnetBlockNumber - goerliBlockNumber);

// check that there is a significative difference between the latest
// block numbers of each chain
assert.isAbove(blockNumberDelta, 100);
});

it("should reset with a url and block number", async function () {
if (INFURA_URL === undefined) {
this.skip();
}
this.timeout(60000);

// fork mainnet
await hh.reset(INFURA_URL);

const mainnetBlockNumber = await hh.time.latestBlock();
assert.isAbove(mainnetBlockNumber, 1_000_000);

// fork an older block number
await hh.reset(INFURA_URL, mainnetBlockNumber - 1000);
const olderMainnetBlockNumber = await hh.time.latestBlock();
assert.equal(olderMainnetBlockNumber, mainnetBlockNumber - 1000);
});
});
13 changes: 13 additions & 0 deletions packages/hardhat-network-helpers/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,16 @@ import chai from "chai";
import chaiAsPromised from "chai-as-promised";

chai.use(chaiAsPromised);

function getEnv(key: string): string | undefined {
const variable = process.env[key];
if (variable === undefined || variable === "") {
return undefined;
}

const trimmed = variable.trim();

return trimmed.length === 0 ? undefined : trimmed;
}

export const INFURA_URL = getEnv("INFURA_URL");

0 comments on commit 9ad5132

Please sign in to comment.