From 8dcc4b9e884583bea18cc02c3b9cbe986a53f323 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 11 Jun 2025 19:48:25 +0200 Subject: [PATCH] Improve test of Blockhash.sol: all cases on supported and unsupported chains (#5732) --- test/utils/Blockhash.test.js | 101 +++++++++++++++-------------------- 1 file changed, 43 insertions(+), 58 deletions(-) diff --git a/test/utils/Blockhash.test.js b/test/utils/Blockhash.test.js index a3de2655e..574ae3eea 100644 --- a/test/utils/Blockhash.test.js +++ b/test/utils/Blockhash.test.js @@ -1,76 +1,61 @@ -const { ethers } = require('hardhat'); +const { ethers, network } = require('hardhat'); const { expect } = require('chai'); -const { loadFixture, mine, mineUpTo, setCode } = require('@nomicfoundation/hardhat-network-helpers'); +const { loadFixture, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers'); const { impersonate } = require('../helpers/account'); -async function fixture() { - const mock = await ethers.deployContract('$Blockhash'); - return { mock }; -} - const HISTORY_STORAGE_ADDRESS = '0x0000F90827F1C53a10cb7A02335B175320002935'; const SYSTEM_ADDRESS = '0xfffffffffffffffffffffffffffffffffffffffe'; const HISTORY_SERVE_WINDOW = 8191; const BLOCKHASH_SERVE_WINDOW = 256; +async function fixture() { + return { + mock: await ethers.deployContract('$Blockhash'), + systemSigner: await impersonate(SYSTEM_ADDRESS), + latestBlock: await ethers.provider.getBlock('latest'), + }; +} + describe('Blockhash', function () { - before(async function () { + beforeEach(async function () { Object.assign(this, await loadFixture(fixture)); - - impersonate(SYSTEM_ADDRESS); - this.systemSigner = await ethers.getSigner(SYSTEM_ADDRESS); }); - it('recent block', async function () { - await mine(); + for (const supported of [true, false]) { + describe(`${supported ? 'supported' : 'unsupported'} chain`, function () { + beforeEach(async function () { + if (supported) { + await this.systemSigner.sendTransaction({ to: HISTORY_STORAGE_ADDRESS, data: this.latestBlock.hash }); + } else { + // `setCode` in hardhat-network-helpers doesn't support empty code :/ + await network.provider.request({ method: 'hardhat_setCode', params: [HISTORY_STORAGE_ADDRESS, '0x'] }); + } + }); - const mostRecentBlock = (await ethers.provider.getBlock('latest')).number; - const blockToCheck = mostRecentBlock - 1; - const fetchedHash = (await ethers.provider.getBlock(blockToCheck)).hash; - await expect(this.mock.$blockHash(blockToCheck)).to.eventually.equal(fetchedHash); - }); + it('recent block', async function () { + // fast forward (less than blockhash serve window) + await mineUpTo(this.latestBlock.number + BLOCKHASH_SERVE_WINDOW); + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal(this.latestBlock.hash); + }); - it('old block', async function () { - await mine(); + it('old block', async function () { + // fast forward (more than blockhash serve window) + await mineUpTo(this.latestBlock.number + BLOCKHASH_SERVE_WINDOW + 1); + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal( + supported ? this.latestBlock.hash : ethers.ZeroHash, + ); + }); - const mostRecentBlock = await ethers.provider.getBlock('latest'); + it('very old block', async function () { + // fast forward (more than history serve window) + await mineUpTo(this.latestBlock.number + HISTORY_SERVE_WINDOW + 10); + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal(ethers.ZeroHash); + }); - // Call the history address with the most recent block hash - await this.systemSigner.sendTransaction({ - to: HISTORY_STORAGE_ADDRESS, - data: mostRecentBlock.hash, + it('future block', async function () { + // check history access in the future + await expect(this.mock.$blockHash(this.latestBlock.number + 10)).to.eventually.equal(ethers.ZeroHash); + }); }); - - await mineUpTo(mostRecentBlock.number + BLOCKHASH_SERVE_WINDOW + 10); - - // Verify blockhash after setting history - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(mostRecentBlock.hash); - }); - - it('very old block', async function () { - await mine(); - - const mostRecentBlock = await ethers.provider.getBlock('latest'); - await mineUpTo(mostRecentBlock.number + HISTORY_SERVE_WINDOW + 10); - - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(ethers.ZeroHash); - }); - - it('future block', async function () { - await mine(); - - const mostRecentBlock = await ethers.provider.getBlock('latest'); - const blockToCheck = mostRecentBlock.number + 10; - await expect(this.mock.$blockHash(blockToCheck)).to.eventually.equal(ethers.ZeroHash); - }); - - it('unsupported chain', async function () { - await setCode(HISTORY_STORAGE_ADDRESS, '0x00'); - - const mostRecentBlock = await ethers.provider.getBlock('latest'); - await mineUpTo(mostRecentBlock.number + BLOCKHASH_SERVE_WINDOW + 10); - - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(ethers.ZeroHash); - await expect(this.mock.$blockHash(mostRecentBlock.number + 20)).to.eventually.not.equal(ethers.ZeroHash); - }); + } });