|
@@ -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();
|
|
|
-
|
|
|
- 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('old block', async function () {
|
|
|
- await mine();
|
|
|
-
|
|
|
- const mostRecentBlock = await ethers.provider.getBlock('latest');
|
|
|
-
|
|
|
- // Call the history address with the most recent block hash
|
|
|
- await this.systemSigner.sendTransaction({
|
|
|
- to: HISTORY_STORAGE_ADDRESS,
|
|
|
- data: mostRecentBlock.hash,
|
|
|
+ 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'] });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ 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 () {
|
|
|
+ // 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,
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+
|
|
|
+ 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);
|
|
|
- });
|
|
|
+ }
|
|
|
});
|