|
1 |
| -const { ethers } = require('hardhat'); |
| 1 | +const { ethers, network } = require('hardhat'); |
2 | 2 | const { expect } = require('chai');
|
3 |
| -const { loadFixture, mine, mineUpTo, setCode } = require('@nomicfoundation/hardhat-network-helpers'); |
| 3 | +const { loadFixture, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers'); |
4 | 4 | const { impersonate } = require('../helpers/account');
|
5 | 5 |
|
6 |
| -async function fixture() { |
7 |
| - const mock = await ethers.deployContract('$Blockhash'); |
8 |
| - return { mock }; |
9 |
| -} |
10 |
| - |
11 | 6 | const HISTORY_STORAGE_ADDRESS = '0x0000F90827F1C53a10cb7A02335B175320002935';
|
12 | 7 | const SYSTEM_ADDRESS = '0xfffffffffffffffffffffffffffffffffffffffe';
|
13 | 8 | const HISTORY_SERVE_WINDOW = 8191;
|
14 | 9 | const BLOCKHASH_SERVE_WINDOW = 256;
|
15 | 10 |
|
| 11 | +async function fixture() { |
| 12 | + return { |
| 13 | + mock: await ethers.deployContract('$Blockhash'), |
| 14 | + systemSigner: await impersonate(SYSTEM_ADDRESS), |
| 15 | + latestBlock: await ethers.provider.getBlock('latest'), |
| 16 | + }; |
| 17 | +} |
| 18 | + |
16 | 19 | describe('Blockhash', function () {
|
17 |
| - before(async function () { |
| 20 | + beforeEach(async function () { |
18 | 21 | Object.assign(this, await loadFixture(fixture));
|
19 |
| - |
20 |
| - impersonate(SYSTEM_ADDRESS); |
21 |
| - this.systemSigner = await ethers.getSigner(SYSTEM_ADDRESS); |
22 | 22 | });
|
23 | 23 |
|
24 |
| - it('recent block', async function () { |
25 |
| - await mine(); |
26 |
| - |
27 |
| - const mostRecentBlock = (await ethers.provider.getBlock('latest')).number; |
28 |
| - const blockToCheck = mostRecentBlock - 1; |
29 |
| - const fetchedHash = (await ethers.provider.getBlock(blockToCheck)).hash; |
30 |
| - await expect(this.mock.$blockHash(blockToCheck)).to.eventually.equal(fetchedHash); |
31 |
| - }); |
32 |
| - |
33 |
| - it('old block', async function () { |
34 |
| - await mine(); |
35 |
| - |
36 |
| - const mostRecentBlock = await ethers.provider.getBlock('latest'); |
37 |
| - |
38 |
| - // Call the history address with the most recent block hash |
39 |
| - await this.systemSigner.sendTransaction({ |
40 |
| - to: HISTORY_STORAGE_ADDRESS, |
41 |
| - data: mostRecentBlock.hash, |
| 24 | + for (const supported of [true, false]) { |
| 25 | + describe(`${supported ? 'supported' : 'unsupported'} chain`, function () { |
| 26 | + beforeEach(async function () { |
| 27 | + if (supported) { |
| 28 | + await this.systemSigner.sendTransaction({ to: HISTORY_STORAGE_ADDRESS, data: this.latestBlock.hash }); |
| 29 | + } else { |
| 30 | + // `setCode` in hardhat-network-helpers doesn't support empty code :/ |
| 31 | + await network.provider.request({ method: 'hardhat_setCode', params: [HISTORY_STORAGE_ADDRESS, '0x'] }); |
| 32 | + } |
| 33 | + }); |
| 34 | + |
| 35 | + it('recent block', async function () { |
| 36 | + // fast forward (less than blockhash serve window) |
| 37 | + await mineUpTo(this.latestBlock.number + BLOCKHASH_SERVE_WINDOW); |
| 38 | + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal(this.latestBlock.hash); |
| 39 | + }); |
| 40 | + |
| 41 | + it('old block', async function () { |
| 42 | + // fast forward (more than blockhash serve window) |
| 43 | + await mineUpTo(this.latestBlock.number + BLOCKHASH_SERVE_WINDOW + 1); |
| 44 | + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal( |
| 45 | + supported ? this.latestBlock.hash : ethers.ZeroHash, |
| 46 | + ); |
| 47 | + }); |
| 48 | + |
| 49 | + it('very old block', async function () { |
| 50 | + // fast forward (more than history serve window) |
| 51 | + await mineUpTo(this.latestBlock.number + HISTORY_SERVE_WINDOW + 10); |
| 52 | + await expect(this.mock.$blockHash(this.latestBlock.number)).to.eventually.equal(ethers.ZeroHash); |
| 53 | + }); |
| 54 | + |
| 55 | + it('future block', async function () { |
| 56 | + // check history access in the future |
| 57 | + await expect(this.mock.$blockHash(this.latestBlock.number + 10)).to.eventually.equal(ethers.ZeroHash); |
| 58 | + }); |
42 | 59 | });
|
43 |
| - |
44 |
| - await mineUpTo(mostRecentBlock.number + BLOCKHASH_SERVE_WINDOW + 10); |
45 |
| - |
46 |
| - // Verify blockhash after setting history |
47 |
| - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(mostRecentBlock.hash); |
48 |
| - }); |
49 |
| - |
50 |
| - it('very old block', async function () { |
51 |
| - await mine(); |
52 |
| - |
53 |
| - const mostRecentBlock = await ethers.provider.getBlock('latest'); |
54 |
| - await mineUpTo(mostRecentBlock.number + HISTORY_SERVE_WINDOW + 10); |
55 |
| - |
56 |
| - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(ethers.ZeroHash); |
57 |
| - }); |
58 |
| - |
59 |
| - it('future block', async function () { |
60 |
| - await mine(); |
61 |
| - |
62 |
| - const mostRecentBlock = await ethers.provider.getBlock('latest'); |
63 |
| - const blockToCheck = mostRecentBlock.number + 10; |
64 |
| - await expect(this.mock.$blockHash(blockToCheck)).to.eventually.equal(ethers.ZeroHash); |
65 |
| - }); |
66 |
| - |
67 |
| - it('unsupported chain', async function () { |
68 |
| - await setCode(HISTORY_STORAGE_ADDRESS, '0x00'); |
69 |
| - |
70 |
| - const mostRecentBlock = await ethers.provider.getBlock('latest'); |
71 |
| - await mineUpTo(mostRecentBlock.number + BLOCKHASH_SERVE_WINDOW + 10); |
72 |
| - |
73 |
| - await expect(this.mock.$blockHash(mostRecentBlock.number)).to.eventually.equal(ethers.ZeroHash); |
74 |
| - await expect(this.mock.$blockHash(mostRecentBlock.number + 20)).to.eventually.not.equal(ethers.ZeroHash); |
75 |
| - }); |
| 60 | + } |
76 | 61 | });
|
0 commit comments