Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix block.chainid returning 0 in view functions #2766

Merged
merged 2 commits into from
May 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quiet-impalas-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Fixed `block.chainid` returning 0 in view functions
Original file line number Diff line number Diff line change
Expand Up @@ -2352,7 +2352,7 @@ Hardhat Network's forking functionality only works with blocks from at least spu
// eslint-disable-next-line @typescript-eslint/dot-notation
...this._vm._common["_chainParams"],
chainId:
this._forkBlockNumber !== undefined &&
this._forkBlockNumber === undefined ||
blockContext.header.number.gte(new BN(this._forkBlockNumber))
? this._configChainId
: this._forkNetworkId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,3 +428,77 @@ contract Foo {
},
topics: {},
};

export const EXAMPLE_CHAIN_ID_CONTRACT = {
sourceCode: `pragma solidity 0.8.14;

contract Example {
uint public chainId;

constructor() {
chainId = block.chainid;
}

function setChainId() public {
chainId = block.chainid;
}

function getChainId() public view returns (uint) {
return block.chainid;
}
}`,
bytecode: {
linkReferences: {},
object:
"608060405234801561001057600080fd5b504660008190555060fa806100266000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80632a30c45e1460415780633408e4701460495780639a8a0592146063575b600080fd5b6047607d565b005b604f6086565b604051605a919060ab565b60405180910390f35b6069608e565b6040516074919060ab565b60405180910390f35b46600081905550565b600046905090565b60005481565b6000819050919050565b60a5816094565b82525050565b600060208201905060be6000830184609e565b9291505056fea2646970667358221220a2dd68e26413cece194c696cf36d8d09330fe96ab11210d5f32ba00d6ca4ca3d64736f6c634300080e0033",
opcodes:
"PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CHAINID PUSH1 0x0 DUP2 SWAP1 SSTORE POP PUSH1 0xFA DUP1 PUSH2 0x26 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3C JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2A30C45E EQ PUSH1 0x41 JUMPI DUP1 PUSH4 0x3408E470 EQ PUSH1 0x49 JUMPI DUP1 PUSH4 0x9A8A0592 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x47 PUSH1 0x7D JUMP JUMPDEST STOP JUMPDEST PUSH1 0x4F PUSH1 0x86 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x5A SWAP2 SWAP1 PUSH1 0xAB JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x69 PUSH1 0x8E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x74 SWAP2 SWAP1 PUSH1 0xAB JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CHAINID PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMP JUMPDEST PUSH1 0x0 CHAINID SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0xA5 DUP2 PUSH1 0x94 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH1 0xBE PUSH1 0x0 DUP4 ADD DUP5 PUSH1 0x9E JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 LOG2 0xDD PUSH9 0xE26413CECE194C696C RETURN PUSH14 0x8D09330FE96AB11210D5F32BA00D PUSH13 0xA4CA3D64736F6C634300080E00 CALLER ",
sourceMap: "25:268:0:-:0;;;74:52;;;;;;;;;;106:13;96:7;:23;;;;25:268;;;;;;",
},
abi: [
{
inputs: [],
stateMutability: "nonpayable",
type: "constructor",
},
{
inputs: [],
name: "chainId",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "getChainId",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "setChainId",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
],
selectors: {
chainId: "0x9a8a0592",
getChainId: "0x3408e470",
setChainId: "0x2a30c45e",
},
topics: {},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { assert } from "chai";
import { BN, toBuffer } from "ethereumjs-util";

import { workaroundWindowsCiFailures } from "../../../../../utils/workaround-windows-ci-failures";
import { EXAMPLE_CHAIN_ID_CONTRACT } from "../../../helpers/contracts";
import { setCWD } from "../../../helpers/cwd";
import {
DEFAULT_ACCOUNTS_ADDRESSES,
DEFAULT_CHAIN_ID,
PROVIDERS,
} from "../../../helpers/providers";
import { deployContract } from "../../../helpers/transactions";

describe("Eth module", function () {
PROVIDERS.forEach(({ name, useProvider, isFork }) => {
if (isFork) {
this.timeout(50000);
}

workaroundWindowsCiFailures.call(this, { isFork });

describe(`${name} provider`, function () {
setCWD();
useProvider();

describe("chain id", function () {
it("should read the right chain id in the constructor", async function () {
const contractAddress = await deployContract(
this.provider,
`0x${EXAMPLE_CHAIN_ID_CONTRACT.bytecode.object}`
);

const chainIdHex = await this.provider.send("eth_call", [
{
to: contractAddress,
from: DEFAULT_ACCOUNTS_ADDRESSES[0],
data: `${EXAMPLE_CHAIN_ID_CONTRACT.selectors.chainId}`,
},
]);

const chainId = new BN(toBuffer(chainIdHex)).toNumber();

assert.equal(chainId, DEFAULT_CHAIN_ID);
});

it("should read the right chain id in a write function", async function () {
const contractAddress = await deployContract(
this.provider,
`0x${EXAMPLE_CHAIN_ID_CONTRACT.bytecode.object}`
);

await this.provider.send("eth_sendTransaction", [
{
to: contractAddress,
from: DEFAULT_ACCOUNTS_ADDRESSES[0],
data: `${EXAMPLE_CHAIN_ID_CONTRACT.selectors.setChainId}`,
},
]);

const chainIdHex = await this.provider.send("eth_call", [
{
to: contractAddress,
from: DEFAULT_ACCOUNTS_ADDRESSES[0],
data: `${EXAMPLE_CHAIN_ID_CONTRACT.selectors.chainId}`,
},
]);

const chainId = new BN(toBuffer(chainIdHex)).toNumber();

assert.equal(chainId, DEFAULT_CHAIN_ID);
});

it("should read the right chain id in a view function", async function () {
const contractAddress = await deployContract(
this.provider,
`0x${EXAMPLE_CHAIN_ID_CONTRACT.bytecode.object}`
);

const chainIdHex = await this.provider.send("eth_call", [
{
to: contractAddress,
from: DEFAULT_ACCOUNTS_ADDRESSES[0],
data: `${EXAMPLE_CHAIN_ID_CONTRACT.selectors.getChainId}`,
},
]);

const chainId = new BN(toBuffer(chainIdHex)).toNumber();

assert.equal(chainId, DEFAULT_CHAIN_ID);
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -696,10 +696,6 @@ contract C {
});

it("should use the proper chain ID", async function () {
if (!isFork) {
this.skip();
}

const [_, compilerOutput] = await compileLiteral(`
contract ChainIdGetter {
event ChainId(uint i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1041,10 +1041,6 @@ describe("Eth module", function () {
});

it("should use the proper chain ID", async function () {
if (!isFork) {
this.skip();
}

// arrange: deploy a contract that will emit the chain ID:
const [_, compilerOutput] = await compileLiteral(`
contract ChainIdEmitter {
Expand Down