diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 98e26b530..dc2c2a4a9 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. ([#950](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/950)) + ## 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)) 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..aaa59cbe4 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, 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,36 @@ 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; - + 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: 'hardhat', - instanceId: hardhatMetadata.instanceId, - forkedNetwork: hardhatMetadata.forkedNetwork, + networkName: networkType, + instanceId: networkMetadata.instanceId, + forkedNetwork: networkMetadata.forkedNetwork, }; } @@ -83,7 +98,7 @@ interface DevInstanceMetadata { forkedNetwork?: { // The chainId of the network that is being forked chainId: number; - }; + } | null; } export class Manifest { @@ -129,7 +144,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..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; @@ -12,13 +13,14 @@ export interface EthereumProvider { send(method: string, params: unknown[]): Promise; } -interface HardhatMetadata { +export interface HardhatMetadata { + clientVersion: string; chainId: number; instanceId: string; forkedNetwork?: { // The chainId of the network that is being forked chainId: number; - }; + } | null; } interface EthereumTransaction { @@ -57,6 +59,13 @@ export async function getHardhatMetadata(provider: EthereumProvider): Promise { + return provider.send('anvil_metadata', []); +} + export async function getStorageAt( provider: EthereumProvider, address: string,