diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 6b1886995..e69df217c 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog -## Unreleased +## 1.40.0 (2024-10-10) - Fix Hardhat compile error when overriding interface functions with public constant variables. ([#1091](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1091)) +- Support ignoring Hardhat compile errors when extracting detailed namespaced storage layouts for validations. ([#1090](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1090)) ## 1.39.0 (2024-10-02) diff --git a/packages/core/package.json b/packages/core/package.json index 4fc426472..31d27cb30 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/upgrades-core", - "version": "1.39.0", + "version": "1.40.0", "description": "", "repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core", "license": "MIT", diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6a4d640c5..d173104d6 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -63,3 +63,4 @@ export { getUpgradeInterfaceVersion } from './upgrade-interface-version'; export { makeNamespacedInput } from './utils/make-namespaced'; export { isNamespaceSupported } from './storage/namespace'; export { inferProxyAdmin } from './infer-proxy-admin'; +export { assertUnreachable } from './utils/assert'; diff --git a/packages/plugin-hardhat/CHANGELOG.md b/packages/plugin-hardhat/CHANGELOG.md index 6ed398b6e..02f25b39b 100644 --- a/packages/plugin-hardhat/CHANGELOG.md +++ b/packages/plugin-hardhat/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 3.5.0 (2024-10-10) + +- Support ignoring Hardhat compile errors when extracting detailed namespaced storage layouts for validations. ([#1090](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1090)) + ## 3.4.0 (2024-09-23) ### Potentially breaking changes diff --git a/packages/plugin-hardhat/package.json b/packages/plugin-hardhat/package.json index b170f8f0b..12223d56a 100644 --- a/packages/plugin-hardhat/package.json +++ b/packages/plugin-hardhat/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/hardhat-upgrades", - "version": "3.4.0", + "version": "3.5.0", "description": "", "repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/plugin-hardhat", "license": "MIT", @@ -38,7 +38,7 @@ "@openzeppelin/defender-sdk-base-client": "^1.14.4", "@openzeppelin/defender-sdk-deploy-client": "^1.14.4", "@openzeppelin/defender-sdk-network-client": "^1.14.4", - "@openzeppelin/upgrades-core": "^1.38.0", + "@openzeppelin/upgrades-core": "^1.40.0", "chalk": "^4.1.0", "debug": "^4.1.1", "ethereumjs-util": "^7.1.5", diff --git a/packages/plugin-hardhat/src/index.ts b/packages/plugin-hardhat/src/index.ts index 1a07cf7b0..f7458a300 100644 --- a/packages/plugin-hardhat/src/index.ts +++ b/packages/plugin-hardhat/src/index.ts @@ -6,7 +6,7 @@ import { subtask, extendEnvironment, extendConfig } from 'hardhat/config'; import { TASK_COMPILE_SOLIDITY, TASK_COMPILE_SOLIDITY_COMPILE } from 'hardhat/builtin-tasks/task-names'; import { lazyObject } from 'hardhat/plugins'; import { HardhatConfig, HardhatRuntimeEnvironment } from 'hardhat/types'; -import type { silenceWarnings, SolcInput, SolcOutput } from '@openzeppelin/upgrades-core'; +import { assertUnreachable, type silenceWarnings, type SolcInput, type SolcOutput } from '@openzeppelin/upgrades-core'; import type { DeployFunction } from './deploy-proxy'; import type { PrepareUpgradeFunction } from './prepare-upgrade'; import type { UpgradeFunction } from './upgrade-proxy'; @@ -101,7 +101,46 @@ subtask(TASK_COMPILE_SOLIDITY_COMPILE, async (args: RunCompilerArgs, hre, runSup if (isNamespaceSupported(args.solcVersion)) { const namespacedInput = makeNamespacedInput(args.input, output, args.solcVersion); namespacedOutput = (await runSuper({ ...args, quiet: true, input: namespacedInput })).output; - await checkNamespacedCompileErrors(namespacedOutput); + + const namespacedCompileErrors = getNamespacedCompileErrors(namespacedOutput); + if (namespacedCompileErrors.length > 0) { + // If there are compile errors in the namespaced output, show error or warning if needed, then only use the original output + + const msg = `Failed to compile modified contracts for namespaced storage layout validations:\n\n${namespacedCompileErrors.join('\n')}`; + const preamble = [ + 'Please report this at https://zpl.in/upgrades/report. If possible, include the source code for the contracts mentioned in the errors above.', + 'This step allows for advanced storage modifications such as tight varible packing when performing upgrades with namespaced storage layouts.', + ]; + + switch (hre.config.namespacedCompileErrors) { + case undefined: + case 'error': { + const { UpgradesError } = await import('@openzeppelin/upgrades-core'); + const details = [ + ...preamble, + 'If you are not using namespaced storage, or if you do not anticipate making advanced modifications to namespaces during upgrades,', + "you can set namespacedCompileErrors: 'warn' or namespacedCompileErrors: 'ignore' in your hardhat config to convert this to a warning or to ignore this.", + ]; + throw new UpgradesError(msg, () => details.join('\n')); + } + case 'warn': { + const { logWarning } = await import('@openzeppelin/upgrades-core'); + const details = [ + ...preamble, + 'If you are not using namespaced storage, or if you do not anticipate making advanced modifications to namespaces during upgrades,', + "you can set namespacedCompileErrors: 'ignore' in your hardhat config to ignore this.", + ]; + logWarning(msg, details); + break; + } + case 'ignore': + break; + default: + assertUnreachable(hre.config.namespacedCompileErrors); + } + + namespacedOutput = undefined; + } } const validations = validate(output, decodeSrc, args.solcVersion, args.input, namespacedOutput); @@ -111,11 +150,7 @@ subtask(TASK_COMPILE_SOLIDITY_COMPILE, async (args: RunCompilerArgs, hre, runSup return { output, solcBuild }; }); -/** - * Checks for compile errors in the modified contracts for namespaced storage. - * If errors are found, throws an error with the compile error messages. - */ -async function checkNamespacedCompileErrors(namespacedOutput: SolcOutput) { +function getNamespacedCompileErrors(namespacedOutput: SolcOutput) { const errors = []; if (namespacedOutput.errors !== undefined) { for (const error of namespacedOutput.errors) { @@ -124,14 +159,7 @@ async function checkNamespacedCompileErrors(namespacedOutput: SolcOutput) { } } } - if (errors.length > 0) { - const { UpgradesError } = await import('@openzeppelin/upgrades-core'); - throw new UpgradesError( - `Failed to compile modified contracts for namespaced storage:\n\n${errors.join('\n')}`, - () => - 'Please report this at https://zpl.in/upgrades/report. If possible, include the source code for the contracts mentioned in the errors above.', - ); - } + return errors; } extendEnvironment(hre => { diff --git a/packages/plugin-hardhat/src/type-extensions.ts b/packages/plugin-hardhat/src/type-extensions.ts index 67f7c899e..18808b499 100644 --- a/packages/plugin-hardhat/src/type-extensions.ts +++ b/packages/plugin-hardhat/src/type-extensions.ts @@ -17,12 +17,16 @@ export interface HardhatDefenderConfig { network?: string; } +export type NamespacedCompileErrorsRule = 'error' | 'warn' | 'ignore'; + declare module 'hardhat/types/config' { export interface HardhatUserConfig { defender?: HardhatDefenderConfig; + namespacedCompileErrors?: NamespacedCompileErrorsRule; } export interface HardhatConfig { defender?: HardhatDefenderConfig; + namespacedCompileErrors?: NamespacedCompileErrorsRule; } }