diff --git a/.changeset/new-rocks-report.md b/.changeset/new-rocks-report.md new file mode 100644 index 0000000000..fcda419f78 --- /dev/null +++ b/.changeset/new-rocks-report.md @@ -0,0 +1,5 @@ +--- +"hardhat": patch +--- + +Fixed a bug when `hardhat_setStorageAt` was used in untouched addresses diff --git a/.github/workflows/hardhat-network-helpers-ci.yml b/.github/workflows/hardhat-network-helpers-ci.yml index 5858a8aff5..455d5ff7c6 100644 --- a/.github/workflows/hardhat-network-helpers-ci.yml +++ b/.github/workflows/hardhat-network-helpers-ci.yml @@ -4,6 +4,7 @@ on: push: branches: [$default-branch] paths: + - "packages/hardhat-core/**" - "packages/hardhat-network-helpers/**" - "packages/hardhat-common/**" - "config/**" @@ -11,6 +12,7 @@ on: branches: - "**" paths: + - "packages/hardhat-core/**" - "packages/hardhat-network-helpers/**" - "packages/hardhat-common/**" - "config/**" diff --git a/packages/hardhat-core/src/internal/hardhat-network/provider/node.ts b/packages/hardhat-core/src/internal/hardhat-network/provider/node.ts index 8799dec047..0e4b83755f 100644 --- a/packages/hardhat-core/src/internal/hardhat-network/provider/node.ts +++ b/packages/hardhat-core/src/internal/hardhat-network/provider/node.ts @@ -1430,6 +1430,12 @@ Hardhat Network's forking functionality only works with blocks from at least spu positionIndex: bigint, value: Buffer ) { + // create the account if it doesn't exist + const account = await this._stateManager.getAccount(address); + if (account === undefined) { + await this._stateManager.putAccount(address, new Account()); + } + await this._stateManager.putContractStorage( address, setLengthLeft(bigIntToBytes(positionIndex), 32), diff --git a/packages/hardhat-core/test/internal/hardhat-network/provider/modules/hardhat.ts b/packages/hardhat-core/test/internal/hardhat-network/provider/modules/hardhat.ts index bd24a7de1b..815be7672b 100644 --- a/packages/hardhat-core/test/internal/hardhat-network/provider/modules/hardhat.ts +++ b/packages/hardhat-core/test/internal/hardhat-network/provider/modules/hardhat.ts @@ -28,6 +28,7 @@ import { import { compileLiteral } from "../../stack-traces/compilation"; import { getPendingBaseFeePerGas } from "../../helpers/getPendingBaseFeePerGas"; import { RpcBlockOutput } from "../../../../../src/internal/hardhat-network/provider/output"; +import { randomAddressString } from "../../../../../src/internal/hardhat-network/provider/utils/random"; import * as BigIntUtils from "../../../../../src/internal/util/bigint"; import { EXAMPLE_DIFFICULTY_CONTRACT } from "../../helpers/contracts"; import { HardhatMetadata } from "../../../../../src/internal/core/jsonrpc/types/output/metadata"; @@ -1697,6 +1698,21 @@ describe("Hardhat module", function () { ); assert.strictEqual(balancePreviousBlockAfterRevert, targetBalance1); }); + + it("should work with accounts that weren't interacted with before", async function () { + const targetAddress = randomAddressString(); + await this.provider.send("hardhat_setBalance", [ + targetAddress, + numberToRpcQuantity(123), + ]); + + const resultingBalance = await this.provider.send("eth_getBalance", [ + targetAddress, + "latest", + ]); + + assert.equal(BigInt(resultingBalance), 123n); + }); }); describe("hardhat_setCode", function () { @@ -1893,6 +1909,22 @@ describe("Hardhat module", function () { ).stateRoot; assert.equal(newStateRoot, oldStateRoot); }); + + it("should work with accounts that weren't interacted with before", async function () { + const targetAddress = randomAddressString(); + const targetCode = "0x0123456789abcdef"; + await this.provider.send("hardhat_setCode", [ + targetAddress, + targetCode, + ]); + + const actualCode = await this.provider.send("eth_getCode", [ + targetAddress, + "latest", + ]); + + assert.equal(actualCode, targetCode); + }); }); describe("hardhat_setNonce", function () { @@ -2076,6 +2108,21 @@ describe("Hardhat module", function () { "Cannot set account nonce when the transaction pool is not empty" ); }); + + it("should work with accounts that weren't interacted with before", async function () { + const targetAddress = randomAddressString(); + await this.provider.send("hardhat_setNonce", [ + targetAddress, + numberToRpcQuantity(123), + ]); + + const resultingNonce = await this.provider.send( + "eth_getTransactionCount", + [targetAddress, "latest"] + ); + + assert.equal(BigInt(resultingNonce), 123n); + }); }); describe("hardhat_setStorageAt", function () { @@ -2253,6 +2300,23 @@ describe("Hardhat module", function () { targetStorageValue ); }); + + it("should work with accounts that weren't interacted with before", async function () { + const targetAddress = randomAddressString(); + const targetStorageValue = 99; + await this.provider.send("hardhat_setStorageAt", [ + targetAddress, + numberToRpcQuantity(0), + `0x${BigIntUtils.toEvmWord(targetStorageValue)}`, + ]); + + const resultingStorageValue = await this.provider.send( + "eth_getStorageAt", + [targetAddress, numberToRpcStorageSlot(0), "latest"] + ); + + assert.equal(resultingStorageValue, targetStorageValue); + }); }); describe("hardhat_dropTransaction", function () {