From ba9354ef60e8c3da9369d7f5e813886a306dc0c0 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 13:39:01 -0500 Subject: [PATCH 1/6] Handle null forkedNetwork from anvil --- packages/core/src/manifest.test.ts | 16 +++++++++++++-- packages/core/src/manifest.ts | 32 ++++++++++++++---------------- packages/core/src/provider.ts | 3 ++- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/packages/core/src/manifest.test.ts b/packages/core/src/manifest.test.ts index 092448de3..81c3767cc 100644 --- a/packages/core/src/manifest.test.ts +++ b/packages/core/src/manifest.test.ts @@ -399,11 +399,23 @@ test('manifest name for an unknown network, development instance, non hardhat', test('manifest name for an unknown network, development instance, hardhat', t => { const chainId = 31337; const instanceId = '0x22223'; - const devInstanceMetadata = { networkName: 'dev', instanceId: instanceId }; + const devInstanceMetadata = { networkName: 'hardhat', instanceId: instanceId }; const manifest = new Manifest(chainId, devInstanceMetadata, '/tmp'); - const expectedPath = `/tmp/openzeppelin-upgrades/dev-${chainId}-${instanceId}.json`; + const expectedPath = `/tmp/openzeppelin-upgrades/hardhat-${chainId}-${instanceId}.json`; + t.is(manifest.file, expectedPath); + t.is(manifest.fallbackFile, `.openzeppelin/unknown-${chainId}.json`); +}); + +test('manifest name for an unknown network, development instance, anvil - forkedNetwork null', t => { + const chainId = 31337; + const instanceId = '0x22224'; + const devInstanceMetadata = { networkName: 'anvil', instanceId: instanceId, forkedNetwork: null }; + + const manifest = new Manifest(chainId, devInstanceMetadata, '/tmp'); + + const expectedPath = `/tmp/openzeppelin-upgrades/anvil-${chainId}-${instanceId}.json`; t.is(manifest.file, expectedPath); t.is(manifest.fallbackFile, `.openzeppelin/unknown-${chainId}.json`); }); diff --git a/packages/core/src/manifest.ts b/packages/core/src/manifest.ts index a803929c9..36f5798f7 100644 --- a/packages/core/src/manifest.ts +++ b/packages/core/src/manifest.ts @@ -48,25 +48,23 @@ async function getDevInstanceMetadata( provider: EthereumProvider, chainId: number, ): Promise { - let hardhatMetadata; - try { - hardhatMetadata = await getHardhatMetadata(provider); + const hardhatMetadata = await getHardhatMetadata(provider); + + if (hardhatMetadata.chainId !== chainId) { + throw new Error( + `Broken invariant: Hardhat metadata's chainId ${hardhatMetadata.chainId} does not match eth_chainId ${chainId}`, + ); + } + + return { + networkName: hardhatMetadata.clientVersion.startsWith('anvil') ? 'anvil' : 'hardhat', + instanceId: hardhatMetadata.instanceId, + forkedNetwork: hardhatMetadata.forkedNetwork, + }; } catch (e: unknown) { return undefined; } - - if (hardhatMetadata.chainId !== chainId) { - throw new Error( - `Broken invariant: Hardhat metadata's chainId ${hardhatMetadata.chainId} does not match eth_chainId ${chainId}`, - ); - } - - return { - networkName: 'hardhat', - instanceId: hardhatMetadata.instanceId, - forkedNetwork: hardhatMetadata.forkedNetwork, - }; } function getSuffix(chainId: number, devInstanceMetadata?: DevInstanceMetadata) { @@ -83,7 +81,7 @@ interface DevInstanceMetadata { forkedNetwork?: { // The chainId of the network that is being forked chainId: number; - }; + } | null; } export class Manifest { @@ -129,7 +127,7 @@ export class Manifest { } debug('development manifest file:', this.file, 'fallback file:', this.fallbackFile); - if (devInstanceMetadata.forkedNetwork !== undefined) { + if (devInstanceMetadata.forkedNetwork) { const forkedChainId = devInstanceMetadata.forkedNetwork.chainId; debug('forked network chain id:', forkedChainId); diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts index 3677cb618..a3bf697e8 100644 --- a/packages/core/src/provider.ts +++ b/packages/core/src/provider.ts @@ -13,12 +13,13 @@ export interface EthereumProvider { } interface HardhatMetadata { + clientVersion: string; chainId: number; instanceId: string; forkedNetwork?: { // The chainId of the network that is being forked chainId: number; - }; + } | null; } interface EthereumTransaction { From 1ee2bd3ab714a8429b3449081db8d69a27c6944e Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 13:41:26 -0500 Subject: [PATCH 2/6] Update changelog --- packages/core/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 98e26b530..709d66acd 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- Fix manifest error when connecting to an Anvil dev network. + ## 1.32.1 (2023-12-14) - CLI: Fix ambiguous name error when passing in fully qualified contract names. ([#944](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/944)) From fcd8771796ebd6e06ef16ca2c3489bd9066152f9 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 13:54:39 -0500 Subject: [PATCH 3/6] Update changelog --- packages/core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 709d66acd..dc2c2a4a9 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Fix manifest error when connecting to an Anvil dev network. +- Fix manifest error when connecting to an Anvil dev network. ([#950](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/950)) ## 1.32.1 (2023-12-14) From 2d497ad38bf099c859747c2c2b57a0185968d2a3 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 13:58:04 -0500 Subject: [PATCH 4/6] Only keep necessary error handling, use stronger types --- packages/core/src/manifest.ts | 30 ++++++++++++++++-------------- packages/core/src/provider.ts | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/core/src/manifest.ts b/packages/core/src/manifest.ts index 36f5798f7..499bd3890 100644 --- a/packages/core/src/manifest.ts +++ b/packages/core/src/manifest.ts @@ -1,7 +1,7 @@ import os from 'os'; import path from 'path'; import { promises as fs } from 'fs'; -import { EthereumProvider, getChainId, getHardhatMetadata, networkNames } from './provider'; +import { EthereumProvider, HardhatMetadata, getChainId, getHardhatMetadata, networkNames } from './provider'; import lockfile from 'proper-lockfile'; import { compare as compareVersions } from 'compare-versions'; @@ -48,23 +48,25 @@ async function getDevInstanceMetadata( provider: EthereumProvider, chainId: number, ): Promise { - try { - const hardhatMetadata = await getHardhatMetadata(provider); - - if (hardhatMetadata.chainId !== chainId) { - throw new Error( - `Broken invariant: Hardhat metadata's chainId ${hardhatMetadata.chainId} does not match eth_chainId ${chainId}`, - ); - } + let hardhatMetadata: HardhatMetadata; - return { - networkName: hardhatMetadata.clientVersion.startsWith('anvil') ? 'anvil' : 'hardhat', - instanceId: hardhatMetadata.instanceId, - forkedNetwork: hardhatMetadata.forkedNetwork, - }; + try { + hardhatMetadata = await getHardhatMetadata(provider); } catch (e: unknown) { return undefined; } + + if (hardhatMetadata.chainId !== chainId) { + throw new Error( + `Broken invariant: Hardhat metadata's chainId ${hardhatMetadata.chainId} does not match eth_chainId ${chainId}`, + ); + } + + return { + networkName: hardhatMetadata.clientVersion.startsWith('anvil') ? 'anvil' : 'hardhat', + instanceId: hardhatMetadata.instanceId, + forkedNetwork: hardhatMetadata.forkedNetwork, + }; } function getSuffix(chainId: number, devInstanceMetadata?: DevInstanceMetadata) { diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts index a3bf697e8..9713d24a9 100644 --- a/packages/core/src/provider.ts +++ b/packages/core/src/provider.ts @@ -12,7 +12,7 @@ export interface EthereumProvider { send(method: string, params: unknown[]): Promise; } -interface HardhatMetadata { +export interface HardhatMetadata { clientVersion: string; chainId: number; instanceId: string; From 9f182ec54be2c50799174c1833c9a6760bd7f9da Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 17:23:14 -0500 Subject: [PATCH 5/6] Use anvil_metadata if available --- packages/core/src/manifest.ts | 34 +++++++++++++++++++++++++--------- packages/core/src/provider.ts | 8 ++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/packages/core/src/manifest.ts b/packages/core/src/manifest.ts index 499bd3890..1ee9c7897 100644 --- a/packages/core/src/manifest.ts +++ b/packages/core/src/manifest.ts @@ -1,7 +1,14 @@ import os from 'os'; import path from 'path'; import { promises as fs } from 'fs'; -import { EthereumProvider, HardhatMetadata, getChainId, getHardhatMetadata, networkNames } from './provider'; +import { + EthereumProvider, + HardhatMetadata, + getAnvilMetadata, + getChainId, + getHardhatMetadata, + networkNames, +} from './provider'; import lockfile from 'proper-lockfile'; import { compare as compareVersions } from 'compare-versions'; @@ -44,28 +51,37 @@ function defaultManifest(): ManifestData { const MANIFEST_DEFAULT_DIR = '.openzeppelin'; const MANIFEST_TEMP_DIR = 'openzeppelin-upgrades'; +type DevNetworkType = 'hardhat' | 'anvil'; + async function getDevInstanceMetadata( provider: EthereumProvider, chainId: number, ): Promise { - let hardhatMetadata: HardhatMetadata; + let networkMetadata: HardhatMetadata; + let networkType: DevNetworkType; try { - hardhatMetadata = await getHardhatMetadata(provider); + networkMetadata = await getAnvilMetadata(provider); + networkType = 'anvil'; } catch (e: unknown) { - return undefined; + try { + networkMetadata = await getHardhatMetadata(provider); + networkType = 'hardhat'; + } catch (e: unknown) { + return undefined; + } } - if (hardhatMetadata.chainId !== chainId) { + if (networkMetadata.chainId !== chainId) { throw new Error( - `Broken invariant: Hardhat metadata's chainId ${hardhatMetadata.chainId} does not match eth_chainId ${chainId}`, + `Broken invariant: Hardhat or Anvil metadata's chainId ${networkMetadata.chainId} does not match eth_chainId ${chainId}`, ); } return { - networkName: hardhatMetadata.clientVersion.startsWith('anvil') ? 'anvil' : 'hardhat', - instanceId: hardhatMetadata.instanceId, - forkedNetwork: hardhatMetadata.forkedNetwork, + networkName: networkType, + instanceId: networkMetadata.instanceId, + forkedNetwork: networkMetadata.forkedNetwork, }; } diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts index 9713d24a9..0fcea674e 100644 --- a/packages/core/src/provider.ts +++ b/packages/core/src/provider.ts @@ -1,4 +1,5 @@ export interface EthereumProvider { + send(method: 'anvil_metadata', params: []): Promise; send(method: 'hardhat_metadata', params: []): Promise; send(method: 'web3_clientVersion', params: []): Promise; send(method: 'net_version', params: []): Promise; @@ -58,6 +59,13 @@ export async function getHardhatMetadata(provider: EthereumProvider): Promise { + return provider.send('anvil_metadata', []); +} + export async function getStorageAt( provider: EthereumProvider, address: string, From e78d649c05623b1a29af15383c0f30283eb5a79f Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 20 Dec 2023 19:58:33 -0500 Subject: [PATCH 6/6] spacing --- packages/core/src/manifest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/manifest.ts b/packages/core/src/manifest.ts index 1ee9c7897..aaa59cbe4 100644 --- a/packages/core/src/manifest.ts +++ b/packages/core/src/manifest.ts @@ -58,7 +58,6 @@ async function getDevInstanceMetadata( chainId: number, ): Promise { let networkMetadata: HardhatMetadata; - let networkType: DevNetworkType; try { networkMetadata = await getAnvilMetadata(provider);