Skip to content

Commit

Permalink
fix: ensure GRE handles multiple chains with same chainId gracefully (#…
Browse files Browse the repository at this point in the history
…695)

* fix: ensure GRE handles multiple chains with same chainId gracefully

Signed-off-by: Tomás Migone <[email protected]>
  • Loading branch information
tmigone authored Aug 30, 2022
1 parent 707b856 commit f9deb7b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 17 deletions.
68 changes: 52 additions & 16 deletions gre/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import GraphNetwork from './helpers/network'
import { createProvider } from 'hardhat/internal/core/providers/construction'
import { EthersProviderWrapper } from '@nomiclabs/hardhat-ethers/internal/ethers-provider-wrapper'

import { logDebug } from './logger'
import { logDebug, logWarn } from './logger'
import { HARDHAT_NETWORK_NAME } from 'hardhat/plugins'

interface GREChains {
l1ChainId: number
Expand Down Expand Up @@ -99,19 +100,25 @@ export function getProviders(
const getProvider = (
networks: NetworksConfig,
chainId: number,
mainNetworkName: string,
isMainProvider: boolean,
chainLabel: string,
): EthersProviderWrapper | undefined => {
const network = getNetworkConfig(networks, chainId) as HttpNetworkConfig
const networkName = getNetworkName(networks, chainId)
const network = getNetworkConfig(networks, chainId, mainNetworkName) as HttpNetworkConfig
const networkName = getNetworkName(networks, chainId, mainNetworkName)

logDebug(`Provider url for ${chainLabel}(${networkName}): ${network?.url}`)

// Ensure at least main provider is configured
if (isMainProvider && network === undefined) {
// For Hardhat network we don't need url to create a provider
if (
isMainProvider &&
(network === undefined || network.url === undefined) &&
networkName !== HARDHAT_NETWORK_NAME
) {
throw new GREPluginError(`Must set a provider url for chain: ${chainId}!`)
}

logDebug(`Provider url for ${chainLabel}: ${network?.url}`)

if (network === undefined || networkName === undefined) {
return undefined
}
Expand All @@ -123,8 +130,8 @@ export function getProviders(
return ethersProviderWrapper
}

const l1Provider = getProvider(hre.config.networks, l1ChainId, isHHL1, 'L1')
const l2Provider = getProvider(hre.config.networks, l2ChainId, !isHHL1, 'L2')
const l1Provider = getProvider(hre.config.networks, l1ChainId, hre.network.name, isHHL1, 'L1')
const l2Provider = getProvider(hre.config.networks, l2ChainId, hre.network.name, !isHHL1, 'L2')

return {
l1Provider,
Expand All @@ -142,8 +149,8 @@ export function getGraphConfigPaths(
logDebug('== Getting graph config paths')
logDebug(`Graph base dir: ${hre.config.paths.graph}`)

const l1Network = getNetworkConfig(hre.config.networks, l1ChainId)
const l2Network = getNetworkConfig(hre.config.networks, l2ChainId)
const l1Network = getNetworkConfig(hre.config.networks, l1ChainId, hre.network.name)
const l2Network = getNetworkConfig(hre.config.networks, l2ChainId, hre.network.name)

// Priority is as follows:
// - hre.graph() init parameter l1GraphConfigPath/l2GraphConfigPath
Expand Down Expand Up @@ -205,14 +212,43 @@ export function getGraphConfigPaths(
}
}

function getNetworkConfig(networks: NetworksConfig, chainId: number): NetworkConfig | undefined {
return Object.keys(networks)
.map((n) => networks[n])
.find((n) => n.chainId === chainId)
function getNetworkConfig(
networks: NetworksConfig,
chainId: number,
mainNetworkName: string,
): (NetworkConfig & { name: string }) | undefined {
let candidateNetworks = Object.keys(networks)
.map((n) => ({ ...networks[n], name: n }))
.filter((n) => n.chainId === chainId)

if (candidateNetworks.length > 1) {
logWarn(
`Found multiple networks with chainId ${chainId}, trying to use main network name to desambiguate`,
)

candidateNetworks = candidateNetworks.filter((n) => n.name === mainNetworkName)

if (candidateNetworks.length === 1) {
return candidateNetworks[0]
} else {
throw new GREPluginError(
`Found multiple networks with chainID ${chainId}. This is not supported!`,
)
}
} else if (candidateNetworks.length === 1) {
return candidateNetworks[0]
} else {
return undefined
}
}

function getNetworkName(networks: NetworksConfig, chainId: number): string | undefined {
return Object.keys(networks).find((n) => networks[n].chainId === chainId)
function getNetworkName(
networks: NetworksConfig,
chainId: number,
mainNetworkName: string,
): string | undefined {
const network = getNetworkConfig(networks, chainId, mainNetworkName)
return network?.name
}

function normalizePath(_path: string, graphPath: string) {
Expand Down
3 changes: 3 additions & 0 deletions gre/gre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ extendConfig((config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) =>

extendEnvironment((hre: HardhatRuntimeEnvironment) => {
hre.graph = (opts: GraphRuntimeEnvironmentOptions = {}) => {
logDebug('*** Initializing Graph Runtime Environment (GRE) ***')
logDebug(`Main network: ${hre.network.name}`)

const { l1ChainId, l2ChainId, isHHL1 } = getChains(hre.network.config.chainId)
const { l1Provider, l2Provider } = getProviders(hre, l1ChainId, l2ChainId, isHHL1)
const addressBookPath = getAddressBookPath(hre, opts)
Expand Down
16 changes: 15 additions & 1 deletion gre/test/gre.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('GRE usage', function () {
describe('graph-config project setting --network to an L2', function () {
useEnvironment('graph-config', 'arbitrum-goerli')

it('should return L1 and L2 configured objects ', function () {
it('should return L1 and L2 configured objects', function () {
const g = this.hre.graph()

expect(g).to.be.an('object')
Expand All @@ -32,6 +32,20 @@ describe('GRE usage', function () {
})
})

describe('graph-config project setting --network to hardhat network', function () {
useEnvironment('graph-config', 'hardhat')

it('should return L1 configured object and L2 unconfigured', function () {
const g = this.hre.graph()

expect(g).to.be.an('object')
expect(g.l1).to.be.an('object')
expect(g.l2).to.be.null
expect(g.l1.chainId).to.equal(1337)
expect(g.chainId).to.equal(1337)
})
})

describe('graph-config project setting --network to an L1 with no configured counterpart', function () {
useEnvironment('graph-config', 'localhost')

Expand Down

0 comments on commit f9deb7b

Please sign in to comment.