Improve test of Blockhash.sol: all cases on supported and unsupported chains (#5732)

This commit is contained in:
Hadrien Croubois
2025-06-11 19:48:25 +02:00
committed by GitHub
parent 78c8da8648
commit 8dcc4b9e88

View File

@ -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);
});
}
});