Skip to content

Commit

Permalink
Merge pull request #2766 from NomicFoundation/francovictorio/hh-688/c…
Browse files Browse the repository at this point in the history
…hainid-zero-view-functions

Fix `block.chainid` returning 0 in view functions
  • Loading branch information
fvictorio committed May 30, 2022
2 parents 868f0bf + 73beb27 commit bc1db44
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-impalas-cry.md
@@ -0,0 +1,5 @@
---
"hardhat": patch
---

Fixed `block.chainid` returning 0 in view functions
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
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: {},
};
@@ -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);
});
});
});
});
});
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
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

0 comments on commit bc1db44

Please sign in to comment.