From cc89564e20aaa11a54470ac5f1bcd88d642e94cd Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 21 Aug 2024 16:52:00 -0400 Subject: [PATCH 01/27] Exclude by pattern --- .../test/cli/AbstractNotUpgradeable.sol | 10 +++ .../test/cli/AbstractNotUpgradeable2.sol | 10 +++ .../test/cli/AbstractUpgradeable.sol | 14 ++++ .../contracts/test/cli/UsesUpgradeable.sol | 15 ++++ packages/core/package.json | 3 +- packages/core/src/cli/cli.test.ts | 29 ++++++++ packages/core/src/cli/cli.test.ts.md | 67 ++++++++++++++++++ packages/core/src/cli/cli.test.ts.snap | Bin 2707 -> 2983 bytes packages/core/src/cli/validate.ts | 9 ++- .../core/src/cli/validate/contract-report.ts | 27 +++++-- .../cli/validate/validate-upgrade-safety.ts | 3 +- packages/core/src/cli/validate/validations.ts | 1 - yarn.lock | 33 ++------- 13 files changed, 183 insertions(+), 38 deletions(-) create mode 100644 packages/core/contracts/test/cli/AbstractNotUpgradeable.sol create mode 100644 packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol create mode 100644 packages/core/contracts/test/cli/AbstractUpgradeable.sol create mode 100644 packages/core/contracts/test/cli/UsesUpgradeable.sol diff --git a/packages/core/contracts/test/cli/AbstractNotUpgradeable.sol b/packages/core/contracts/test/cli/AbstractNotUpgradeable.sol new file mode 100644 index 000000000..5a7ce8016 --- /dev/null +++ b/packages/core/contracts/test/cli/AbstractNotUpgradeable.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +abstract contract AbstractNotUpgradeable { + uint256 public immutable x; + + constructor(uint256 _x) { + x = _x; + } +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol b/packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol new file mode 100644 index 000000000..058446e81 --- /dev/null +++ b/packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +abstract contract AbstractNotUpgradeable2 { + uint256 public immutable y; + + constructor(uint256 _y) { + y = _y; + } +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/AbstractUpgradeable.sol b/packages/core/contracts/test/cli/AbstractUpgradeable.sol new file mode 100644 index 000000000..132479ab0 --- /dev/null +++ b/packages/core/contracts/test/cli/AbstractUpgradeable.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {AbstractNotUpgradeable} from "./AbstractNotUpgradeable.sol"; +import {AbstractNotUpgradeable2} from "./AbstractNotUpgradeable2.sol"; + +abstract contract AbstractUpgradeable is UUPSUpgradeable, AbstractNotUpgradeable, AbstractNotUpgradeable2 { + uint256 public immutable z; + + constructor(uint256 _x, uint256 _y, uint256 _z) AbstractNotUpgradeable(_x) AbstractNotUpgradeable2(_y) { + z = _z; + } +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/UsesUpgradeable.sol b/packages/core/contracts/test/cli/UsesUpgradeable.sol new file mode 100644 index 000000000..161615312 --- /dev/null +++ b/packages/core/contracts/test/cli/UsesUpgradeable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// This contract is for testing only, it is not safe for use in production. + +import {AbstractUpgradeable} from "./AbstractUpgradeable.sol"; + +contract UsesUpgradeable is AbstractUpgradeable { + constructor(uint256 _x, uint256 _y, uint256 _z) AbstractUpgradeable(x, y, z) { + } + + function _authorizeUpgrade(address newImplementation) internal pure override { + revert("Upgrade disabled"); + } +} \ No newline at end of file diff --git a/packages/core/package.json b/packages/core/package.json index d1ce44559..00b792aba 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -69,6 +69,7 @@ "ethereumjs-util": "^7.0.3", "minimist": "^1.2.7", "proper-lockfile": "^4.1.1", - "solidity-ast": "^0.4.51" + "solidity-ast": "^0.4.51", + "minimatch": "^9.0.5" } } diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index cec9887d0..8aa3544bf 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -572,3 +572,32 @@ test('validate - contract must not have build info dir name - fully qualified', error?.message, ); }); + +test('validate - excludes by pattern - no match', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude **/NoMatch.sol`)); + const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; + t.snapshot(expectation.join('\n')); +}); + +test('validate - excludes by pattern - some match', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude **/Abstract*.sol`)); + const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; + t.snapshot(expectation.join('\n')); +}); + +test('validate - excludes by pattern - all match', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const output = await execAsync(`${CLI} validate ${temp} --exclude **/*Upgradeable*.sol`); + t.snapshot(output); +}); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 26f9ef3ea..d3efc1255 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -423,3 +423,70 @@ Generated by [AVA](https://avajs.dev). FAILED␊ ␊ Stderr: ` + +## validate - excludes by pattern - no match + +> Snapshot 1 + + `Stdout: ✘ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ + ␊ + contracts/test/cli/UsesUpgradeable.sol:9: Contract \`UsesUpgradeable\` has a constructor␊ + Define an initializer instead␊ + https://zpl.in/upgrades/error-001␊ + ␊ + contracts/test/cli/AbstractUpgradeable.sol:11: Contract \`AbstractUpgradeable\` has a constructor␊ + Define an initializer instead␊ + https://zpl.in/upgrades/error-001␊ + ␊ + contracts/test/cli/AbstractUpgradeable.sol:9: Variable \`z\` is immutable and will be initialized on the implementation␊ + If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ + Otherwise, consider a constant variable or use a mutable variable instead␊ + https://zpl.in/upgrades/error-005␊ + ␊ + contracts/test/cli/AbstractNotUpgradeable2.sol:7: Contract \`AbstractNotUpgradeable2\` has a constructor␊ + Define an initializer instead␊ + https://zpl.in/upgrades/error-001␊ + ␊ + contracts/test/cli/AbstractNotUpgradeable2.sol:5: Variable \`y\` is immutable and will be initialized on the implementation␊ + If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ + Otherwise, consider a constant variable or use a mutable variable instead␊ + https://zpl.in/upgrades/error-005␊ + ␊ + contracts/test/cli/AbstractNotUpgradeable.sol:7: Contract \`AbstractNotUpgradeable\` has a constructor␊ + Define an initializer instead␊ + https://zpl.in/upgrades/error-001␊ + ␊ + contracts/test/cli/AbstractNotUpgradeable.sol:5: Variable \`x\` is immutable and will be initialized on the implementation␊ + If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ + Otherwise, consider a constant variable or use a mutable variable instead␊ + https://zpl.in/upgrades/error-005␊ + ␊ + FAILED (1 upgradeable contract detected, 0 passed, 1 failed)␊ + ␊ + Stderr: ` + +## validate - excludes by pattern - some match + +> Snapshot 1 + + `Stdout: ✘ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ + ␊ + contracts/test/cli/UsesUpgradeable.sol:9: Contract \`UsesUpgradeable\` has a constructor␊ + Define an initializer instead␊ + https://zpl.in/upgrades/error-001␊ + ␊ + FAILED (1 upgradeable contract detected, 0 passed, 1 failed)␊ + ␊ + Stderr: ` + +## validate - excludes by pattern - all match + +> Snapshot 1 + + { + stderr: '', + stdout: ` ✔ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ + ␊ + SUCCESS (1 upgradeable contract detected, 1 passed, 0 failed)␊ + `, + } diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 1b7118f66881adb3817d1c87b1a0714db1e380c6..6b932126ab5975a3e3bf921f43d79c4684297846 100644 GIT binary patch literal 2983 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 { functionArgs.reference, functionArgs.opts, functionArgs.referenceBuildInfoDirs, + functionArgs.exclude, ); console.log(result.explain()); process.exitCode = result.ok ? 0 : 1; @@ -50,7 +51,7 @@ function parseArgs(args: string[]) { 'unsafeAllowLinkedLibraries', 'requireReference', ], - string: ['unsafeAllow', 'contract', 'reference', 'referenceBuildInfoDirs'], + string: ['unsafeAllow', 'contract', 'reference', 'referenceBuildInfoDirs', 'exclude'], alias: { h: 'help' }, }); const extraArgs = parsedArgs._; @@ -74,6 +75,7 @@ interface FunctionArgs { reference?: string; opts: Required; referenceBuildInfoDirs?: string[]; + exclude?: string[]; } /** @@ -94,6 +96,7 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri const reference = getAndValidateString(parsedArgs, 'reference'); const opts = withDefaults(parsedArgs); const referenceBuildInfoDirs = getAndValidateString(parsedArgs, 'referenceBuildInfoDirs')?.split(/,+/); + const exclude = getAndValidateString(parsedArgs, 'exclude')?.split(/,+/); if (contract === undefined) { if (reference !== undefined) { @@ -102,7 +105,7 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri throw new Error('The --requireReference option can only be used along with the --contract option.'); } } - return { buildInfoDir, contract, reference, opts, referenceBuildInfoDirs }; + return { buildInfoDir, contract, reference, opts, referenceBuildInfoDirs, exclude }; } } @@ -130,6 +133,8 @@ function validateOptions(parsedArgs: minimist.ParsedArgs) { 'reference', 'requireReference', 'referenceBuildInfoDirs', + 'skipPatterns', + 'exclude', ].includes(key), ); if (invalidArgs.length > 0) { diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 21d474356..7ce8f8942 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -18,6 +18,7 @@ import { SourceContract } from './validations'; import { LayoutCompatibilityReport } from '../../storage/report'; import { indent } from '../../utils/indent'; import { BuildInfoDictionary, SpecifiedContracts } from './validate-upgrade-safety'; +import { minimatch } from 'minimatch'; /** * Report for an upgradeable contract. @@ -72,6 +73,7 @@ export function getContractReports( buildInfoDictionary: BuildInfoDictionary, opts: Required, specifiedContracts?: SpecifiedContracts, + exclude?: string[], ) { const upgradeableContractReports: UpgradeableContractReport[] = []; @@ -91,7 +93,7 @@ export function getContractReports( } else if (specifiedContracts !== undefined || upgradeabilityAssessment.upgradeable) { const reference = upgradeabilityAssessment.referenceContract; const kind = upgradeabilityAssessment.uups ? 'uups' : 'transparent'; - const report = getUpgradeableContractReport(sourceContract, reference, { ...opts, kind: kind }); + const report = getUpgradeableContractReport(sourceContract, reference, { ...opts, kind: kind }, exclude); if (report !== undefined) { upgradeableContractReports.push(report); } @@ -104,7 +106,14 @@ function getUpgradeableContractReport( contract: SourceContract, referenceContract: SourceContract | undefined, opts: ValidationOptions, + exclude?: string[], ): UpgradeableContractReport | undefined { + // TODO if this contract matches an exclude pattern, log something as debug and return undefined + if (exclude !== undefined && exclude.some(glob => minimatch(contract.fullyQualifiedName, glob))) { + debug('Excluding: ' + contract.fullyQualifiedName); + return undefined; + } + let version; try { version = getContractVersion(contract.validationData, contract.fullyQualifiedName); @@ -119,7 +128,7 @@ function getUpgradeableContractReport( } debug('Checking: ' + contract.fullyQualifiedName); - const standaloneReport = getStandaloneReport(contract.validationData, version, opts); + const standaloneReport = getStandaloneReport(contract.validationData, version, opts, exclude); let reference: string | undefined; let storageLayoutReport: LayoutCompatibilityReport | undefined; @@ -145,7 +154,17 @@ function getStandaloneReport( data: ValidationData, version: Version, opts: ValidationOptions, + exclude?: string[], ): UpgradeableContractErrorReport { - const errors = getErrors(data, version, withValidationDefaults(opts)); - return new UpgradeableContractErrorReport(errors); + const allErrors = getErrors(data, version, withValidationDefaults(opts)); + + const includeErrors = allErrors.filter(e => { + return exclude === undefined || !exclude.some(glob => minimatch(getPath(e.src), glob)); + }); + + return new UpgradeableContractErrorReport(includeErrors); +} + +function getPath(src: string): string { + return src.split(':')[0]; } diff --git a/packages/core/src/cli/validate/validate-upgrade-safety.ts b/packages/core/src/cli/validate/validate-upgrade-safety.ts index a6042ee6b..2ead42962 100644 --- a/packages/core/src/cli/validate/validate-upgrade-safety.ts +++ b/packages/core/src/cli/validate/validate-upgrade-safety.ts @@ -36,6 +36,7 @@ export async function validateUpgradeSafety( reference?: string, opts: ValidateUpgradeSafetyOptions = {}, referenceBuildInfoDirs?: string[], + exclude?: string[], ): Promise { const allOpts = withCliDefaults(opts); @@ -63,7 +64,7 @@ export async function validateUpgradeSafety( const specifiedContracts = findSpecifiedContracts(buildInfoDictionary, allOpts, contract, reference); - const contractReports = getContractReports(buildInfoDictionary, allOpts, specifiedContracts); + const contractReports = getContractReports(buildInfoDictionary, allOpts, specifiedContracts, exclude); return getProjectReport(contractReports, specifiedContracts !== undefined); } diff --git a/packages/core/src/cli/validate/validations.ts b/packages/core/src/cli/validate/validations.ts index 6201cc8b0..08710e96a 100644 --- a/packages/core/src/cli/validate/validations.ts +++ b/packages/core/src/cli/validate/validations.ts @@ -42,7 +42,6 @@ function addContractsFromBuildInfo( for (const contractDef of findAll('ContractDefinition', ast)) { const fullyQualifiedName = getFullyQualifiedName(sourcePath, contractDef.name); - debug('Found: ' + fullyQualifiedName); sourceContracts.push({ node: contractDef, diff --git a/yarn.lock b/yarn.lock index 00e2cc185..728791615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4138,7 +4138,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.4: +minimatch@^9.0.4, minimatch@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== @@ -5227,16 +5227,7 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5307,7 +5298,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5321,13 +5312,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -5795,7 +5779,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -5822,15 +5806,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From d4d4452bd3892da80f203489fb87253fa44f9029 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 12:25:12 -0400 Subject: [PATCH 02/27] Use quotes in command --- packages/core/src/cli/cli.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 8aa3544bf..89e1c5533 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -578,7 +578,7 @@ test('validate - excludes by pattern - no match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude **/NoMatch.sol`)); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/NoMatch.sol'`)); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); @@ -588,7 +588,7 @@ test('validate - excludes by pattern - some match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude **/Abstract*.sol`)); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/Abstract*.sol'`)); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); @@ -598,6 +598,6 @@ test('validate - excludes by pattern - all match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync(`${CLI} validate ${temp} --exclude **/*Upgradeable*.sol`); + const output = await execAsync(`${CLI} validate ${temp} --exclude '**/*Upgradeable*.sol'`); t.snapshot(output); }); From 63363556731655818bd4051472addb8502b85218 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 12:40:10 -0400 Subject: [PATCH 03/27] Use single glob, improve reporting --- packages/core/src/cli/cli.test.ts | 11 +++++++ packages/core/src/cli/cli.test.ts.md | 14 +++++++-- packages/core/src/cli/cli.test.ts.snap | Bin 2983 -> 2995 bytes packages/core/src/cli/validate.ts | 4 +-- .../core/src/cli/validate/contract-report.ts | 28 ++++++++++-------- .../cli/validate/validate-upgrade-safety.ts | 2 +- packages/core/src/cli/validate/validations.ts | 2 -- 7 files changed, 41 insertions(+), 20 deletions(-) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 89e1c5533..349e4b143 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -601,3 +601,14 @@ test('validate - excludes by pattern - all match', async t => { const output = await execAsync(`${CLI} validate ${temp} --exclude '**/*Upgradeable*.sol'`); t.snapshot(output); }); + +test('validate - excludes single contract which has a reference', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/Validate.sol:BecomesBadLayout`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const output = await execAsync( + `${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude '**/Validate.sol'`, + ); + t.snapshot(output); +}); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index d3efc1255..666646e61 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -485,8 +485,16 @@ Generated by [AVA](https://avajs.dev). { stderr: '', - stdout: ` ✔ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ - ␊ - SUCCESS (1 upgradeable contract detected, 1 passed, 0 failed)␊ + stdout: `No upgradeable contracts detected.␊ + `, + } + +## validate - excludes single contract which has a reference + +> Snapshot 1 + + { + stderr: '', + stdout: `No upgradeable contracts detected.␊ `, } diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 6b932126ab5975a3e3bf921f43d79c4684297846..5575e6ac67fcdec0befe634293b58493760b4cff 100644 GIT binary patch literal 2995 zcmV;k3rzGuRzVwxOeabp61N^ecPd+mdFb_8v)Dsj9c^2qg=bId%C+1!~4y_Qc+CXA-*Gjd364jnM^ z$>QUk^=B)4>l|tNEd9y7=q}&nYX?=5pSlmVtI5e%hAQ2C`P^05Pu@CLN zFp$!^VE`Ye$qKV*XoGq%&J^_nZlSU>aySErnSfv@mx1NEx~6 z9vg{EDmQYV2~{FnU|@6B3-qm+C9x0Zq{dGX`cRPznvQfD@_;D-$GFu9OXN`mc^jy5ME3e5LiABnt6oU%ETMkZd<^D&!(+LCoR3_{w zU_Q{$uzAC$ei!~a2hbh1@xx|d$Y{V7{>%wGsRA&(s^7x8#ZsoCJtN#KN7$SohJ5bL`3dKc#EO&z?*8WWARo981z#fg8`b3N{htm z0?VN#jIJB4KZby%phT!XkP5?G3gQvBaW0R|wT%vi0gRZ`X)zz&HR5%LQ74Gvj0}Mk ztJxIn3E>I&I6WCktxak4c|w#LcUIN2H}TjOMFoNT>;Wb0*;8yQi@ zgK5{z=c%;o>CJjzf>>2TzWDTaq&N4?KQxN3AW4rxt*)0kPVhvJ?ot=;C zBKXc zEUd~&yr>9K7rT|*99ww!23#uN$l%P+;=~IxA5-Q``+IvW>g|K(klD@NfAGoN!V6+7 z5$)@pL>z4B|iv>uKWWHaEo5u|3_LKY;KYxQO5C_39hJ#U-tEkjQ&ER^q^p6xke=ZdRXgsf8 zx?>G;;=_|Tq3!D(LMx8u8O4$JQXKi}WpYHHYcGQy!!TdVhdB%#hMp+r2mjhzDe(VO z5d5>|IHy`uRVtP7qUvmms$o3)elDJ6`0)J{jec;!G#ZTUNy(|xWL5Em?o==?lz9(> zeJP)N%L4#`#~11Ih_OA+*&d6z>`~4<)e8H5&u zS$!~d|Fv$D((%RbBGh+kwbgn(KK?mcJ)@fHP-{@pf2GLxdBHWxmEFY{#+JF0VMO43 z?fVeao|iULustg1v$0Fe?g4Up8*XoB;3BpJuFkrA&_1)p?32yu-=>W7tBIV)pNUa6 z56;ad{cij%O+WBiErlCYqmqh2-`j9UY+)p4#T{)B_h7K&U!*$rhr-i?Km`L*Aq8;N{6o7CkS0JyG{7rR%fscOHIs;rAP*x8E(jz1hIK zQ>9Y!@z$+d6Q!FIrE3$VuR)z_-z;4Rq~NiT@hkc|k?|D5Z1nZor=tT=axF|oA(a_) zlZy*|(Dp8L8i$o?u3jsBU1k8ib2^~q>LWAb9owL=4L&$6*&Ec%K>9B!=l)~NcFzxY~%y%R> zbMx52+=8|fQ^$u*d3_PP^%)gxcxJTw2K;hNmoF_{7PINniPo8Yj1fqg-bLCBQv5qb ziZ4z{3ZFX7c0q2;=Ho_2u+Fn4IzhboDp6NT!Kla5p!>(F%6^WMPi%J3u44~qpJ?S+9M6aTj_W8(iqv5CL8V7ROtVCf97XUFw_rd;^1r*mNqnE#6q zpP}!=s~7F>=(od<!X<9U3&-gS@!$w-hh_bYmnhb_5fB2TawzvJ)b2 zR_g`*dUjuhi@K0KiX9oZf1(3NUHFVzS6u-Be>e6Roapdvh4}psqH;*}I$Tdclep?# z9iBR9)lWn%yZ)Oa89c3ySVH2a^D=wIN!-Ru3!~o+9 z6-fYaefjniC9yimli~p1&kgW~t7AMH2aQ3J^i{lSM9I?QzD}0zm@MZ^mb_fK+Ef{2 z%F&o9Lz&XMq&R9X{cfIo{YN8n0pa31j@j8j>7!IOurxYL{BmXk=WLW8jx-9sW|M6b pZFBzO7EDFXn~oN;wCg|6QU3*kvfl8^LRVMW{{sKq!@Fus0093`u^<2d literal 2983 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 referenceBuildInfoDirs?: string[]; - exclude?: string[]; + exclude?: string; } /** @@ -96,7 +96,7 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri const reference = getAndValidateString(parsedArgs, 'reference'); const opts = withDefaults(parsedArgs); const referenceBuildInfoDirs = getAndValidateString(parsedArgs, 'referenceBuildInfoDirs')?.split(/,+/); - const exclude = getAndValidateString(parsedArgs, 'exclude')?.split(/,+/); + const exclude = getAndValidateString(parsedArgs, 'exclude'); if (contract === undefined) { if (reference !== undefined) { diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 7ce8f8942..531297240 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -73,7 +73,7 @@ export function getContractReports( buildInfoDictionary: BuildInfoDictionary, opts: Required, specifiedContracts?: SpecifiedContracts, - exclude?: string[], + exclude?: string, ) { const upgradeableContractReports: UpgradeableContractReport[] = []; @@ -106,11 +106,10 @@ function getUpgradeableContractReport( contract: SourceContract, referenceContract: SourceContract | undefined, opts: ValidationOptions, - exclude?: string[], + exclude?: string, ): UpgradeableContractReport | undefined { - // TODO if this contract matches an exclude pattern, log something as debug and return undefined - if (exclude !== undefined && exclude.some(glob => minimatch(contract.fullyQualifiedName, glob))) { - debug('Excluding: ' + contract.fullyQualifiedName); + if (exclude !== undefined && minimatch(getPath(contract.fullyQualifiedName), exclude)) { + debug('Excluding contract: ' + contract.fullyQualifiedName); return undefined; } @@ -154,15 +153,20 @@ function getStandaloneReport( data: ValidationData, version: Version, opts: ValidationOptions, - exclude?: string[], + exclude?: string, ): UpgradeableContractErrorReport { const allErrors = getErrors(data, version, withValidationDefaults(opts)); - - const includeErrors = allErrors.filter(e => { - return exclude === undefined || !exclude.some(glob => minimatch(getPath(e.src), glob)); - }); - - return new UpgradeableContractErrorReport(includeErrors); + const reportErrors = + exclude !== undefined + ? allErrors.filter(e => { + const excluded = minimatch(getPath(e.src), exclude); + if (excluded) { + debug('Excluding error: ' + e.src); + } + return !excluded; + }) + : allErrors; + return new UpgradeableContractErrorReport(reportErrors); } function getPath(src: string): string { diff --git a/packages/core/src/cli/validate/validate-upgrade-safety.ts b/packages/core/src/cli/validate/validate-upgrade-safety.ts index 2ead42962..b5cb3b8f9 100644 --- a/packages/core/src/cli/validate/validate-upgrade-safety.ts +++ b/packages/core/src/cli/validate/validate-upgrade-safety.ts @@ -36,7 +36,7 @@ export async function validateUpgradeSafety( reference?: string, opts: ValidateUpgradeSafetyOptions = {}, referenceBuildInfoDirs?: string[], - exclude?: string[], + exclude?: string, ): Promise { const allOpts = withCliDefaults(opts); diff --git a/packages/core/src/cli/validate/validations.ts b/packages/core/src/cli/validate/validations.ts index 08710e96a..a4d2ff2c9 100644 --- a/packages/core/src/cli/validate/validations.ts +++ b/packages/core/src/cli/validate/validations.ts @@ -1,7 +1,5 @@ import { solcInputOutputDecoder, validate, ValidationRunData } from '../..'; -import debug from '../../utils/debug'; - import { findAll } from 'solidity-ast/utils'; import { ContractDefinition } from 'solidity-ast'; From 166cae4e84cd29d1354838ed8a8d45fe9410b71f Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:17:26 -0400 Subject: [PATCH 04/27] Throw error if specified contract does not have a report --- packages/core/src/cli/cli.test.ts | 8 ++++---- packages/core/src/cli/cli.test.ts.md | 10 ---------- packages/core/src/cli/cli.test.ts.snap | Bin 2995 -> 2974 bytes .../core/src/cli/validate/contract-report.ts | 10 ++++++++++ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 349e4b143..778ec4508 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -602,13 +602,13 @@ test('validate - excludes by pattern - all match', async t => { t.snapshot(output); }); -test('validate - excludes single contract which has a reference', async t => { +test('validate - excludes specified contract', async t => { const temp = await getTempDir(t); const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/Validate.sol:BecomesBadLayout`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync( + const error = await t.throwsAsync(execAsync( `${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude '**/Validate.sol'`, - ); - t.snapshot(output); + )); + t.true(error?.message.includes('No validation report found for contract contracts/test/cli/Validate.sol:BecomesBadLayout'), error?.message); }); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 666646e61..37edb575c 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -488,13 +488,3 @@ Generated by [AVA](https://avajs.dev). stdout: `No upgradeable contracts detected.␊ `, } - -## validate - excludes single contract which has a reference - -> Snapshot 1 - - { - stderr: '', - stdout: `No upgradeable contracts detected.␊ - `, - } diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 5575e6ac67fcdec0befe634293b58493760b4cff..2969a7c0b6e414042be978c24087321d702ad5a7 100644 GIT binary patch literal 2974 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 diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 531297240..89c61222f 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -19,6 +19,7 @@ import { LayoutCompatibilityReport } from '../../storage/report'; import { indent } from '../../utils/indent'; import { BuildInfoDictionary, SpecifiedContracts } from './validate-upgrade-safety'; import { minimatch } from 'minimatch'; +import { ValidateCommandError } from './error'; /** * Report for an upgradeable contract. @@ -96,12 +97,21 @@ export function getContractReports( const report = getUpgradeableContractReport(sourceContract, reference, { ...opts, kind: kind }, exclude); if (report !== undefined) { upgradeableContractReports.push(report); + } else if (specifiedContracts !== undefined) { + // If there was no report for the specified contract, it was excluded or is abstract. + const userAction = exclude !== undefined ? `Ensure the contract is not abstract and is not excluded by the exclude option.` : `Ensure the contract is not abstract.`; + throw new ValidateCommandError(`No validation report found for contract ${specifiedContracts.contract.fullyQualifiedName}`, () => userAction); } } } + return upgradeableContractReports; } +/** + * Gets a report for an upgradeable contract. + * Returns undefined if the contract is excluded or is abstract. + */ function getUpgradeableContractReport( contract: SourceContract, referenceContract: SourceContract | undefined, From 077bffd3930a8a26a9c02c79c5d3aefc16f96ce2 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:23:04 -0400 Subject: [PATCH 05/27] Update tests --- .../test/cli/AbstractUpgradeable.sol | 14 ------------ .../Abstract1.sol} | 2 +- .../Abstract2.sol} | 2 +- .../test/cli/excludes/AbstractUUPS.sol | 14 ++++++++++++ .../UsesAbstractUUPS.sol} | 6 +++--- packages/core/src/cli/cli.test.ts | 8 +++---- packages/core/src/cli/cli.test.ts.md | 20 +++++++++--------- packages/core/src/cli/cli.test.ts.snap | Bin 2974 -> 2978 bytes 8 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 packages/core/contracts/test/cli/AbstractUpgradeable.sol rename packages/core/contracts/test/cli/{AbstractNotUpgradeable.sol => excludes/Abstract1.sol} (75%) rename packages/core/contracts/test/cli/{AbstractNotUpgradeable2.sol => excludes/Abstract2.sol} (75%) create mode 100644 packages/core/contracts/test/cli/excludes/AbstractUUPS.sol rename packages/core/contracts/test/cli/{UsesUpgradeable.sol => excludes/UsesAbstractUUPS.sol} (57%) diff --git a/packages/core/contracts/test/cli/AbstractUpgradeable.sol b/packages/core/contracts/test/cli/AbstractUpgradeable.sol deleted file mode 100644 index 132479ab0..000000000 --- a/packages/core/contracts/test/cli/AbstractUpgradeable.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {AbstractNotUpgradeable} from "./AbstractNotUpgradeable.sol"; -import {AbstractNotUpgradeable2} from "./AbstractNotUpgradeable2.sol"; - -abstract contract AbstractUpgradeable is UUPSUpgradeable, AbstractNotUpgradeable, AbstractNotUpgradeable2 { - uint256 public immutable z; - - constructor(uint256 _x, uint256 _y, uint256 _z) AbstractNotUpgradeable(_x) AbstractNotUpgradeable2(_y) { - z = _z; - } -} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/AbstractNotUpgradeable.sol b/packages/core/contracts/test/cli/excludes/Abstract1.sol similarity index 75% rename from packages/core/contracts/test/cli/AbstractNotUpgradeable.sol rename to packages/core/contracts/test/cli/excludes/Abstract1.sol index 5a7ce8016..64deee0f7 100644 --- a/packages/core/contracts/test/cli/AbstractNotUpgradeable.sol +++ b/packages/core/contracts/test/cli/excludes/Abstract1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -abstract contract AbstractNotUpgradeable { +abstract contract Abstract1 { uint256 public immutable x; constructor(uint256 _x) { diff --git a/packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol b/packages/core/contracts/test/cli/excludes/Abstract2.sol similarity index 75% rename from packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol rename to packages/core/contracts/test/cli/excludes/Abstract2.sol index 058446e81..d8fea8654 100644 --- a/packages/core/contracts/test/cli/AbstractNotUpgradeable2.sol +++ b/packages/core/contracts/test/cli/excludes/Abstract2.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; -abstract contract AbstractNotUpgradeable2 { +abstract contract Abstract2 { uint256 public immutable y; constructor(uint256 _y) { diff --git a/packages/core/contracts/test/cli/excludes/AbstractUUPS.sol b/packages/core/contracts/test/cli/excludes/AbstractUUPS.sol new file mode 100644 index 000000000..85005b80b --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/AbstractUUPS.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {Abstract1} from "./Abstract1.sol"; +import {Abstract2} from "./Abstract2.sol"; + +abstract contract AbstractUUPS is UUPSUpgradeable, Abstract1, Abstract2 { + uint256 public immutable z; + + constructor(uint256 _x, uint256 _y, uint256 _z) Abstract1(_x) Abstract2(_y) { + z = _z; + } +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/UsesUpgradeable.sol b/packages/core/contracts/test/cli/excludes/UsesAbstractUUPS.sol similarity index 57% rename from packages/core/contracts/test/cli/UsesUpgradeable.sol rename to packages/core/contracts/test/cli/excludes/UsesAbstractUUPS.sol index 161615312..4a6f7f76b 100644 --- a/packages/core/contracts/test/cli/UsesUpgradeable.sol +++ b/packages/core/contracts/test/cli/excludes/UsesAbstractUUPS.sol @@ -3,10 +3,10 @@ pragma solidity ^0.8.9; // This contract is for testing only, it is not safe for use in production. -import {AbstractUpgradeable} from "./AbstractUpgradeable.sol"; +import {AbstractUUPS} from "./AbstractUUPS.sol"; -contract UsesUpgradeable is AbstractUpgradeable { - constructor(uint256 _x, uint256 _y, uint256 _z) AbstractUpgradeable(x, y, z) { +contract UsesAbstractUUPS is AbstractUUPS { + constructor(uint256 _x, uint256 _y, uint256 _z) AbstractUUPS(x, y, z) { } function _authorizeUpgrade(address newImplementation) internal pure override { diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 778ec4508..2adc56247 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -575,7 +575,7 @@ test('validate - contract must not have build info dir name - fully qualified', test('validate - excludes by pattern - no match', async t => { const temp = await getTempDir(t); - const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/NoMatch.sol'`)); @@ -585,7 +585,7 @@ test('validate - excludes by pattern - no match', async t => { test('validate - excludes by pattern - some match', async t => { const temp = await getTempDir(t); - const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/Abstract*.sol'`)); @@ -595,10 +595,10 @@ test('validate - excludes by pattern - some match', async t => { test('validate - excludes by pattern - all match', async t => { const temp = await getTempDir(t); - const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable`); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync(`${CLI} validate ${temp} --exclude '**/*Upgradeable*.sol'`); + const output = await execAsync(`${CLI} validate ${temp} --exclude '**/excludes/*.sol'`); t.snapshot(output); }); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 37edb575c..ad14300b1 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -428,35 +428,35 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 - `Stdout: ✘ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ + `Stdout: ✘ contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS␊ ␊ - contracts/test/cli/UsesUpgradeable.sol:9: Contract \`UsesUpgradeable\` has a constructor␊ + contracts/test/cli/excludes/UsesAbstractUUPS.sol:9: Contract \`UsesAbstractUUPS\` has a constructor␊ Define an initializer instead␊ https://zpl.in/upgrades/error-001␊ ␊ - contracts/test/cli/AbstractUpgradeable.sol:11: Contract \`AbstractUpgradeable\` has a constructor␊ + contracts/test/cli/excludes/AbstractUUPS.sol:11: Contract \`AbstractUUPS\` has a constructor␊ Define an initializer instead␊ https://zpl.in/upgrades/error-001␊ ␊ - contracts/test/cli/AbstractUpgradeable.sol:9: Variable \`z\` is immutable and will be initialized on the implementation␊ + contracts/test/cli/excludes/AbstractUUPS.sol:9: Variable \`z\` is immutable and will be initialized on the implementation␊ If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ Otherwise, consider a constant variable or use a mutable variable instead␊ https://zpl.in/upgrades/error-005␊ ␊ - contracts/test/cli/AbstractNotUpgradeable2.sol:7: Contract \`AbstractNotUpgradeable2\` has a constructor␊ + contracts/test/cli/excludes/Abstract2.sol:7: Contract \`Abstract2\` has a constructor␊ Define an initializer instead␊ https://zpl.in/upgrades/error-001␊ ␊ - contracts/test/cli/AbstractNotUpgradeable2.sol:5: Variable \`y\` is immutable and will be initialized on the implementation␊ + contracts/test/cli/excludes/Abstract2.sol:5: Variable \`y\` is immutable and will be initialized on the implementation␊ If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ Otherwise, consider a constant variable or use a mutable variable instead␊ https://zpl.in/upgrades/error-005␊ ␊ - contracts/test/cli/AbstractNotUpgradeable.sol:7: Contract \`AbstractNotUpgradeable\` has a constructor␊ + contracts/test/cli/excludes/Abstract1.sol:7: Contract \`Abstract1\` has a constructor␊ Define an initializer instead␊ https://zpl.in/upgrades/error-001␊ ␊ - contracts/test/cli/AbstractNotUpgradeable.sol:5: Variable \`x\` is immutable and will be initialized on the implementation␊ + contracts/test/cli/excludes/Abstract1.sol:5: Variable \`x\` is immutable and will be initialized on the implementation␊ If by design, annotate with '@custom:oz-upgrades-unsafe-allow state-variable-immutable'␊ Otherwise, consider a constant variable or use a mutable variable instead␊ https://zpl.in/upgrades/error-005␊ @@ -469,9 +469,9 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 - `Stdout: ✘ contracts/test/cli/UsesUpgradeable.sol:UsesUpgradeable␊ + `Stdout: ✘ contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS␊ ␊ - contracts/test/cli/UsesUpgradeable.sol:9: Contract \`UsesUpgradeable\` has a constructor␊ + contracts/test/cli/excludes/UsesAbstractUUPS.sol:9: Contract \`UsesAbstractUUPS\` has a constructor␊ Define an initializer instead␊ https://zpl.in/upgrades/error-001␊ ␊ diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 2969a7c0b6e414042be978c24087321d702ad5a7..ef59de8a66ff64acbbb13892f3c368c7cd8c1b0e 100644 GIT binary patch literal 2978 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 Date: Thu, 22 Aug 2024 13:35:40 -0400 Subject: [PATCH 06/27] Add tests --- .../test/cli/excludes/ImportVersions.sol | 9 +++++++++ .../core/contracts/test/cli/excludes/V1.sol | 6 ++++++ .../contracts/test/cli/excludes/V2Bad1.sol | 6 ++++++ .../contracts/test/cli/excludes/V2Bad2.sol | 6 ++++++ packages/core/src/cli/cli.test.ts | 12 ++++++++++++ packages/core/src/cli/cli.test.ts.md | 13 +++++++++++++ packages/core/src/cli/cli.test.ts.snap | Bin 2978 -> 3033 bytes 7 files changed, 52 insertions(+) create mode 100644 packages/core/contracts/test/cli/excludes/ImportVersions.sol create mode 100644 packages/core/contracts/test/cli/excludes/V1.sol create mode 100644 packages/core/contracts/test/cli/excludes/V2Bad1.sol create mode 100644 packages/core/contracts/test/cli/excludes/V2Bad2.sol diff --git a/packages/core/contracts/test/cli/excludes/ImportVersions.sol b/packages/core/contracts/test/cli/excludes/ImportVersions.sol new file mode 100644 index 000000000..c2fee413f --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/ImportVersions.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "./V1.sol"; +import "./V2Bad1.sol"; +import "./V2Bad2.sol"; + +abstract contract Dummy { +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/excludes/V1.sol b/packages/core/contracts/test/cli/excludes/V1.sol new file mode 100644 index 000000000..e109d3afe --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/V1.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +contract V1 { + uint256 public x; +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/excludes/V2Bad1.sol b/packages/core/contracts/test/cli/excludes/V2Bad1.sol new file mode 100644 index 000000000..15c500859 --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/V2Bad1.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/// @custom:oz-upgrades-from V1 +contract V2Bad1 { +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/excludes/V2Bad2.sol b/packages/core/contracts/test/cli/excludes/V2Bad2.sol new file mode 100644 index 000000000..faba82d87 --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/V2Bad2.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/// @custom:oz-upgrades-from V1 +contract V2Bad2 { +} \ No newline at end of file diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 2adc56247..2999c1db4 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -612,3 +612,15 @@ test('validate - excludes specified contract', async t => { )); t.true(error?.message.includes('No validation report found for contract contracts/test/cli/Validate.sol:BecomesBadLayout'), error?.message); }); + +test('validate - excludes one contract from layout comparisions', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersions.sol:Dummy`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const error = await t.throwsAsync(execAsync( + `${CLI} validate ${temp} --exclude '**/V2Bad1.sol'`, + )); + const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; + t.snapshot(expectation.join('\n')); +}); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index ad14300b1..2664aca59 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -488,3 +488,16 @@ Generated by [AVA](https://avajs.dev). stdout: `No upgradeable contracts detected.␊ `, } + +## validate - excludes one contract from layout comparisions + +> Snapshot 1 + + `Stdout: ✘ contracts/test/cli/excludes/V2Bad2.sol:V2Bad2 (upgrades from contracts/test/cli/excludes/V1.sol:V1)␊ + ␊ + V1: Deleted \`x\`␊ + > Keep the variable even if unused␊ + ␊ + FAILED (1 upgradeable contract detected, 0 passed, 1 failed)␊ + ␊ + Stderr: ` diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index ef59de8a66ff64acbbb13892f3c368c7cd8c1b0e..e5dd1daf012190a90afc1f1d79279c6abfac0d50 100644 GIT binary patch literal 3033 zcmV;~3nuhIRzV5RF zX0Qj_XCI3Q00000000B+Tg`JDNfoz}+6`+eMHaZQRY2EL-~=Q)Qk=xrdR=j3r{WOo zU|ELLR?2Q^dZfmqnaT8wWBCNd1+El_9G1g!;R1gF+_+F2_p3-5K$jC!Pz zHDf!rmzAq*OEc5m@BQBIee}nCVm2+OwJ%WYrzi(h?W7}TfF z-+6L%>e>|k6yBP8_sR$FGz4w4DzV)|^1yMKeZ*XsS=^or+_pyzCQ2>GW8{EZ96Dg+ zqos$9^{1=5>l=?YcURZ9mS4c7&1c)|n;Z4z7t_kc-@pB$BhAu$edCE+lj=1 zCPhLmYXnKSeT=m@G;8+xXv|89J!XO)c8igvt+hvMTWcG&wOvj48nuaIgUrwrurrWe zY7|XdM`A!YAZrN+u|D7ijF4INz7#qLFrKt3n92iRBNheg_>xc5;{s4mgGX8zJAI&x zTy>60u}dm9vY`o8BAZ}f6x?7Yx0w+^*cStN2ltzd+wEcSUIqa0RxJG~;o5LQ?R<`g zm2Olj1vYwaeV@B^1w^gGTKiIUP3=$?K^TwRKVjZ*P=FOgi-ttI3{tN{4;Xkz2J{9P z^bl#c4y;?{o)`!u0xeAqhzIIg3Pm{!qnzup1MUQZ957FyZ$&JLd^jUDeumHo0`2B^ z0BnUoQIQQhaqNhI(3>uXY6Nna{E*Bn!L1D->vDAluro2JConsf;M^W%322c4<03K$ zMvR3(+F*};&xSPRDJf>j8ikOYc1r~{WTnkt2CN8zwXDEEJr!sma2V{n5YAI$h_bh$ z{O-C-LqX!#`>4Yr+_8kO26u=DZ7WP^Si9Cq#7DMBKH`N^5K&wgeTzR>~vUZwQZ2vYl}&-H7T|x#nz$(JqYTu>gnGI2f?3J znff5+5Z+fGJ`0~wLwl~{`>v?Y%^kVctXAgENz;{X-!5lW|0huLao1w`^t}uEHiV1; zy3-*Gu>z3vXL;nUgwJLjf8k=spP!G%*Tc-o$G?-+Uh6ibAgF^UcKc%4Eer_a5tI~- z#XB5V!U)&G)ab z*hUS&iEbC0Js1!kic+SASV&NUN;b5a5hNj1=EUVk)4_@&s`;X>@k&Xbe- zSpAYV1)GD)^sqM<_}mh6141AuIgGoIHSg%g-S((0u!e)go8QJ-(z}(JTB<~`jj)_} zDvO0RnZ)yo5O%Rs&djmJ`)|OdvW*PR{4^@Ou<|iv&9t|>+otXwXbzQKdYQL^+4mB#x<|U8_Q+VlkW?>>ciDQ2m%OS56D!+Ls+LIkgXLEI_l0UkCTK zl*)M}-*9Zr}V%kTW<`P&!e{pCCN zFM<0%T3LU(wn}c6=SM698geBW7lrN-7iPrxX@QuOTg(8MVFm@7S4lVvJA6-@hGCM{ z`Wl*#{rt1UbnG8f+H@=fWs-i9-Qs6&a0TKp7^Tr*6y+=`u~0KSUoHGI0nlFy`2d>a z)eCp5VNQH_94EAOy#r{)(LCcg@?L@?U%g0<=(+YH=rIcON7*okp@YB`#q8i;c`E__ ze{zC<+8XCXbEL$^PQd|r| z3qn>OF5Q2l+oW)G{;LS}My{u` zoTq&sf!g!JW&*YcIej*AiOMb@x4Yr=R|d{wN#OF#%ZKe#$!DK*PX8`poL^66-2RM> zvbld|HW_r|Z)y60&uS&yuo~q=4Eo-NGiC`R-Yf2EgE;%c9se@Xu{RQ)J_J&){?}M9 za=#u zWmv?YCPb{IintRW>VP=cWq4Qx<6St-R2PONeVlNP&m+YGQUlCnJiL|ah8-W zRLV&v0bt>g9gxT=xm5;{ z1ym~Mf`zIc`j@mCuy^uFNKPg1RY|yl5>Hm-u`xXMqa8Z+doI&zB4{0-2*a|+W3t|n z;LI;z2lI>CN=zMZw&d|e?ABvcu+f##&KvN{30?kg>9Ukgmu@)E9AJz<%JdJ?rjX*_ z2~vE1LQ;6tZgp~UqmqpqDZx6+oah+w7OF%YDFve*NrUbksYmuQ>>Q_bd`{UU+ViZ8 z-SX_$=H<~_o*(85JlYEbBNG3&FCy{(DPQ96PZ%z$23S4??CEj+(}WBE{bVkz0rRB@ z@hSS=zkJdDmVP??P;NNMkPfoo;d!;#(4~H>Gt7%?e@^h?57)->A{t??Az1%VOygNy zZMhCyJSGSq-_fFeW_$37^E#$Ijx(_eL*nB;WMBR-mh1riPUJ+G`|t&Z=#>zn%1ZTy zTwg?kIO_Esp4fZUH%U#TB#g(~b}AjWqr;+Wug@`Wf$B6Z?B`60fWAL2?BLWZePxwO1cLf_R%(VLLs>_|}_O^WiR zB}I9d6o(U1j3h<>DB`#k^V?af@*j=O_`<#qRJAOAhX46gu3T&09)W;0F bcKyaGmT9}Fr#Sp@M(p_?HLyZ=*-QWcAym&` literal 2978 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 Date: Thu, 22 Aug 2024 13:47:58 -0400 Subject: [PATCH 07/27] Update docs, use double quotes --- docs/modules/ROOT/pages/api-core.adoc | 1 + packages/core/src/cli/cli.test.ts | 10 +++++----- packages/core/src/cli/cli.test.ts.md | 2 ++ packages/core/src/cli/cli.test.ts.snap | Bin 3033 -> 3136 bytes packages/core/src/cli/validate.ts | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index a9025a734..dc80e899f 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -120,6 +120,7 @@ If any errors are found, the command will exit with a non-zero exit code and pri * `--reference ` Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. * `--requireReference` Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. * `--referenceBuildInfoDirs` Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. +* `--exclude ""` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/**/*.sol"`. Does not apply to reference contracts. * `--unsafeAllow ""` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 2999c1db4..27e12c7bd 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -578,7 +578,7 @@ test('validate - excludes by pattern - no match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/NoMatch.sol'`)); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude "**/NoMatch.sol"`)); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); @@ -588,7 +588,7 @@ test('validate - excludes by pattern - some match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude '**/Abstract*.sol'`)); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude "**/Abstract*.sol"`)); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); @@ -598,7 +598,7 @@ test('validate - excludes by pattern - all match', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync(`${CLI} validate ${temp} --exclude '**/excludes/*.sol'`); + const output = await execAsync(`${CLI} validate ${temp} --exclude "**/excludes/*.sol"`); t.snapshot(output); }); @@ -608,7 +608,7 @@ test('validate - excludes specified contract', async t => { await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); const error = await t.throwsAsync(execAsync( - `${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude '**/Validate.sol'`, + `${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude "**/Validate.sol"`, )); t.true(error?.message.includes('No validation report found for contract contracts/test/cli/Validate.sol:BecomesBadLayout'), error?.message); }); @@ -619,7 +619,7 @@ test('validate - excludes one contract from layout comparisions', async t => { await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); const error = await t.throwsAsync(execAsync( - `${CLI} validate ${temp} --exclude '**/V2Bad1.sol'`, + `${CLI} validate ${temp} --exclude "**/V2Bad1.sol"`, )); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 2664aca59..dabd6eb39 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -20,6 +20,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory.␊ + --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts.␊ --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ @@ -41,6 +42,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory.␊ + --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts.␊ --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index e5dd1daf012190a90afc1f1d79279c6abfac0d50..482794e5be4153d8e7eff9889f99fb0ccbb969c0 100644 GIT binary patch literal 3136 zcmV-G48QY1RzV%2OoetcP?DG@Lu=Ks7D%E zGqz)US-Hx#G&9}(-tYb1M}N%6X47(7d*aQv|HypqTg>P%%jLqRuIM6M zngO>A!fn$b2KV53$2%m{HsWCfdEH@thj|44z%7sDei2H}|MAwDO9<+A@ zUrOr)K75=e%gm&K1?s^#Q`GahiOQDca3vgWikOZ^o>0%|P@lM-^9zX)T$_SE1|D2> z0^0!5q6eqRnn@0wz>BVsK!ALdv;yG+ph}LOPDOl}bm1luE^Be~kZ>3-Reiu1;Z%4@ zFiWM#USy$GU*FtVs%-+In*g9qy9}i^1Is!juL7`^$(a#eHzmk%V*n#Er&PdpB5|Ne zkxIr9UNH>rSYh&(W~b zjY_4!M$c{Rakrs>sC8ItPpYn|9m*mIUHQo0}si7ULS)V zBkk6Jb<5lneSt)vrKth&KwV3rC}&}mb3L}toj{O%<_Ywzh$WE^XQal@5c)u%-TV%K ztq>?GvSBBV9T5};8YogLad6TbAt;ePe& z{8^UC9HJ=UJ@w(U@EJ9<=Q_UcifXxhUA{_BCHA0AT4y#EVQ$f2{g-XR@I62ro*wvu=F=MWr7R0qL!#NQ*VfKavXjbtX z;J%hpIj`jFj;*)0dh;KBtMF+1wCIm*T0nI2m&Joxd`B_oBSN za_`|KaR1e%wP!2Kj80LMvR~4h)KD{41gJCP@s90gtM@N_qAyl zCTXp&f%(|aKTS->{xP9V$1+eR=_lDOe)a}eAP$028V*KL&Y}`aPlNN-!Y2uU{#wWf z&^WJNxMK}+;)CNjp{-QzLo1Hv8O4$J6CC;SMRG*XwHHB;VVJLG!yJYV0#_8XgMa0n z1o;2S3I1tooDtDL z7b@i?I!SSyYP#-@Jdu_xcu7;94DI4^&{P(^D10?m_e+JVGw^>7ez)QGYlU~;E4*88 z;%Tr#A^v#d#*K->^@+ljiNaUlnJZr}Tm_`ywvh2F{5p|x7s71#^~y)115td?O-3PA z863t37y6*>9Z@aqSE`wMt@L%70`%6&fR?k5)QWd(gWNXw;YrEfq(%zTe@i&`U$Pe~ zIuuZ;oC_AJdgxu!YQV#jPeO7k`JhU|6_j|gB9D#Xu^;Uit$*k;ttNuj@rf`jdpsuV z9SP3t9Ck1}udT#1@McRM$i!|vMg<#Q8EwA>zZ}!$|CTNb>2&Fa^UOZR2&7E!XmAQC z{+%GjXD1|uN9|T8CpTuYaU&&IXPFZnBi>wd(@PXT*+T>odnh5vps7uJCJ zLWKAfeIH)FXn$Kj9j;zskRd&M%|R_T$QL07d2#K}310l++DKkRBb2uU>m7>Odfrf5 zu6-Ae3Bt#BG_Rl8?tkLEj%knLOsv9y__z<*lmGK2J3zl3IT7YQe1Rc)C4{K5QoZxn z6VV`!dLfA?_FnZ(QWGf&BH!1$UArd~SX z;2;si_>M&!6C6*z;zdcMPJAan#P{<_WTb+zpQb6P5=OV@B`cc literal 3033 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 bcKyaGmT9}Fr#Sp@M(p_?HLyZ=*-QWcAym&` diff --git a/packages/core/src/cli/validate.ts b/packages/core/src/cli/validate.ts index 74e3d1169..5ac9f96f1 100644 --- a/packages/core/src/cli/validate.ts +++ b/packages/core/src/cli/validate.ts @@ -17,6 +17,7 @@ Options: --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated. --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation. --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. + --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( ', ', )} From ba384d570516db20856752db2456f4207168a989 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:49:09 -0400 Subject: [PATCH 08/27] 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 7af4ee161..0f629a02b 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- CLI: Support `--exclude` option. + ## 1.36.0 (2024-08-21) - Update dependency on Slang. ([#1059](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1059)) From 610d2cda605b719eccef4389b85ae1bc6a2a560a Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:52:55 -0400 Subject: [PATCH 09/27] Add dash separator. Fix escaping of asterisk --- docs/modules/ROOT/pages/api-core.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index dc80e899f..7b840b5db 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -116,11 +116,11 @@ If any errors are found, the command will exit with a non-zero exit code and pri *Options:* -* `--contract ` The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated. -* `--reference ` Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. -* `--requireReference` Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. -* `--referenceBuildInfoDirs` Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. -* `--exclude ""` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/**/*.sol"`. Does not apply to reference contracts. +* `--contract ` - The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated. +* `--reference ` - Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. +* `--requireReference` - Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. +* `--referenceBuildInfoDirs` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. +* `--exclude ""` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. * `--unsafeAllow ""` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. From b05169d5ca66f25119ca8fb260108fd151e4e6f9 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:54:49 -0400 Subject: [PATCH 10/27] Remove unused --- packages/core/src/cli/validate.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/cli/validate.ts b/packages/core/src/cli/validate.ts index 5ac9f96f1..a9eb54a54 100644 --- a/packages/core/src/cli/validate.ts +++ b/packages/core/src/cli/validate.ts @@ -134,7 +134,6 @@ function validateOptions(parsedArgs: minimist.ParsedArgs) { 'reference', 'requireReference', 'referenceBuildInfoDirs', - 'skipPatterns', 'exclude', ].includes(key), ); From a96ebb84eb241858b8774b11fdd63b09ff35a0d5 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:57:14 -0400 Subject: [PATCH 11/27] Revert --- packages/core/src/cli/validate/validations.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/cli/validate/validations.ts b/packages/core/src/cli/validate/validations.ts index a4d2ff2c9..6201cc8b0 100644 --- a/packages/core/src/cli/validate/validations.ts +++ b/packages/core/src/cli/validate/validations.ts @@ -1,5 +1,7 @@ import { solcInputOutputDecoder, validate, ValidationRunData } from '../..'; +import debug from '../../utils/debug'; + import { findAll } from 'solidity-ast/utils'; import { ContractDefinition } from 'solidity-ast'; @@ -40,6 +42,7 @@ function addContractsFromBuildInfo( for (const contractDef of findAll('ContractDefinition', ast)) { const fullyQualifiedName = getFullyQualifiedName(sourcePath, contractDef.name); + debug('Found: ' + fullyQualifiedName); sourceContracts.push({ node: contractDef, From ae56a61338f8095941e293855072263ae6426af8 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 13:58:46 -0400 Subject: [PATCH 12/27] Rename --- packages/core/src/cli/validate/contract-report.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 89c61222f..963b78d23 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -179,6 +179,6 @@ function getStandaloneReport( return new UpgradeableContractErrorReport(reportErrors); } -function getPath(src: string): string { - return src.split(':')[0]; +function getPath(srcOrFullyQualifiedName: string): string { + return srcOrFullyQualifiedName.split(':')[0]; } From 53deb62fbe7c0db921f317d909725981e382ca96 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 14:48:07 -0400 Subject: [PATCH 13/27] Update changelog, fix lint --- packages/core/CHANGELOG.md | 2 +- packages/core/src/cli/cli.test.ts | 15 ++++++++------- packages/core/src/cli/validate/contract-report.ts | 10 ++++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 0f629a02b..55378041e 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- CLI: Support `--exclude` option. +- CLI: Support `--exclude` option. ([#1065](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1065)) ## 1.36.0 (2024-08-21) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 27e12c7bd..29f6820e1 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -607,10 +607,13 @@ test('validate - excludes specified contract', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/Validate.sol:BecomesBadLayout`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync( - `${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude "**/Validate.sol"`, - )); - t.true(error?.message.includes('No validation report found for contract contracts/test/cli/Validate.sol:BecomesBadLayout'), error?.message); + const error = await t.throwsAsync( + execAsync(`${CLI} validate ${temp} --contract BecomesBadLayout --reference StorageV1 --exclude "**/Validate.sol"`), + ); + t.true( + error?.message.includes('No validation report found for contract contracts/test/cli/Validate.sol:BecomesBadLayout'), + error?.message, + ); }); test('validate - excludes one contract from layout comparisions', async t => { @@ -618,9 +621,7 @@ test('validate - excludes one contract from layout comparisions', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersions.sol:Dummy`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const error = await t.throwsAsync(execAsync( - `${CLI} validate ${temp} --exclude "**/V2Bad1.sol"`, - )); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude "**/V2Bad1.sol"`)); const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 963b78d23..d7e9e94d6 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -99,8 +99,14 @@ export function getContractReports( upgradeableContractReports.push(report); } else if (specifiedContracts !== undefined) { // If there was no report for the specified contract, it was excluded or is abstract. - const userAction = exclude !== undefined ? `Ensure the contract is not abstract and is not excluded by the exclude option.` : `Ensure the contract is not abstract.`; - throw new ValidateCommandError(`No validation report found for contract ${specifiedContracts.contract.fullyQualifiedName}`, () => userAction); + const userAction = + exclude !== undefined + ? `Ensure the contract is not abstract and is not excluded by the exclude option.` + : `Ensure the contract is not abstract.`; + throw new ValidateCommandError( + `No validation report found for contract ${specifiedContracts.contract.fullyQualifiedName}`, + () => userAction, + ); } } } From 46a9432fe104f444b481f88fc83eda02683b7a11 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 16:23:51 -0400 Subject: [PATCH 14/27] Support referenceBuildInfoDirs and excludes as arrays --- packages/core/src/cli/cli.test.ts | 22 +++++++++++-- packages/core/src/cli/cli.test.ts.md | 14 +++++++++ packages/core/src/cli/cli.test.ts.snap | Bin 3136 -> 3160 bytes packages/core/src/cli/validate.ts | 29 +++++++++++++++--- .../core/src/cli/validate/contract-report.ts | 11 ++++--- .../cli/validate/validate-upgrade-safety.ts | 3 +- 6 files changed, 65 insertions(+), 14 deletions(-) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 29f6820e1..61a9c9f28 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -444,7 +444,7 @@ test('validate - references other build info dir by command with fully qualified t.snapshot(expectation.join('\n')); }); -test('validate - references multiple build info dirs by annotation', async t => { +async function setupMultipleBuildInfoDirsTest(t: ExecutionContext) { const temp = await getTempDir(t); const v1Dir = path.join(temp, 'build-info-v1'); @@ -460,13 +460,18 @@ test('validate - references multiple build info dirs by annotation', async t => const v2BranchDir = path.join(temp, 'build-info-v2-branch'); await fs.mkdir(v2BranchDir); const v2BranchBuildInfoOk = await artifacts.getBuildInfo( - `contracts/test/cli/ValidateBuildInfoV2_Branch_Ok.sol:MyContract`, + `contracts/test/cli/ValidateBuildInfoV2_Branch_Ok.sol:MyContract` ); const v2BranchBuildInfoBad = await artifacts.getBuildInfo( - `contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract`, + `contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract` ); await fs.writeFile(path.join(v2BranchDir, 'ok.json'), JSON.stringify(v2BranchBuildInfoOk)); await fs.writeFile(path.join(v2BranchDir, 'bad.json'), JSON.stringify(v2BranchBuildInfoBad)); + return { v2BranchDir, v1Dir, v2Dir }; +} + +test('validate - references multiple build info dirs by annotation', async t => { + const { v2BranchDir, v1Dir, v2Dir } = await setupMultipleBuildInfoDirsTest(t); const error = await t.throwsAsync( execAsync(`${CLI} validate ${v2BranchDir} --referenceBuildInfoDirs ${v1Dir},${v2Dir}`), @@ -475,6 +480,16 @@ test('validate - references multiple build info dirs by annotation', async t => t.snapshot(expectation.join('\n')); }); +test('validate - references multiple build info dirs by annotation - same arg multiple times', async t => { + const { v2BranchDir, v1Dir, v2Dir } = await setupMultipleBuildInfoDirsTest(t); + + const error = await t.throwsAsync( + execAsync(`${CLI} validate ${v2BranchDir} --referenceBuildInfoDirs ${v1Dir} --referenceBuildInfoDirs ${v2Dir}`), + ); + const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; + t.snapshot(expectation.join('\n')); +}); + test('validate - references other build info dir by annotation - ok', async t => { const temp = await getTempDir(t); const referenceDir = path.join(temp, 'build-info-v1'); @@ -625,3 +640,4 @@ test('validate - excludes one contract from layout comparisions', async t => { const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); + diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index dabd6eb39..2a5da0293 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -385,6 +385,20 @@ Generated by [AVA](https://avajs.dev). ## validate - references multiple build info dirs by annotation +> Snapshot 1 + + `Stdout: ✘ contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract (upgrades from build-info-v2:contracts/test/cli/ValidateBuildInfoV2_Ok.sol:MyContract)␊ + ␊ + contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:8: Renamed \`z\` to \`zBranch\`␊ + ␊ + ✔ contracts/test/cli/ValidateBuildInfoV2_Branch_Ok.sol:MyContract (upgrades from build-info-v1:contracts/test/cli/ValidateBuildInfoV1.sol:MyContract)␊ + ␊ + FAILED (2 upgradeable contracts detected, 1 passed, 1 failed)␊ + ␊ + Stderr: ` + +## validate - references multiple build info dirs by annotation - same arg multiple times + > Snapshot 1 `Stdout: ✘ contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract (upgrades from build-info-v2:contracts/test/cli/ValidateBuildInfoV2_Ok.sol:MyContract)␊ diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 482794e5be4153d8e7eff9889f99fb0ccbb969c0..2aac1b621f2327c38826455e7590738f059d9f54 100644 GIT binary patch literal 3160 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 literal 3136 zcmV-G48QY1RzV%2OoetcP?DG@Lu=Ks7D%E zGqz)US-Hx#G&9}(-tYb1M}N%6X47(7d*aQv|HypqTg>P%%jLqRuIM6M zngO>A!fn$b2KV53$2%m{HsWCfdEH@thj|44z%7sDei2H}|MAwDO9<+A@ zUrOr)K75=e%gm&K1?s^#Q`GahiOQDca3vgWikOZ^o>0%|P@lM-^9zX)T$_SE1|D2> z0^0!5q6eqRnn@0wz>BVsK!ALdv;yG+ph}LOPDOl}bm1luE^Be~kZ>3-Reiu1;Z%4@ zFiWM#USy$GU*FtVs%-+In*g9qy9}i^1Is!juL7`^$(a#eHzmk%V*n#Er&PdpB5|Ne zkxIr9UNH>rSYh&(W~b zjY_4!M$c{Rakrs>sC8ItPpYn|9m*mIUHQo0}si7ULS)V zBkk6Jb<5lneSt)vrKth&KwV3rC}&}mb3L}toj{O%<_Ywzh$WE^XQal@5c)u%-TV%K ztq>?GvSBBV9T5};8YogLad6TbAt;ePe& z{8^UC9HJ=UJ@w(U@EJ9<=Q_UcifXxhUA{_BCHA0AT4y#EVQ$f2{g-XR@I62ro*wvu=F=MWr7R0qL!#NQ*VfKavXjbtX z;J%hpIj`jFj;*)0dh;KBtMF+1wCIm*T0nI2m&Joxd`B_oBSN za_`|KaR1e%wP!2Kj80LMvR~4h)KD{41gJCP@s90gtM@N_qAyl zCTXp&f%(|aKTS->{xP9V$1+eR=_lDOe)a}eAP$028V*KL&Y}`aPlNN-!Y2uU{#wWf z&^WJNxMK}+;)CNjp{-QzLo1Hv8O4$J6CC;SMRG*XwHHB;VVJLG!yJYV0#_8XgMa0n z1o;2S3I1tooDtDL z7b@i?I!SSyYP#-@Jdu_xcu7;94DI4^&{P(^D10?m_e+JVGw^>7ez)QGYlU~;E4*88 z;%Tr#A^v#d#*K->^@+ljiNaUlnJZr}Tm_`ywvh2F{5p|x7s71#^~y)115td?O-3PA z863t37y6*>9Z@aqSE`wMt@L%70`%6&fR?k5)QWd(gWNXw;YrEfq(%zTe@i&`U$Pe~ zIuuZ;oC_AJdgxu!YQV#jPeO7k`JhU|6_j|gB9D#Xu^;Uit$*k;ttNuj@rf`jdpsuV z9SP3t9Ck1}udT#1@McRM$i!|vMg<#Q8EwA>zZ}!$|CTNb>2&Fa^UOZR2&7E!XmAQC z{+%GjXD1|uN9|T8CpTuYaU&&IXPFZnBi>wd(@PXT*+T>odnh5vps7uJCJ zLWKAfeIH)FXn$Kj9j;zskRd&M%|R_T$QL07d2#K}310l++DKkRBb2uU>m7>Odfrf5 zu6-Ae3Bt#BG_Rl8?tkLEj%knLOsv9y__z<*lmGK2J3zl3IT7YQe1Rc)C4{K5QoZxn z6VV`!dLfA?_FnZ(QWGf&BH!1$UArd~SX z;2;si_>M&!6C6*z;zdcMPJAan#P{<_WTb+zpQb6P5=OV@B`cc diff --git a/packages/core/src/cli/validate.ts b/packages/core/src/cli/validate.ts index a9eb54a54..c15f70a41 100644 --- a/packages/core/src/cli/validate.ts +++ b/packages/core/src/cli/validate.ts @@ -76,7 +76,7 @@ interface FunctionArgs { reference?: string; opts: Required; referenceBuildInfoDirs?: string[]; - exclude?: string; + exclude?: string[]; } /** @@ -96,8 +96,8 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri const contract = getAndValidateString(parsedArgs, 'contract'); const reference = getAndValidateString(parsedArgs, 'reference'); const opts = withDefaults(parsedArgs); - const referenceBuildInfoDirs = getAndValidateString(parsedArgs, 'referenceBuildInfoDirs')?.split(/,+/); - const exclude = getAndValidateString(parsedArgs, 'exclude'); + const referenceBuildInfoDirs = getAndValidateStringArray(parsedArgs, 'referenceBuildInfoDirs'); + const exclude = getAndValidateStringArray(parsedArgs, 'exclude'); if (contract === undefined) { if (reference !== undefined) { @@ -112,12 +112,31 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri function getAndValidateString(parsedArgs: minimist.ParsedArgs, option: string): string | undefined { const value = parsedArgs[option]; - if (value !== undefined && value.trim().length === 0) { - throw new Error(`Invalid option: --${option} cannot be empty`); + if (value !== undefined) { + assertNonEmptyOption(value, option); } return value; } +function getAndValidateStringArray(parsedArgs: minimist.ParsedArgs, option: string): string[] | undefined { + const value = parsedArgs[option]; + if (value !== undefined) { + if (Array.isArray(value)) { + return value; + } else { + assertNonEmptyOption(value, option); + return value.split(/,+/); + } + } + return value; +} + +function assertNonEmptyOption(value: string, option: string) { + if (value.trim().length === 0) { + throw new Error(`Invalid option: --${option} cannot be empty`); + } +} + function validateOptions(parsedArgs: minimist.ParsedArgs) { const invalidArgs = Object.keys(parsedArgs).filter( key => diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index d7e9e94d6..81a4ee5c8 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -68,13 +68,14 @@ export class UpgradeableContractReport implements Report { * @param buildInfoDictionary Dictionary of build info directories and the source contracts they contain. * @param opts The validation options. * @param specifiedContracts If provided, only the specified contract (upgrading from its reference contract) will be reported. + * @param exclude Exclude validations for contracts in source file paths that match the given glob patterns. * @returns The upgradeable contract reports. */ export function getContractReports( buildInfoDictionary: BuildInfoDictionary, opts: Required, specifiedContracts?: SpecifiedContracts, - exclude?: string, + exclude?: string[], ) { const upgradeableContractReports: UpgradeableContractReport[] = []; @@ -122,9 +123,9 @@ function getUpgradeableContractReport( contract: SourceContract, referenceContract: SourceContract | undefined, opts: ValidationOptions, - exclude?: string, + exclude?: string[], ): UpgradeableContractReport | undefined { - if (exclude !== undefined && minimatch(getPath(contract.fullyQualifiedName), exclude)) { + if (exclude !== undefined && exclude.some(glob => minimatch(getPath(contract.fullyQualifiedName), glob))) { debug('Excluding contract: ' + contract.fullyQualifiedName); return undefined; } @@ -169,13 +170,13 @@ function getStandaloneReport( data: ValidationData, version: Version, opts: ValidationOptions, - exclude?: string, + exclude?: string[], ): UpgradeableContractErrorReport { const allErrors = getErrors(data, version, withValidationDefaults(opts)); const reportErrors = exclude !== undefined ? allErrors.filter(e => { - const excluded = minimatch(getPath(e.src), exclude); + const excluded = exclude.some(glob => minimatch(getPath(e.src), glob)); if (excluded) { debug('Excluding error: ' + e.src); } diff --git a/packages/core/src/cli/validate/validate-upgrade-safety.ts b/packages/core/src/cli/validate/validate-upgrade-safety.ts index b5cb3b8f9..8cd7ed85e 100644 --- a/packages/core/src/cli/validate/validate-upgrade-safety.ts +++ b/packages/core/src/cli/validate/validate-upgrade-safety.ts @@ -28,6 +28,7 @@ export type SpecifiedContracts = { * @param reference The name or fully qualified name of the reference contract to use for storage layout comparisons. Can only be used along with `contract`. If not specified, uses the `@custom:oz-upgrades-from` annotation in the contract that is being validated. * @param opts Validation options, or undefined to use the default validation options. * @param referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `reference` param or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. + * @param exclude Exclude validations for contracts in source file paths that match the given glob patterns. * @returns The project report. */ export async function validateUpgradeSafety( @@ -36,7 +37,7 @@ export async function validateUpgradeSafety( reference?: string, opts: ValidateUpgradeSafetyOptions = {}, referenceBuildInfoDirs?: string[], - exclude?: string, + exclude?: string[], ): Promise { const allOpts = withCliDefaults(opts); From 45211f6e2fd6e880b6ff8e391af36ca472305b01 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 16:57:15 -0400 Subject: [PATCH 15/27] Standarize handling of string array params --- docs/modules/ROOT/pages/api-core.adoc | 6 ++--- packages/core/src/cli/cli.test.ts | 5 ++--- packages/core/src/cli/cli.test.ts.md | 12 +++++----- packages/core/src/cli/cli.test.ts.snap | Bin 3160 -> 3231 bytes packages/core/src/cli/validate.test.ts | 22 +++++++++++++++++++ packages/core/src/cli/validate.ts | 29 ++++++++++--------------- 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index 7b840b5db..66fb2911c 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -119,9 +119,9 @@ If any errors are found, the command will exit with a non-zero exit code and pri * `--contract ` - The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated. * `--reference ` - Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. * `--requireReference` - Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. -* `--referenceBuildInfoDirs` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. -* `--exclude ""` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. -* `--unsafeAllow ""` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` +* `--referenceBuildInfoDirs "[,...]"` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. +* `--exclude "[,...]"` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern. +* `--unsafeAllow "[,...]"` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 61a9c9f28..309c9a650 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -460,10 +460,10 @@ async function setupMultipleBuildInfoDirsTest(t: ExecutionContext) { const v2BranchDir = path.join(temp, 'build-info-v2-branch'); await fs.mkdir(v2BranchDir); const v2BranchBuildInfoOk = await artifacts.getBuildInfo( - `contracts/test/cli/ValidateBuildInfoV2_Branch_Ok.sol:MyContract` + `contracts/test/cli/ValidateBuildInfoV2_Branch_Ok.sol:MyContract`, ); const v2BranchBuildInfoBad = await artifacts.getBuildInfo( - `contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract` + `contracts/test/cli/ValidateBuildInfoV2_Branch_Bad.sol:MyContract`, ); await fs.writeFile(path.join(v2BranchDir, 'ok.json'), JSON.stringify(v2BranchBuildInfoOk)); await fs.writeFile(path.join(v2BranchDir, 'bad.json'), JSON.stringify(v2BranchBuildInfoBad)); @@ -640,4 +640,3 @@ test('validate - excludes one contract from layout comparisions', async t => { const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; t.snapshot(expectation.join('\n')); }); - diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 2a5da0293..0b676f807 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -19,9 +19,9 @@ Generated by [AVA](https://avajs.dev). --contract The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated.␊ --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ - --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory.␊ - --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts.␊ - --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ + --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ + --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern.␊ + --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ ` @@ -41,9 +41,9 @@ Generated by [AVA](https://avajs.dev). --contract The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated.␊ --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ - --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory.␊ - --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts.␊ - --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ + --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ + --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern.␊ + --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ ` diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 2aac1b621f2327c38826455e7590738f059d9f54..7c67e73f4da14de609b261d2ef499ea727c0213a 100644 GIT binary patch literal 3231 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 RusI|4{15!a)wO9;004#*C<_1p delta 3157 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 vGDXY(jy~}avuS4r3T&09)W;k { )}`, }); }); + +test('withDefaults - empty unsafeAllow', t => { + const parsedArgs = minimist(['validate', 'build-info.json', '--unsafeAllow']); + t.throws(() => withDefaults(parsedArgs), { + message: `Invalid option: --unsafeAllow cannot be empty`, + }); +}); + +test('withDefaults - unsafeAllow multiple times', t => { + const parsedArgs = minimist([ + 'validate', + 'build-info.json', + '--unsafeAllow', + 'selfdestruct', + '--unsafeAllow', + 'delegatecall', + '--unsafeAllow', + 'constructor', + ]); + const opts = withDefaults(parsedArgs); + t.deepEqual(opts.unsafeAllow, ['selfdestruct', 'delegatecall', 'constructor']); +}); diff --git a/packages/core/src/cli/validate.ts b/packages/core/src/cli/validate.ts index c15f70a41..3a5ceb0b0 100644 --- a/packages/core/src/cli/validate.ts +++ b/packages/core/src/cli/validate.ts @@ -16,9 +16,9 @@ Options: --contract The name or fully qualified name of the contract to validate. If not specified, all upgradeable contracts in the build info directory will be validated. --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated. --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation. - --referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. - --exclude "" Exclude validations for contracts in source file paths that match the given glob pattern. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. - --unsafeAllow "" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( + --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. + --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern. + --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( ', ', )} --unsafeAllowRenames Configure storage layout check to allow variable renaming. @@ -113,7 +113,7 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri function getAndValidateString(parsedArgs: minimist.ParsedArgs, option: string): string | undefined { const value = parsedArgs[option]; if (value !== undefined) { - assertNonEmptyOption(value, option); + assertNonEmptyString(value, option); } return value; } @@ -124,15 +124,15 @@ function getAndValidateStringArray(parsedArgs: minimist.ParsedArgs, option: stri if (Array.isArray(value)) { return value; } else { - assertNonEmptyOption(value, option); - return value.split(/,+/); + assertNonEmptyString(value, option); + return value.split(/[\s,]+/); } } return value; } -function assertNonEmptyOption(value: string, option: string) { - if (value.trim().length === 0) { +function assertNonEmptyString(value: string, option: string) { + if (typeof value !== 'string' || value.trim().length === 0) { throw new Error(`Invalid option: --${option} cannot be empty`); } } @@ -161,18 +161,13 @@ function validateOptions(parsedArgs: minimist.ParsedArgs) { } } -function getUnsafeAllowKinds(unsafeAllow: string | undefined): ValidationError['kind'][] { +function getUnsafeAllowKinds(parseArgs: minimist.ParsedArgs): ValidationError['kind'][] { type errorKindsType = (typeof errorKinds)[number]; - if (unsafeAllow === undefined) { - return []; - } - - const unsafeAllowTokens: string[] = unsafeAllow.split(/[\s,]+/); + const unsafeAllowTokens: string[] = getAndValidateStringArray(parseArgs, 'unsafeAllow') ?? []; if (unsafeAllowTokens.some(token => !errorKinds.includes(token as errorKindsType))) { - // This includes empty strings throw new Error( - `Invalid option: --unsafeAllow "${unsafeAllow}". Supported values for the --unsafeAllow option are: ${errorKinds.join( + `Invalid option: --unsafeAllow "${parseArgs['unsafeAllow']}". Supported values for the --unsafeAllow option are: ${errorKinds.join( ', ', )}`, ); @@ -188,7 +183,7 @@ export function withDefaults(parsedArgs: minimist.ParsedArgs): Required Date: Thu, 22 Aug 2024 17:01:41 -0400 Subject: [PATCH 16/27] Add testcase for multiple exclude --- packages/core/src/cli/cli.test.ts | 9 +++++++++ packages/core/src/cli/cli.test.ts.md | 10 ++++++++++ packages/core/src/cli/cli.test.ts.snap | Bin 3231 -> 3242 bytes 3 files changed, 19 insertions(+) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 309c9a650..e22d85b03 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -617,6 +617,15 @@ test('validate - excludes by pattern - all match', async t => { t.snapshot(output); }); +test('validate - exclude passed multiple times', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const output = await execAsync(`${CLI} validate ${temp} --exclude "**/excludes/Abstract*.sol" --exclude "**/UsesAbstractUUPS.sol"`); + t.snapshot(output); +}); + test('validate - excludes specified contract', async t => { const temp = await getTempDir(t); const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/Validate.sol:BecomesBadLayout`); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 0b676f807..2edec8dc2 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -497,6 +497,16 @@ Generated by [AVA](https://avajs.dev). ## validate - excludes by pattern - all match +> Snapshot 1 + + { + stderr: '', + stdout: `No upgradeable contracts detected.␊ + `, + } + +## validate - exclude passed multiple times + > Snapshot 1 { diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 7c67e73f4da14de609b261d2ef499ea727c0213a..74b4b6193b8b547161558a51bbf8591412e7eeec 100644 GIT binary patch literal 3242 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 literal 3231 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 RusI|4{15!a)wO9;004#*C<_1p From 1c8a9c61d39b97590d90391977eb941e44e14640 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 17:38:03 -0400 Subject: [PATCH 17/27] Exclude UpgradeableBeacon by default --- ...rsions.sol => ImportVersionsAndBeacon.sol} | 3 +- .../excludes/contracts/proxy/beacon/Other.sol | 12 ++++++++ .../proxy/beacon/UpgradeableBeacon.sol | 15 ++++++++++ packages/core/src/cli/cli.test.ts | 19 +++++++++++-- packages/core/src/cli/cli.test.ts.md | 12 +++++++- packages/core/src/cli/cli.test.ts.snap | Bin 3242 -> 3278 bytes .../core/src/cli/validate/contract-report.ts | 26 +++++++++--------- .../core/src/cli/validate/default-exclude.ts | 3 ++ 8 files changed, 72 insertions(+), 18 deletions(-) rename packages/core/contracts/test/cli/excludes/{ImportVersions.sol => ImportVersionsAndBeacon.sol} (71%) create mode 100644 packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol create mode 100644 packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol create mode 100644 packages/core/src/cli/validate/default-exclude.ts diff --git a/packages/core/contracts/test/cli/excludes/ImportVersions.sol b/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol similarity index 71% rename from packages/core/contracts/test/cli/excludes/ImportVersions.sol rename to packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol index c2fee413f..2f06bc48b 100644 --- a/packages/core/contracts/test/cli/excludes/ImportVersions.sol +++ b/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.9; import "./V1.sol"; import "./V2Bad1.sol"; import "./V2Bad2.sol"; +import "./contracts/proxy/beacon/UpgradeableBeacon.sol"; abstract contract Dummy { -} \ No newline at end of file +} diff --git a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol new file mode 100644 index 000000000..c476c4e08 --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// This contract is for testing only, it is not safe for use in production. + +contract Other { + address immutable foo; + + constructor(address _foo) { + foo = _foo; + } +} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol new file mode 100644 index 000000000..3fb6ea11c --- /dev/null +++ b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// This contract is for testing only, it is not safe for use in production. + +import {Other} from "./Other.sol"; + +contract UpgradeableBeacon is Other { + constructor(address foo) Other(foo) { + } + + function upgradeTo(address newImplementation) public pure { + revert("Upgrade disabled"); + } +} \ No newline at end of file diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index e22d85b03..fe421da85 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -622,7 +622,9 @@ test('validate - exclude passed multiple times', async t => { const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync(`${CLI} validate ${temp} --exclude "**/excludes/Abstract*.sol" --exclude "**/UsesAbstractUUPS.sol"`); + const output = await execAsync( + `${CLI} validate ${temp} --exclude "**/excludes/Abstract*.sol" --exclude "**/UsesAbstractUUPS.sol"`, + ); t.snapshot(output); }); @@ -640,9 +642,20 @@ test('validate - excludes specified contract', async t => { ); }); -test('validate - excludes one contract from layout comparisions', async t => { +test('validate - excludes UpgradeableBeacon and its parents by default', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo( + `contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon`, + ); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const output = await execAsync(`${CLI} validate ${temp}`); + t.snapshot(output); +}); + +test('validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default', async t => { const temp = await getTempDir(t); - const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersions.sol:Dummy`); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersionsAndBeacon.sol:Dummy`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp} --exclude "**/V2Bad1.sol"`)); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 2edec8dc2..6fbd08bfe 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -515,7 +515,17 @@ Generated by [AVA](https://avajs.dev). `, } -## validate - excludes one contract from layout comparisions +## validate - excludes UpgradeableBeacon and its parents by default + +> Snapshot 1 + + { + stderr: '', + stdout: `No upgradeable contracts detected.␊ + `, + } + +## validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default > Snapshot 1 diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 74b4b6193b8b547161558a51bbf8591412e7eeec..8445c188085ed9aa53c5b17ce3a8662dc9375a1b 100644 GIT binary patch literal 3278 zcmV;<3^DUTRzVVT?0pa1xp3jad)+gm9%*FF z*pBV6a#dn!X1e>m-}}9f{uqC1)-9*8FW!9TkId)3#f%oSTrO?~Q$U<>PDHf;L%|*zO^D?6}N6Vy??9ZkGeM=~07;Qp52WIiMDY4j6ec zyRf~wwzRvtzOu2qw7NO>5-x2#+gjaNug$$2A75fVYxshM&1v0Yq~X}UNAarZIc-8o zJ>Zr>xNSPb;2u2hcpXA*BOXSO*DdC^m`C70xCIh~9TGuJHaR{%?=^!qvwcw=C!|*< zLN;8VJ2th5OZ^t{9qcE4*w-!IXh{(%w*`4x+gK+iw@?HQO=}KF#QhFD(RSgo2kqU! zm(n_c4<9GV5;JLFfqF2`1oeDwqOxTEdbD_ZH7{tfn{~bs{pKJa%P0rO$l<`7{G|kDHX7tNE~QV zB-FA7kc8XESc^lmdY6yJq?FiWCg@=|7@6H%URmB;USC|^)r4Q9HgRl_8JYri2GUE7 zqG{_$3{U007>Mr9UNH>rSYh&(W~b zjY_4!M$fJ7bGN2|SZuMzzEoXPJCsEb#v}Jnm^U00UnzilOK|aS-7Nf;gob4aMHD63A&Sg^gFjx|SlE3wzqPfzxsD7>d=L4z96lX7wv9`wkMf;6! z&NXI%kpL!8%iu!hF6mhwX={}d%ELU*@j%N(l(-bBVi1c1H>ECm!_ezZ2ZaJes^IPL zcM_SFLN>8j6UITD(G->m9xLw_Nt;WvmE53i@kZp&zJs0?3Sb6y1A8rnQL7jD zO@^K-Al*2&$(sRS&>P<{MId>oG*qN6a0yz%=(;U?GYeP>t_al!5^PZXge=7^tneap zZDI7pv_=eSH<^dAIbs;2wjX96nHVWPW>K&wBrOO&ljC9i-Lye!uPH_)_^1RQmEfZi zd{lyuO7Kw$J}SXSCHSZWAC=(eQi8vVE9O$zaepy>{duAoe|o*<8z5GdkS{*@J?Z*M z846;*+^~3gCn~7G%c?cddVDvS&iI^`chSOo-lPgtGOReRmm!rL70STH2n!v zA;ch+49Q*)^?VEF0FW5O?LAEM-RtwVu?XNqw~O@-3x8PFQMh0hIiwZBS zd<kv0v(B(3$;Hy``?=ZWdqKgP7_SO&@@{Up1^&)(n)#C|YJ zgTW}uSyWraKjkb5-7hV4ut8-f{y#;9ga7^J!#{Gq%TUCVLc9H#AdL z?MK!)l{FSMYxJEwC_%E-O`;d2xEO>Mgsk3Qy8lMEN#W@HR}pI4i;K&(TD1LhxO_@A z)uvXzqW?;e@AI5nA!#8cGsQm%D{On z30$6edB1(8^4TYy)4xj?=htHyw?AW}Z0w(zO?ut@DuYgZaG?jGZ~-trs}c(O4`&e5PMq+YY`30HgRx}2x5GXCyoh@ zC*QE7BvL27lON*y`5~T)LP$R~rYts~`0RCx4+yDRo literal 3242 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 diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 81a4ee5c8..da8641556 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -20,6 +20,7 @@ import { indent } from '../../utils/indent'; import { BuildInfoDictionary, SpecifiedContracts } from './validate-upgrade-safety'; import { minimatch } from 'minimatch'; import { ValidateCommandError } from './error'; +import { defaultExclude } from './default-exclude'; /** * Report for an upgradeable contract. @@ -125,7 +126,9 @@ function getUpgradeableContractReport( opts: ValidationOptions, exclude?: string[], ): UpgradeableContractReport | undefined { - if (exclude !== undefined && exclude.some(glob => minimatch(getPath(contract.fullyQualifiedName), glob))) { + const excludeWithDefaults = exclude !== undefined ? exclude.concat(defaultExclude) : defaultExclude; + + if (excludeWithDefaults.some(glob => minimatch(getPath(contract.fullyQualifiedName), glob))) { debug('Excluding contract: ' + contract.fullyQualifiedName); return undefined; } @@ -144,7 +147,7 @@ function getUpgradeableContractReport( } debug('Checking: ' + contract.fullyQualifiedName); - const standaloneReport = getStandaloneReport(contract.validationData, version, opts, exclude); + const standaloneReport = getStandaloneReport(contract.validationData, version, opts, excludeWithDefaults); let reference: string | undefined; let storageLayoutReport: LayoutCompatibilityReport | undefined; @@ -170,19 +173,16 @@ function getStandaloneReport( data: ValidationData, version: Version, opts: ValidationOptions, - exclude?: string[], + excludeWithDefaults: string[], ): UpgradeableContractErrorReport { const allErrors = getErrors(data, version, withValidationDefaults(opts)); - const reportErrors = - exclude !== undefined - ? allErrors.filter(e => { - const excluded = exclude.some(glob => minimatch(getPath(e.src), glob)); - if (excluded) { - debug('Excluding error: ' + e.src); - } - return !excluded; - }) - : allErrors; + const reportErrors = allErrors.filter(e => { + const excluded = excludeWithDefaults.some(glob => minimatch(getPath(e.src), glob)); + if (excluded) { + debug('Excluding error: ' + e.src); + } + return !excluded; + }); return new UpgradeableContractErrorReport(reportErrors); } diff --git a/packages/core/src/cli/validate/default-exclude.ts b/packages/core/src/cli/validate/default-exclude.ts new file mode 100644 index 000000000..16de95c27 --- /dev/null +++ b/packages/core/src/cli/validate/default-exclude.ts @@ -0,0 +1,3 @@ +const UPGRADEABLE_BEACON = '**/contracts/proxy/beacon/UpgradeableBeacon.sol' as const; + +export const defaultExclude = [UPGRADEABLE_BEACON]; From 440dbf76bbbbe9bedfd555af7109f2f2c6722619 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 17:56:17 -0400 Subject: [PATCH 18/27] Simplify tests --- .../cli/excludes/ImportVersionsAndBeacon.sol | 2 +- .../excludes/contracts/proxy/beacon/Other.sol | 12 ------------ .../proxy/beacon/UpgradeableBeacon.sol | 15 --------------- packages/core/src/cli/cli.test.ts | 9 ++++----- packages/core/src/cli/cli.test.ts.md | 18 +++++++++++++----- packages/core/src/cli/cli.test.ts.snap | Bin 3278 -> 3305 bytes 6 files changed, 18 insertions(+), 38 deletions(-) delete mode 100644 packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol delete mode 100644 packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol diff --git a/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol b/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol index 2f06bc48b..9b0890ae8 100644 --- a/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol +++ b/packages/core/contracts/test/cli/excludes/ImportVersionsAndBeacon.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.9; import "./V1.sol"; import "./V2Bad1.sol"; import "./V2Bad2.sol"; -import "./contracts/proxy/beacon/UpgradeableBeacon.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; abstract contract Dummy { } diff --git a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol deleted file mode 100644 index c476c4e08..000000000 --- a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/Other.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -// This contract is for testing only, it is not safe for use in production. - -contract Other { - address immutable foo; - - constructor(address _foo) { - foo = _foo; - } -} \ No newline at end of file diff --git a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol b/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol deleted file mode 100644 index 3fb6ea11c..000000000 --- a/packages/core/contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -// This contract is for testing only, it is not safe for use in production. - -import {Other} from "./Other.sol"; - -contract UpgradeableBeacon is Other { - constructor(address foo) Other(foo) { - } - - function upgradeTo(address newImplementation) public pure { - revert("Upgrade disabled"); - } -} \ No newline at end of file diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index fe421da85..92f5b155c 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -644,13 +644,12 @@ test('validate - excludes specified contract', async t => { test('validate - excludes UpgradeableBeacon and its parents by default', async t => { const temp = await getTempDir(t); - const buildInfo = await artifacts.getBuildInfo( - `contracts/test/cli/excludes/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon`, - ); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersionsAndBeacon.sol:Dummy`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); - const output = await execAsync(`${CLI} validate ${temp}`); - t.snapshot(output); + const error = await t.throwsAsync(execAsync(`${CLI} validate ${temp}`)); + const expectation: string[] = [`Stdout: ${(error as any).stdout}`, `Stderr: ${(error as any).stderr}`]; + t.snapshot(expectation.join('\n')); }); test('validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default', async t => { diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 6fbd08bfe..bdf7ce2b5 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -519,11 +519,19 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 - { - stderr: '', - stdout: `No upgradeable contracts detected.␊ - `, - } + `Stdout: ✘ contracts/test/cli/excludes/V2Bad1.sol:V2Bad1 (upgrades from contracts/test/cli/excludes/V1.sol:V1)␊ + ␊ + V1: Deleted \`x\`␊ + > Keep the variable even if unused␊ + ␊ + ✘ contracts/test/cli/excludes/V2Bad2.sol:V2Bad2 (upgrades from contracts/test/cli/excludes/V1.sol:V1)␊ + ␊ + V1: Deleted \`x\`␊ + > Keep the variable even if unused␊ + ␊ + FAILED (2 upgradeable contracts detected, 0 passed, 2 failed)␊ + ␊ + Stderr: ` ## validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 8445c188085ed9aa53c5b17ce3a8662dc9375a1b..3de3b26ee6c4689580c9e69993078bd2c54b2dbe 100644 GIT binary patch literal 3305 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 literal 3278 zcmV;<3^DUTRzVVT?0pa1xp3jad)+gm9%*FF z*pBV6a#dn!X1e>m-}}9f{uqC1)-9*8FW!9TkId)3#f%oSTrO?~Q$U<>PDHf;L%|*zO^D?6}N6Vy??9ZkGeM=~07;Qp52WIiMDY4j6ec zyRf~wwzRvtzOu2qw7NO>5-x2#+gjaNug$$2A75fVYxshM&1v0Yq~X}UNAarZIc-8o zJ>Zr>xNSPb;2u2hcpXA*BOXSO*DdC^m`C70xCIh~9TGuJHaR{%?=^!qvwcw=C!|*< zLN;8VJ2th5OZ^t{9qcE4*w-!IXh{(%w*`4x+gK+iw@?HQO=}KF#QhFD(RSgo2kqU! zm(n_c4<9GV5;JLFfqF2`1oeDwqOxTEdbD_ZH7{tfn{~bs{pKJa%P0rO$l<`7{G|kDHX7tNE~QV zB-FA7kc8XESc^lmdY6yJq?FiWCg@=|7@6H%URmB;USC|^)r4Q9HgRl_8JYri2GUE7 zqG{_$3{U007>Mr9UNH>rSYh&(W~b zjY_4!M$fJ7bGN2|SZuMzzEoXPJCsEb#v}Jnm^U00UnzilOK|aS-7Nf;gob4aMHD63A&Sg^gFjx|SlE3wzqPfzxsD7>d=L4z96lX7wv9`wkMf;6! z&NXI%kpL!8%iu!hF6mhwX={}d%ELU*@j%N(l(-bBVi1c1H>ECm!_ezZ2ZaJes^IPL zcM_SFLN>8j6UITD(G->m9xLw_Nt;WvmE53i@kZp&zJs0?3Sb6y1A8rnQL7jD zO@^K-Al*2&$(sRS&>P<{MId>oG*qN6a0yz%=(;U?GYeP>t_al!5^PZXge=7^tneap zZDI7pv_=eSH<^dAIbs;2wjX96nHVWPW>K&wBrOO&ljC9i-Lye!uPH_)_^1RQmEfZi zd{lyuO7Kw$J}SXSCHSZWAC=(eQi8vVE9O$zaepy>{duAoe|o*<8z5GdkS{*@J?Z*M z846;*+^~3gCn~7G%c?cddVDvS&iI^`chSOo-lPgtGOReRmm!rL70STH2n!v zA;ch+49Q*)^?VEF0FW5O?LAEM-RtwVu?XNqw~O@-3x8PFQMh0hIiwZBS zd<kv0v(B(3$;Hy``?=ZWdqKgP7_SO&@@{Up1^&)(n)#C|YJ zgTW}uSyWraKjkb5-7hV4ut8-f{y#;9ga7^J!#{Gq%TUCVLc9H#AdL z?MK!)l{FSMYxJEwC_%E-O`;d2xEO>Mgsk3Qy8lMEN#W@HR}pI4i;K&(TD1LhxO_@A z)uvXzqW?;e@AI5nA!#8cGsQm%D{On z30$6edB1(8^4TYy)4xj?=htHyw?AW}Z0w(zO?ut@DuYgZaG?jGZ~-trs}c(O4`&e5PMq+YY`30HgRx}2x5GXCyoh@ zC*QE7BvL27lON*y`5~T)LP$R~rYts~`0RCx4+yDRo From 9f0309bf1b330129ded23f31848aaa400639e779 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Thu, 22 Aug 2024 18:00:26 -0400 Subject: [PATCH 19/27] Rename test --- packages/core/src/cli/cli.test.ts | 2 +- packages/core/src/cli/cli.test.ts.md | 2 +- packages/core/src/cli/cli.test.ts.snap | Bin 3305 -> 3305 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 92f5b155c..9a666153e 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -652,7 +652,7 @@ test('validate - excludes UpgradeableBeacon and its parents by default', async t t.snapshot(expectation.join('\n')); }); -test('validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default', async t => { +test('validate - excludes UpgradeableBeacon and its parents by default, and excludes one contract from layout comparisions', async t => { const temp = await getTempDir(t); const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/ImportVersionsAndBeacon.sol:Dummy`); await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index bdf7ce2b5..6b59ffce8 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -533,7 +533,7 @@ Generated by [AVA](https://avajs.dev). ␊ Stderr: ` -## validate - excludes one contract from layout comparisions, and excludes UpgradeableBeacon by default +## validate - excludes UpgradeableBeacon and its parents by default, and excludes one contract from layout comparisions > Snapshot 1 diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 3de3b26ee6c4689580c9e69993078bd2c54b2dbe..ea678889688028e3e7d80e2390b60794d5b20f8c 100644 GIT binary patch delta 108 zcmV-y0F(de8R;1^K~_N^Q*L2!b7*gLAa*kf0{|ICIl>k#PMpq`s^H|sUJU*2`0-4& zdhXEOj`f|X368NchYT?6pOh43c`t5?hfm|sBB2@hiyycln?a=M6p{Wr{&dhqw#~^R O?f(Gr@orz0RsaBtj5MYI delta 108 zcmV-y0F(de8R;1^K~_N^Q*L2!b7*gLAa*kf0|5V505TaT@=DfTp~XDd7&D8SS96AT z;qUi1J(6Xcg}SjahYT=mWRU_-kjC*r>NoIbJ8)OEESYiyk&YzJbc#6t9e*0=BHQ9* Ok@bIlt2pL`RsaB`VK3kS From c2692a0999a6758d7cf77a0c9871b89e4e01b10c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 12:10:45 -0400 Subject: [PATCH 20/27] Make variables clearer --- packages/core/src/cli/validate/contract-report.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index da8641556..ea8a2db85 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -176,14 +176,16 @@ function getStandaloneReport( excludeWithDefaults: string[], ): UpgradeableContractErrorReport { const allErrors = getErrors(data, version, withValidationDefaults(opts)); - const reportErrors = allErrors.filter(e => { - const excluded = excludeWithDefaults.some(glob => minimatch(getPath(e.src), glob)); - if (excluded) { + + const includeErrors = allErrors.filter(e => { + const shouldExclude = excludeWithDefaults.some(glob => minimatch(getPath(e.src), glob)); + if (shouldExclude) { debug('Excluding error: ' + e.src); } - return !excluded; + return !shouldExclude; }); - return new UpgradeableContractErrorReport(reportErrors); + + return new UpgradeableContractErrorReport(includeErrors); } function getPath(srcOrFullyQualifiedName: string): string { From 8c84a64ba7ebe9ecf8bbe3995e05cb643aa91483 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 12:35:00 -0400 Subject: [PATCH 21/27] Do not treat comma as delimiter for exclude --- docs/modules/ROOT/pages/api-core.adoc | 2 +- packages/core/src/cli/cli.test.ts | 9 +++++++++ packages/core/src/cli/cli.test.ts.md | 14 ++++++++++++-- packages/core/src/cli/cli.test.ts.snap | Bin 3305 -> 3329 bytes packages/core/src/cli/validate.ts | 22 +++++++++++++++------- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index 66fb2911c..dcdb9dbcf 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -120,7 +120,7 @@ If any errors are found, the command will exit with a non-zero exit code and pri * `--reference ` - Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. * `--requireReference` - Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. * `--referenceBuildInfoDirs "[,...]"` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. -* `--exclude "[,...]"` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern. +* `--exclude "" [--exclude ...]` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. * `--unsafeAllow "[,...]"` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. diff --git a/packages/core/src/cli/cli.test.ts b/packages/core/src/cli/cli.test.ts index 9a666153e..2af1a71c0 100644 --- a/packages/core/src/cli/cli.test.ts +++ b/packages/core/src/cli/cli.test.ts @@ -617,6 +617,15 @@ test('validate - excludes by pattern - all match', async t => { t.snapshot(output); }); +test('validate - excludes by pattern - all match using commas within glob', async t => { + const temp = await getTempDir(t); + const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); + await fs.writeFile(path.join(temp, 'validate.json'), JSON.stringify(buildInfo)); + + const output = await execAsync(`${CLI} validate ${temp} --exclude "**/excludes/{Abstract*,UsesAbstractUUPS}.sol"`); + t.snapshot(output); +}); + test('validate - exclude passed multiple times', async t => { const temp = await getTempDir(t); const buildInfo = await artifacts.getBuildInfo(`contracts/test/cli/excludes/UsesAbstractUUPS.sol:UsesAbstractUUPS`); diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 6b59ffce8..d3ca043dd 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -20,7 +20,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ @@ -42,7 +42,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ @@ -497,6 +497,16 @@ Generated by [AVA](https://avajs.dev). ## validate - excludes by pattern - all match +> Snapshot 1 + + { + stderr: '', + stdout: `No upgradeable contracts detected.␊ + `, + } + +## validate - excludes by pattern - all match using commas within glob + > Snapshot 1 { diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index ea678889688028e3e7d80e2390b60794d5b20f8c..3922ee056bebbf04a891cc1b6d469ce196cdce03 100644 GIT binary patch delta 3247 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 Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated. --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation. --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. - --exclude "[,...]" Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, separate them with commas or call the option multiple times, once for each pattern. + --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( ', ', )} @@ -96,8 +96,8 @@ export function getFunctionArgs(parsedArgs: minimist.ParsedArgs, extraArgs: stri const contract = getAndValidateString(parsedArgs, 'contract'); const reference = getAndValidateString(parsedArgs, 'reference'); const opts = withDefaults(parsedArgs); - const referenceBuildInfoDirs = getAndValidateStringArray(parsedArgs, 'referenceBuildInfoDirs'); - const exclude = getAndValidateStringArray(parsedArgs, 'exclude'); + const referenceBuildInfoDirs = getAndValidateStringArray(parsedArgs, 'referenceBuildInfoDirs', true); + const exclude = getAndValidateStringArray(parsedArgs, 'exclude', false); if (contract === undefined) { if (reference !== undefined) { @@ -118,20 +118,28 @@ function getAndValidateString(parsedArgs: minimist.ParsedArgs, option: string): return value; } -function getAndValidateStringArray(parsedArgs: minimist.ParsedArgs, option: string): string[] | undefined { +function getAndValidateStringArray( + parsedArgs: minimist.ParsedArgs, + option: string, + useCommaDelimiter: boolean, +): string[] | undefined { const value = parsedArgs[option]; if (value !== undefined) { if (Array.isArray(value)) { return value; } else { assertNonEmptyString(value, option); - return value.split(/[\s,]+/); + if (useCommaDelimiter) { + return value.split(/[\s,]+/); + } else { + return [value]; + } } } return value; } -function assertNonEmptyString(value: string, option: string) { +function assertNonEmptyString(value: unknown, option: string) { if (typeof value !== 'string' || value.trim().length === 0) { throw new Error(`Invalid option: --${option} cannot be empty`); } @@ -164,7 +172,7 @@ function validateOptions(parsedArgs: minimist.ParsedArgs) { function getUnsafeAllowKinds(parseArgs: minimist.ParsedArgs): ValidationError['kind'][] { type errorKindsType = (typeof errorKinds)[number]; - const unsafeAllowTokens: string[] = getAndValidateStringArray(parseArgs, 'unsafeAllow') ?? []; + const unsafeAllowTokens: string[] = getAndValidateStringArray(parseArgs, 'unsafeAllow', true) ?? []; if (unsafeAllowTokens.some(token => !errorKinds.includes(token as errorKindsType))) { throw new Error( `Invalid option: --unsafeAllow "${parseArgs['unsafeAllow']}". Supported values for the --unsafeAllow option are: ${errorKinds.join( From ff70daa40f8f679ac49ae799d64acc6aeb197ba5 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 12:37:06 -0400 Subject: [PATCH 22/27] Add quotes --- docs/modules/ROOT/pages/api-core.adoc | 2 +- packages/core/src/cli/cli.test.ts.md | 4 ++-- packages/core/src/cli/cli.test.ts.snap | Bin 3329 -> 3326 bytes packages/core/src/cli/validate.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index dcdb9dbcf..4e5dff077 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -120,7 +120,7 @@ If any errors are found, the command will exit with a non-zero exit code and pri * `--reference ` - Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. * `--requireReference` - Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. * `--referenceBuildInfoDirs "[,...]"` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. -* `--exclude "" [--exclude ...]` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. +* `--exclude "" [--exclude ""...]` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. * `--unsafeAllow "[,...]"` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index d3ca043dd..357a3d4ed 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -20,7 +20,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ @@ -42,7 +42,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 3922ee056bebbf04a891cc1b6d469ce196cdce03..202f9147ac66a15edb48214bb0fa9438f475deb0 100644 GIT binary patch delta 3218 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 Zib($*e< Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated. --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation. --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. - --exclude "" [--exclude ...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( ', ', )} From 881576a7e2c7ad5701f0db41c2d75f7d5c797b36 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 13:18:55 -0400 Subject: [PATCH 23/27] Update doc --- docs/modules/ROOT/pages/api-core.adoc | 2 +- packages/core/src/cli/cli.test.ts.md | 4 ++-- packages/core/src/cli/cli.test.ts.snap | Bin 3326 -> 3331 bytes packages/core/src/cli/validate.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index 4e5dff077..d89a9f79f 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -120,7 +120,7 @@ If any errors are found, the command will exit with a non-zero exit code and pri * `--reference ` - Can only be used when the `--contract` option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the `@custom:oz-upgrades-from` annotation if it is defined in the contract that is being validated. * `--requireReference` - Can only be used when the `--contract` option is also provided. Not compatible with `--unsafeSkipStorageCheck`. If specified, requires either the `--reference` option to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. * `--referenceBuildInfoDirs "[,...]"` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `--reference` option or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. -* `--exclude "" [--exclude ""...]` - Exclude validations for contracts in source file paths that match the given glob pattern. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. +* `--exclude "" [--exclude ""...]` - Exclude validations for contracts in source file paths that match any of the given glob patterns. For example, `--exclude "contracts/mocks/\**/*.sol"`. Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. * `--unsafeAllow "[,...]"` - Selectively disable one or more validation errors. Comma-separated list with one or more of the following: `state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage` * `--unsafeAllowRenames` - Configure storage layout check to allow variable renaming. * `--unsafeSkipStorageCheck` - Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort. diff --git a/packages/core/src/cli/cli.test.ts.md b/packages/core/src/cli/cli.test.ts.md index 357a3d4ed..bcc365e62 100644 --- a/packages/core/src/cli/cli.test.ts.md +++ b/packages/core/src/cli/cli.test.ts.md @@ -20,7 +20,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match any of the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ @@ -42,7 +42,7 @@ Generated by [AVA](https://avajs.dev). --reference Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated.␊ --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation.␊ --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory.␊ - --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match any of the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern.␊ --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: state-variable-assignment, state-variable-immutable, external-library-linking, struct-definition, enum-definition, constructor, delegatecall, selfdestruct, missing-public-upgradeto, internal-function-storage␊ --unsafeAllowRenames Configure storage layout check to allow variable renaming.␊ --unsafeSkipStorageCheck Skips checking for storage layout compatibility errors. This is a dangerous option meant to be used as a last resort.␊ diff --git a/packages/core/src/cli/cli.test.ts.snap b/packages/core/src/cli/cli.test.ts.snap index 202f9147ac66a15edb48214bb0fa9438f475deb0..b8b9cfa675deda863e2e3e734c08a8311a0ad727 100644 GIT binary patch delta 3264 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 delta 3275 zcmV;+3^enD8vYr7K~_N^Q*L2!b7*gLAa*kf0|4oz%alOpDkRE!-C%V}%~?BOX`T(v z3|@Xq(F==EcO)N+2mk;800003?OaW497z@SB-&l%C?X47SP4-I0w-a{lbJYwgR$cH zhxHQd;IR!+6xlV?)iXtUx;tInj>jhu7q}u0IV^|ef{@^Ujs!O@Xpda>z6b7HxNzaU zs{W~->G5>iiS4jsDe+8qSJivp``%Cev_COhmeYPNUS0h?^SN&^qsuIp3!A#4>-gdq zpBM)9>61$v7pLBv!k^MRQ}17RaA{l64r>tGJs=Mpm)VERb(zKOYT$M}YA{i0J02tZ z)Z)+qBTwfUA8xNbTHak-U)|VUUfW!F2A4J-Z>?>tH;WE_+j1f+Smjts?iR?w@mp0b7HW!z+ z0MRV~(55|xQk#Kg^~s9>tYva$gx5_8a@-ieh|DP!u$@R8Xi_HBvPO`E+ecW7L$g-G zM`Kn>>@gGcu-lBxZ?3GaY_6;?t?X*TFHxH~HpmQ30e?FK>7_=|v~?r~gafjca1iT# zZomk+RZpbQL4fh3Rl!sq_!_Y&SjU%qq8=B3dKNs=!r18pW#oo)SczRyxseS`s1n%( z1Eb&uGr7%-2*N}RZH;!Fv$^z?-r3CxmO=3AOV%8dkbdr4rcaxy|R?Z7Lv^ zx~%UHTp0}si8-T;FhBJI|Ib<5ln)^b@pEAke^m z7p$V7Dl1lECypI46?)UfP>nzilOK?odAPL>tbbl;%mBzHM*kGJM|uLcN0|&-0f z?0*17X28K8Jlc4;`*?9{Yh`nN;VOAL`W}*zkd^Rm=;)GEI7%wU3P>n8IwZA_vocEb zs1Kr`%pJZDjOtiU3-9~PLzbCpj>VR)mi z3ycBShXbV;33fDexgeNfI|Zc*K8u#+ynh79b`~G4EiYopvb(amxgni;=vwI3O=f{j z011%X;6kP<=|~>wX@wEW!#vONK#?UhexuKK!1g)p1^F8|^6>Df?xOT|A0G$feUlsEAo#N^>mSG`geU65XW=tyXwP+h-xZB&_0Y9uwYg4J znyzy5W-YJ!KMG?|F@0}?zS}~^0Nv@3g)&Ye{aF!t>*2F`$G>;B!;jOBK;Y!qoM==Du5RkTtAyFbUIWwiBj8 zh(RhDlD#16`5Kh`kQl`EJxue-^+nrQ0&t?+2xe4-+L4WDS1Xe&rEs_rOxk(X@_>dYQL>ccB zQ2mfGS56D!+Lz%RjGHiz#R4?1_)TzMOQ~E`@^#17Ts}9CYqk4tBsb(>N0ieSTS7jk ziJ#lt5K9;1MF?>`*(=bfZT3~4%8(e`n z3`S)%7-cz&N-e?-&sR&IrU3eDsTe?$yn5!2HOz_cAH@l6&2}GJaWv03j(m{f$fdL7 zh@NZDf*zwVUw_SqISd^HF0Nzd1^>c3De(VO5d4$YILDe()oQiLr0Qgos!=@qb}pV} z`0(u%jlOfrG#ZZW@s(qj$?Cx)x>LcpP~|-e_Jw@zEjIuJZcU~4nkM#m&GwkjWsh>^ z{$<9h{lpq4vc{5TjiG}E6-c(aN%W!=7lY7(kkyAv_kUmMHYpvR{whLqdueH<*^IV- z4pvU6rrOjRR`g#f@_kltj&g2SF-Eav?r0bhI8XaN0<|Zlfm3b;eKvB5`Ys^1yY3__ z1E;YhaDL|H!}h5cvrjgsf0HuKFQ;;Df5t}Hc>daKGU&!%*YpFQ)k?TwHEO9C^sRMg z%o0YtSAX2o263Jbcl`5I$KFVI5(uPT$=6sfa;=srl(wu=i*-Z8s8k9Nk@qO zQA+gr6No;YHDeu2+2M&PdDyDg;++8Z?o$VqhDH2wO2nm15qFYvGfn6O4rb=IiXD)oLbP@WVshkQHs(MH+X*FQ~_>+)=O5SOZa0MlvtjJ?y zcXy(7VyyN4aj-PcxPns~D;Xj)3o9a54hUUs3_*j|BqGP93IBD%q%yIrjXM#$m(c48{qLPK|z_BrR+`5w?DI z!scHFN}^bObQJSXN{X_)7dOQ-w Can only be used when the --contract option is also provided. The name or fully qualified name of the reference contract to use for storage layout comparisons. If not specified, uses the @custom:oz-upgrades-from annotation if it is defined in the contract that is being validated. --requireReference Can only be used when the --contract option is also provided. Not compatible with --unsafeSkipStorageCheck. If specified, requires either the --reference option to be provided or the contract to have a @custom:oz-upgrades-from annotation. --referenceBuildInfoDirs "[,...]" Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix ':' before the contract name or fully qualified name in the --reference option or @custom:oz-upgrades-from annotation, where is the directory short name. Each directory short name must be unique, including compared to the main build info directory. If passing in multiple directories, separate them with commas or call the option multiple times, once for each directory. - --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. + --exclude "" [--exclude ""...] Exclude validations for contracts in source file paths that match any of the given glob patterns. For example, --exclude "contracts/mocks/**/*.sol". Does not apply to reference contracts. If passing in multiple patterns, call the option multiple times, once for each pattern. --unsafeAllow "[,...]" Selectively disable one or more validation errors. Comma-separated list with one or more of the following: ${errorKinds.join( ', ', )} From 85e8594e65c9e4539b4dfbb37b972e3add818f3b Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 13:26:07 -0400 Subject: [PATCH 24/27] Clarify doc comments --- packages/core/src/cli/validate/contract-report.ts | 2 +- packages/core/src/cli/validate/validate-upgrade-safety.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index ea8a2db85..8fbfd3d0d 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -69,7 +69,7 @@ export class UpgradeableContractReport implements Report { * @param buildInfoDictionary Dictionary of build info directories and the source contracts they contain. * @param opts The validation options. * @param specifiedContracts If provided, only the specified contract (upgrading from its reference contract) will be reported. - * @param exclude Exclude validations for contracts in source file paths that match the given glob patterns. + * @param exclude Exclude validations for contracts in source file paths that match any of the given glob patterns. * @returns The upgradeable contract reports. */ export function getContractReports( diff --git a/packages/core/src/cli/validate/validate-upgrade-safety.ts b/packages/core/src/cli/validate/validate-upgrade-safety.ts index 8cd7ed85e..f40828187 100644 --- a/packages/core/src/cli/validate/validate-upgrade-safety.ts +++ b/packages/core/src/cli/validate/validate-upgrade-safety.ts @@ -28,7 +28,7 @@ export type SpecifiedContracts = { * @param reference The name or fully qualified name of the reference contract to use for storage layout comparisons. Can only be used along with `contract`. If not specified, uses the `@custom:oz-upgrades-from` annotation in the contract that is being validated. * @param opts Validation options, or undefined to use the default validation options. * @param referenceBuildInfoDirs Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `reference` param or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. - * @param exclude Exclude validations for contracts in source file paths that match the given glob patterns. + * @param exclude Exclude validations for contracts in source file paths that match any of the given glob patterns. * @returns The project report. */ export async function validateUpgradeSafety( From ce3bdb4ceda929608240032fd1c0d08a2352bb6c Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 23 Aug 2024 13:36:40 -0400 Subject: [PATCH 25/27] Update high level API doc --- docs/modules/ROOT/pages/api-core.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/modules/ROOT/pages/api-core.adoc b/docs/modules/ROOT/pages/api-core.adoc index d89a9f79f..df1e6dc02 100644 --- a/docs/modules/ROOT/pages/api-core.adoc +++ b/docs/modules/ROOT/pages/api-core.adoc @@ -153,6 +153,8 @@ validateUpgradeSafety( contract?: string, reference?: string, opts: ValidateUpgradeSafetyOptions = {}, + referenceBuildInfoDirs?: string[], + exclude?: string[], ): Promise ---- @@ -170,6 +172,8 @@ Note that this function does not throw validation errors directly. Instead, you ** `unsafeAllowRenames` ** `unsafeSkipStorageCheck` ** `requireReference` - Can only be used when the `contract` argument is also provided. Not compatible with the `unsafeSkipStorageCheck` option. If specified, requires either the `reference` argument to be provided or the contract to have a `@custom:oz-upgrades-from` annotation. +* `referenceBuildInfoDirs` - Optional paths of additional build info directories from previous versions of the project to use for storage layout comparisons. When using this option, refer to one of these directories using prefix `:` before the contract name or fully qualified name in the `reference` param or `@custom:oz-upgrades-from` annotation, where `` is the directory short name. Each directory short name must be unique, including compared to the main build info directory. +* `exclude` - Exclude validations for contracts in source file paths that match any of the given glob patterns. *Returns:* From 40c76c0c31c049efd4c1923feba6ac6a146ab646 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 28 Aug 2024 16:00:20 -0400 Subject: [PATCH 26/27] Use string[] constant for defaultExclude --- packages/core/src/cli/validate/default-exclude.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/cli/validate/default-exclude.ts b/packages/core/src/cli/validate/default-exclude.ts index 16de95c27..041256839 100644 --- a/packages/core/src/cli/validate/default-exclude.ts +++ b/packages/core/src/cli/validate/default-exclude.ts @@ -1,3 +1,3 @@ const UPGRADEABLE_BEACON = '**/contracts/proxy/beacon/UpgradeableBeacon.sol' as const; -export const defaultExclude = [UPGRADEABLE_BEACON]; +export const defaultExclude: string[] = [UPGRADEABLE_BEACON] as const; From ecae53492008218f3e77ecb49aa84e2940897f27 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Wed, 28 Aug 2024 16:00:41 -0400 Subject: [PATCH 27/27] Update packages/core/src/cli/validate/contract-report.ts Co-authored-by: Hadrien Croubois --- packages/core/src/cli/validate/contract-report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/cli/validate/contract-report.ts b/packages/core/src/cli/validate/contract-report.ts index 8fbfd3d0d..18379b1a2 100644 --- a/packages/core/src/cli/validate/contract-report.ts +++ b/packages/core/src/cli/validate/contract-report.ts @@ -126,7 +126,7 @@ function getUpgradeableContractReport( opts: ValidationOptions, exclude?: string[], ): UpgradeableContractReport | undefined { - const excludeWithDefaults = exclude !== undefined ? exclude.concat(defaultExclude) : defaultExclude; + const excludeWithDefaults = defaultExclude.concat(exclude ?? []); if (excludeWithDefaults.some(glob => minimatch(getPath(contract.fullyQualifiedName), glob))) { debug('Excluding contract: ' + contract.fullyQualifiedName);