diff --git a/e2e/deployment/config/controller.test.ts b/e2e/deployment/config/controller.test.ts index b74a6a4d9..d289fa205 100644 --- a/e2e/deployment/config/controller.test.ts +++ b/e2e/deployment/config/controller.test.ts @@ -1,12 +1,13 @@ import { expect } from 'chai' import hre, { ethers } from 'hardhat' +import { chainIdIsL2 } from '../../../cli/utils' import { NamedAccounts } from '../../../tasks/type-extensions' describe('Controller configuration', () => { const { contracts, getNamedAccounts } = hre.graph() const { Controller } = contracts - const proxyContracts = [ + const proxyContractsL1 = [ 'Curation', 'GNS', 'DisputeManager', @@ -18,12 +19,29 @@ describe('Controller configuration', () => { 'L1Reservoir', ] + const proxyContractsL2 = [ + 'Curation', + 'GNS', + 'DisputeManager', + 'EpochManager', + 'RewardsManager', + 'Staking', + 'L2GraphToken', + 'L2GraphTokenGateway', + 'L2Reservoir', + ] + let namedAccounts: NamedAccounts before(async () => { namedAccounts = await getNamedAccounts() }) + it('protocol should be unpaused', async function () { + const paused = await contracts.Controller.paused() + expect(paused).eq(false) + }) + const proxyShouldMatchDeployed = async (contractName: string) => { // remove L1/L2 prefix, contracts are not registered as L1/L2 on controller const name = contractName.replace(/(^L1|L2)/gi, '') @@ -45,6 +63,8 @@ describe('Controller configuration', () => { }) describe('proxy contract', async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + const proxyContracts = chainIdIsL2(chainId) ? proxyContractsL2 : proxyContractsL1 for (const contract of proxyContracts) { it(`${contract} should match deployed`, async function () { await proxyShouldMatchDeployed(contract) diff --git a/e2e/deployment/config/graphToken.test.ts b/e2e/deployment/config/graphToken.test.ts index 0d719f4f4..73f80f77a 100644 --- a/e2e/deployment/config/graphToken.test.ts +++ b/e2e/deployment/config/graphToken.test.ts @@ -23,7 +23,7 @@ describe('GraphToken configuration', () => { it('deployer should not be minter', async function () { const deployer = await getDeployer() const deployerIsMinter = await GraphToken.isMinter(deployer.address) - hre.network.config.chainId === 1337 ? this.skip() : expect(deployerIsMinter).eq(false) + expect(deployerIsMinter).eq(false) }) it('RewardsManager should not be a minter', async function () { diff --git a/e2e/deployment/config/l1/bridgeEscrow.test.ts b/e2e/deployment/config/l1/bridgeEscrow.test.ts index 369d46df2..bda40fbea 100644 --- a/e2e/deployment/config/l1/bridgeEscrow.test.ts +++ b/e2e/deployment/config/l1/bridgeEscrow.test.ts @@ -1,11 +1,17 @@ import { expect } from 'chai' import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('BridgeEscrow configuration', () => { +describe('[L1] BridgeEscrow configuration', () => { const { contracts: { Controller, BridgeEscrow }, } = hre.graph() + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + }) + it('should be controlled by Controller', async function () { const controller = await BridgeEscrow.controller() expect(controller).eq(Controller.address) diff --git a/e2e/deployment/config/l1/graphToken.test.ts b/e2e/deployment/config/l1/graphToken.test.ts index 980901ce5..285094271 100644 --- a/e2e/deployment/config/l1/graphToken.test.ts +++ b/e2e/deployment/config/l1/graphToken.test.ts @@ -1,11 +1,17 @@ import { expect } from 'chai' import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('GraphToken configuration', () => { +describe('[L1] GraphToken configuration', () => { const { contracts: { GraphToken, L1Reservoir }, } = hre.graph() + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + }) + it('L1Reservoir should be a minter', async function () { const deployerIsMinter = await GraphToken.isMinter(L1Reservoir.address) expect(deployerIsMinter).eq(true) diff --git a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts index b2c141524..37a712dab 100644 --- a/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts +++ b/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts @@ -1,13 +1,88 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('L1GraphTokenGateway configuration', () => { +describe('[L1] L1GraphTokenGateway configuration', () => { const { contracts: { Controller, L1GraphTokenGateway }, + getTestAccounts, } = hre.graph() + let unauthorized: SignerWithAddress + + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + + unauthorized = (await getTestAccounts())[0] + }) + + it('bridge should be unpaused', async function () { + const paused = await L1GraphTokenGateway.paused() + expect(paused).eq(false) + }) + it('should be controlled by Controller', async function () { const controller = await L1GraphTokenGateway.controller() expect(controller).eq(Controller.address) }) + + describe('calls with unauthorized user', () => { + it('initialize should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).initialize(unauthorized.address) + await expect(tx).revertedWith('Caller must be the implementation') + }) + + it('setArbitrumAddresses should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).setArbitrumAddresses( + unauthorized.address, + unauthorized.address, + ) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('setL2TokenAddress should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).setL2TokenAddress(unauthorized.address) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('setL2CounterpartAddress should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).setL2CounterpartAddress( + unauthorized.address, + ) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('setEscrowAddress should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).setEscrowAddress(unauthorized.address) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('addToCallhookWhitelist should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).addToCallhookWhitelist( + unauthorized.address, + ) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('removeFromCallhookWhitelist should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).removeFromCallhookWhitelist( + unauthorized.address, + ) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('finalizeInboundTransfer should revert', async function () { + const tx = L1GraphTokenGateway.connect(unauthorized).finalizeInboundTransfer( + unauthorized.address, + unauthorized.address, + unauthorized.address, + '100', + '0x00', + ) + + await expect(tx).revertedWith('ONLY_COUNTERPART_GATEWAY') + }) + }) }) diff --git a/e2e/deployment/config/l1/l1Reservoir.test.ts b/e2e/deployment/config/l1/l1Reservoir.test.ts index 873cd8f9b..b9d71ca8d 100644 --- a/e2e/deployment/config/l1/l1Reservoir.test.ts +++ b/e2e/deployment/config/l1/l1Reservoir.test.ts @@ -1,13 +1,19 @@ import { expect } from 'chai' import hre from 'hardhat' import { getItemValue } from '../../../../cli/config' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('L1Reservoir configuration', () => { +describe('[L1] L1Reservoir configuration', () => { const { graphConfig, contracts: { Controller, L1Reservoir }, } = hre.graph() + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + }) + it('should be controlled by Controller', async function () { const controller = await L1Reservoir.controller() expect(controller).eq(Controller.address) diff --git a/e2e/deployment/config/l2/l2GraphToken.test.ts b/e2e/deployment/config/l2/l2GraphToken.test.ts new file mode 100644 index 000000000..33baa0804 --- /dev/null +++ b/e2e/deployment/config/l2/l2GraphToken.test.ts @@ -0,0 +1,43 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { expect } from 'chai' +import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' + +describe('[L2] L2GraphToken', () => { + const { + contracts: { L2GraphToken }, + getTestAccounts, + } = hre.graph() + + let unauthorized: SignerWithAddress + + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (!chainIdIsL2(chainId)) this.skip() + + unauthorized = (await getTestAccounts())[0] + }) + + describe('calls with unauthorized user', () => { + it('mint should revert', async function () { + const tx = L2GraphToken.connect(unauthorized).mint( + unauthorized.address, + '1000000000000000000000', + ) + await expect(tx).revertedWith('Only minter can call') + }) + + it('bridgeMint should revert', async function () { + const tx = L2GraphToken.connect(unauthorized).bridgeMint( + unauthorized.address, + '1000000000000000000000', + ) + await expect(tx).revertedWith('NOT_GATEWAY') + }) + + it('setGateway should revert', async function () { + const tx = L2GraphToken.connect(unauthorized).setGateway(unauthorized.address) + await expect(tx).revertedWith('Only Governor can call') + }) + }) +}) diff --git a/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts new file mode 100644 index 000000000..37347c65b --- /dev/null +++ b/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts @@ -0,0 +1,66 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { expect } from 'chai' +import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' + +describe('[L2] L2GraphTokenGateway configuration', () => { + const { + contracts: { Controller, L2GraphTokenGateway }, + getTestAccounts, + } = hre.graph() + + let unauthorized: SignerWithAddress + + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (!chainIdIsL2(chainId)) this.skip() + + unauthorized = (await getTestAccounts())[0] + }) + + it('bridge should be unpaused', async function () { + const paused = await L2GraphTokenGateway.paused() + expect(paused).eq(false) + }) + + it('should be controlled by Controller', async function () { + const controller = await L2GraphTokenGateway.controller() + expect(controller).eq(Controller.address) + }) + + describe('calls with unauthorized user', () => { + it('initialize should revert', async function () { + const tx = L2GraphTokenGateway.connect(unauthorized).initialize(unauthorized.address) + await expect(tx).revertedWith('Caller must be the implementation') + }) + + it('setL2Router should revert', async function () { + const tx = L2GraphTokenGateway.connect(unauthorized).setL2Router(unauthorized.address) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('setL1TokenAddress should revert', async function () { + const tx = L2GraphTokenGateway.connect(unauthorized).setL1TokenAddress(unauthorized.address) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('setL1CounterpartAddress should revert', async function () { + const tx = L2GraphTokenGateway.connect(unauthorized).setL1CounterpartAddress( + unauthorized.address, + ) + await expect(tx).revertedWith('Caller must be Controller governor') + }) + + it('finalizeInboundTransfer should revert', async function () { + const tx = L2GraphTokenGateway.connect(unauthorized).finalizeInboundTransfer( + unauthorized.address, + unauthorized.address, + unauthorized.address, + '1000000000000', + '0x00', + ) + + await expect(tx).revertedWith('ONLY_COUNTERPART_GATEWAY') + }) + }) +}) diff --git a/e2e/deployment/config/l2/l2Reservoir.test.ts b/e2e/deployment/config/l2/l2Reservoir.test.ts new file mode 100644 index 000000000..bce493ded --- /dev/null +++ b/e2e/deployment/config/l2/l2Reservoir.test.ts @@ -0,0 +1,19 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' + +describe('[L2] L2Reservoir configuration', () => { + const { + contracts: { Controller, L2Reservoir }, + } = hre.graph() + + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (!chainIdIsL2(chainId)) this.skip() + }) + + it('should be controlled by Controller', async function () { + const controller = await L2Reservoir.controller() + expect(controller).eq(Controller.address) + }) +}) diff --git a/e2e/deployment/config/protocol.test.ts b/e2e/deployment/config/protocol.test.ts deleted file mode 100644 index 4e12f5088..000000000 --- a/e2e/deployment/config/protocol.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { expect } from 'chai' -import hre from 'hardhat' - -describe('Protocol configuration', () => { - const { contracts } = hre.graph() - - it('should be unpaused', async function () { - const paused = await contracts.Controller.paused() - expect(paused).eq(false) - }) -}) diff --git a/e2e/deployment/init/l1/graphToken.test.ts b/e2e/deployment/init/l1/graphToken.test.ts index 9e708e7b6..d3c459d1b 100644 --- a/e2e/deployment/init/l1/graphToken.test.ts +++ b/e2e/deployment/init/l1/graphToken.test.ts @@ -1,16 +1,26 @@ import { expect } from 'chai' import hre from 'hardhat' import { getItemValue } from '../../../../cli/config' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('GraphToken initialization', () => { +describe('[L1] GraphToken initialization', () => { const { graphConfig, contracts: { GraphToken }, } = hre.graph() + let chainId: number + before(async function () { + chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + }) + it('total supply should match "initialSupply" on the config file', async function () { const value = await GraphToken.totalSupply() const expected = getItemValue(graphConfig, 'contracts/GraphToken/init/initialSupply') - hre.network.config.chainId === 1337 ? expect(value).eq(expected) : expect(value).gte(expected) + + chainId === 1337 || chainId === 412346 + ? expect(value).eq(expected) + : expect(value).gte(expected) }) }) diff --git a/e2e/deployment/init/l1/l1Reservoir.test.ts b/e2e/deployment/init/l1/l1Reservoir.test.ts index d677725bd..97f422089 100644 --- a/e2e/deployment/init/l1/l1Reservoir.test.ts +++ b/e2e/deployment/init/l1/l1Reservoir.test.ts @@ -1,11 +1,17 @@ import { expect } from 'chai' import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' -describe('L1Reservoir initialization', () => { +describe('[L1] L1Reservoir initialization', () => { const { contracts: { L1Reservoir, GraphToken, RewardsManager }, } = hre.graph() + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (chainIdIsL2(chainId)) this.skip() + }) + it('should allow RewardsManager contract to spend MAX_UINT256 tokens on L1Reservoirs behalf', async function () { const allowance = await GraphToken.allowance(L1Reservoir.address, RewardsManager.address) expect(allowance).eq(hre.ethers.constants.MaxUint256) diff --git a/e2e/deployment/init/l2/graphToken.test.ts b/e2e/deployment/init/l2/graphToken.test.ts new file mode 100644 index 000000000..f94867343 --- /dev/null +++ b/e2e/deployment/init/l2/graphToken.test.ts @@ -0,0 +1,20 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' + +describe('[L2] GraphToken initialization', () => { + const { + contracts: { GraphToken }, + } = hre.graph() + + let chainId: number + before(async function () { + chainId = (await hre.ethers.provider.getNetwork()).chainId + if (!chainIdIsL2(chainId)) this.skip() + }) + + it('total supply should be zero', async function () { + const value = await GraphToken.totalSupply() + chainId === 1337 || chainId === 412346 ? expect(value).eq(0) : expect(value).gte(0) + }) +}) diff --git a/e2e/deployment/init/l2/l2Reservoir.test.ts b/e2e/deployment/init/l2/l2Reservoir.test.ts new file mode 100644 index 000000000..0627d40f4 --- /dev/null +++ b/e2e/deployment/init/l2/l2Reservoir.test.ts @@ -0,0 +1,19 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { chainIdIsL2 } from '../../../../cli/utils' + +describe('[L2] L2Reservoir initialization', () => { + const { + contracts: { L2Reservoir, GraphToken, RewardsManager }, + } = hre.graph() + + before(async function () { + const chainId = (await hre.ethers.provider.getNetwork()).chainId + if (!chainIdIsL2(chainId)) this.skip() + }) + + it('should allow RewardsManager contract to spend MAX_UINT256 tokens on L1Reservoirs behalf', async function () { + const allowance = await GraphToken.allowance(L2Reservoir.address, RewardsManager.address) + expect(allowance).eq(hre.ethers.constants.MaxUint256) + }) +}) diff --git a/hardhat.config.ts b/hardhat.config.ts index b0ff4da94..b0925c1c2 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -143,15 +143,18 @@ const config: HardhatUserConfig = { hardfork: 'london', }, localhost: { + chainId: 1337, accounts: process.env.FORK === 'true' ? getAccountsKeys() : { mnemonic: DEFAULT_TEST_MNEMONIC }, }, localnitrol1: { url: 'http://localhost:8545', + chainId: 1337, accounts: { mnemonic: DEFAULT_TEST_MNEMONIC }, }, localnitrol2: { url: 'http://localhost:8547', + chainId: 412346, accounts: { mnemonic: DEFAULT_TEST_MNEMONIC }, }, }, diff --git a/tasks/deployment/accounts.ts b/tasks/deployment/accounts.ts index a84d6990d..2e6dccb80 100644 --- a/tasks/deployment/accounts.ts +++ b/tasks/deployment/accounts.ts @@ -3,7 +3,7 @@ import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' import { updateItemValue, writeConfig } from '../../cli/config' -task('migrate:accounts', '[localhost] Creates protocol accounts and saves them in graph config') +task('migrate:accounts', 'Creates protocol accounts and saves them in graph config') .addParam('graphConfig', cliOpts.graphConfig.description, cliOpts.graphConfig.default) .setAction(async (taskArgs, hre) => { const { graphConfig, getDeployer } = hre.graph({ diff --git a/tasks/deployment/ownership.ts b/tasks/deployment/ownership.ts index 8b711d0af..2f988492e 100644 --- a/tasks/deployment/ownership.ts +++ b/tasks/deployment/ownership.ts @@ -1,11 +1,9 @@ import { ContractTransaction } from 'ethers' import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' +import { chainIdIsL2 } from '../../cli/utils' -task( - 'migrate:ownership', - '[localhost] Accepts ownership of protocol contracts on behalf of governor', -) +task('migrate:ownership', 'Accepts ownership of protocol contracts on behalf of governor') .addParam('addressBook', cliOpts.addressBook.description, cliOpts.addressBook.default) .addParam('graphConfig', cliOpts.graphConfig.description, cliOpts.graphConfig.default) .setAction(async (taskArgs, hre) => { @@ -19,11 +17,16 @@ task( console.log(`- Governor: ${governor.address}`) const txs: ContractTransaction[] = [] - txs.push(await contracts.GraphToken.connect(governor).acceptOwnership()) txs.push(await contracts.Controller.connect(governor).acceptOwnership()) txs.push(await contracts.GraphProxyAdmin.connect(governor).acceptOwnership()) txs.push(await contracts.SubgraphNFT.connect(governor).acceptOwnership()) + const chainId = (await hre.ethers.provider.getNetwork()).chainId + const isL2 = chainIdIsL2(chainId) + if (!isL2) { + txs.push(await contracts.GraphToken.connect(governor).acceptOwnership()) + } + await Promise.all(txs.map((tx) => tx.wait())) console.log('Done!') }) diff --git a/tasks/deployment/unpause.ts b/tasks/deployment/unpause.ts index 7f0b71f57..694fe3a9c 100644 --- a/tasks/deployment/unpause.ts +++ b/tasks/deployment/unpause.ts @@ -1,7 +1,8 @@ import { task } from 'hardhat/config' import { cliOpts } from '../../cli/defaults' +import { chainIdIsL2 } from '../../cli/utils' -task('migrate:unpause', 'Unpause protocol') +task('migrate:unpause', 'Unpause protocol and bridge') .addParam('addressBook', cliOpts.addressBook.description, cliOpts.addressBook.default) .addParam('graphConfig', cliOpts.graphConfig.description, cliOpts.graphConfig.default) .setAction(async (taskArgs, hre) => { @@ -14,5 +15,13 @@ task('migrate:unpause', 'Unpause protocol') console.log('> Unpausing protocol') const tx = await contracts.Controller.connect(governor).setPaused(false) await tx.wait() + + console.log('> Unpausing bridge') + const chainId = (await hre.ethers.provider.getNetwork()).chainId + const isL2 = chainIdIsL2(chainId) + const GraphTokenGateway = isL2 ? contracts.L2GraphTokenGateway : contracts.L1GraphTokenGateway + const tx2 = await GraphTokenGateway.connect(governor).setPaused(false) + await tx2.wait() + console.log('Done!') }) diff --git a/tasks/e2e/e2e.ts b/tasks/e2e/e2e.ts index 90b2246ed..9ff694703 100644 --- a/tasks/e2e/e2e.ts +++ b/tasks/e2e/e2e.ts @@ -4,11 +4,9 @@ import { TASK_TEST, TASK_RUN } from 'hardhat/builtin-tasks/task-names' import glob from 'glob' import { cliOpts } from '../../cli/defaults' import fs from 'fs' -import path from 'path' const CONFIG_TESTS = 'e2e/deployment/config/**/*.test.ts' const INIT_TESTS = 'e2e/deployment/init/**/*.test.ts' -const SCENARIOS = 'e2e/scenarios/*[!.test].ts' // Built-in test & run tasks don't support our arguments // we can pass them to GRE via env vars @@ -29,19 +27,6 @@ task('e2e', 'Run all e2e tests') await hre.run(TASK_TEST, { testFiles: testFiles, }) - - // Run scenarios one by one - // we don't know how one scenario can affect tests from another one - const scenarios = new glob.GlobSync(SCENARIOS).found.map((s) => - path.basename(s, path.extname(s)), - ) - for (const scenario of scenarios) { - await hre.run('e2e:scenario', { - scenario: scenario, - graphConfig: args.graphConfig, - addressBook: args.addressBook, - }) - } }) task('e2e:config', 'Run deployment configuration e2e tests') diff --git a/tasks/gre.ts b/tasks/gre.ts index cea6ae172..1da44b20c 100644 --- a/tasks/gre.ts +++ b/tasks/gre.ts @@ -12,7 +12,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' // Graph Runtime Environment (GRE) extensions for the HRE extendEnvironment((hre: HardhatRuntimeEnvironment) => { hre.graph = (opts: GREOptions = {}) => { - const chainId = hre.network.config.chainId?.toString() ?? '1337' + const chainId = opts.chainId ?? hre.network.config.chainId?.toString() ?? '1337' const addressBookPath = opts.addressBook ?? process.env.ADDRESS_BOOK const graphConfigPath = opts.graphConfig ?? process.env.GRAPH_CONFIG diff --git a/tasks/type-extensions.d.ts b/tasks/type-extensions.d.ts index 5dbaa09ab..ae70c6f7d 100644 --- a/tasks/type-extensions.d.ts +++ b/tasks/type-extensions.d.ts @@ -5,6 +5,7 @@ import { NetworkContracts } from '../cli/contracts' export interface GREOptions { addressBook?: string graphConfig?: string + chainId?: string } export interface NamedAccounts {