From 696e20f37d9fb61ba26ae4a7bac2cecd907d3835 Mon Sep 17 00:00:00 2001 From: Eric Lau Date: Fri, 24 Jan 2025 13:41:32 -0500 Subject: [PATCH] Fix `ASTDereferencerError` when validating initializers (#1118) --- packages/core/CHANGELOG.md | 4 ++++ .../contracts/test/ValidationsInitializer.sol | 15 +++++++++++++++ packages/core/package.json | 2 +- packages/core/src/validate-initializers.test.ts | 6 ++++++ packages/core/src/validate/run/initializer.ts | 6 +++--- 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 84fec474d..096a43870 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.42.1 (2025-01-24) + +- Fix `ASTDereferencerError` when validating initializers. + ## 1.42.0 (2025-01-23) - Update dependencies. ([#1096](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1096)) diff --git a/packages/core/contracts/test/ValidationsInitializer.sol b/packages/core/contracts/test/ValidationsInitializer.sol index f03ea3a59..10d8b0600 100644 --- a/packages/core/contracts/test/ValidationsInitializer.sol +++ b/packages/core/contracts/test/ValidationsInitializer.sol @@ -263,6 +263,21 @@ contract InitializationOrder_UnsafeAllowDuplicate_But_WrongOrder is A, B, C, Par } } +contract WithRequire_Ok is Parent__OnlyInitializingModifier { + uint y; + function initialize(bool foo) initializer public { + require(foo, "foo should be true"); + __Parent_init(); + } +} + +contract WithRequire_Bad is Parent__OnlyInitializingModifier { + uint y; + function initialize(bool foo) initializer public { + require(foo, "foo should be true"); + } +} + // ==== Initializer visibility ==== abstract contract Parent_Private is Initializable { diff --git a/packages/core/package.json b/packages/core/package.json index 33c98c387..b876948a3 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@openzeppelin/upgrades-core", - "version": "1.42.0", + "version": "1.42.1", "description": "", "repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core", "license": "MIT", diff --git a/packages/core/src/validate-initializers.test.ts b/packages/core/src/validate-initializers.test.ts index c0f8b4be5..0ff2eafbe 100644 --- a/packages/core/src/validate-initializers.test.ts +++ b/packages/core/src/validate-initializers.test.ts @@ -124,6 +124,12 @@ testAccepts('InitializationOrder_Duplicate_UnsafeAllow_Call', 'transparent'); testOverride('InitializationOrder_Duplicate_Bad', 'transparent', { unsafeAllow: ['duplicate-initializer-call'] }); testAccepts('InitializationOrder_UnsafeAllowDuplicate_But_WrongOrder', 'transparent'); // warn 'Expected initializers to be called for parent contracts in the following order: A, B, C' +testAccepts('WithRequire_Ok', 'transparent'); +testRejects('WithRequire_Bad', 'transparent', { + contains: ['Missing initializer calls for one or more parent contracts: `Parent__OnlyInitializingModifier`'], + count: 1, +}); + testAccepts('Child_Of_Private_Ok', 'transparent'); testAccepts('Child_Of_Public_Ok', 'transparent'); testRejects('Child_Of_Public_MissingCall_Bad', 'transparent', { diff --git a/packages/core/src/validate/run/initializer.ts b/packages/core/src/validate/run/initializer.ts index 213de2ef3..0a3a4788e 100644 --- a/packages/core/src/validate/run/initializer.ts +++ b/packages/core/src/validate/run/initializer.ts @@ -124,7 +124,7 @@ function getParentsNotInitializedByOtherParents( (fnCall.expression.nodeType === 'Identifier' || fnCall.expression.nodeType === 'MemberAccess') ) { const referencedFn = fnCall.expression.referencedDeclaration; - if (referencedFn) { + if (referencedFn && referencedFn > 0) { const earlierParents = remainingParents.slice(0, remainingParents.indexOf(parent)); const callsEarlierParentInitializer = earlierParents.find(base => parentNameToInitializersMap.get(base)!.some(init => init.id === referencedFn), @@ -177,7 +177,7 @@ function* getInitializerCallExceptions( ) { let recursiveFunctionIds: number[] = []; const referencedFn = fnCall.expression.referencedDeclaration; - if (referencedFn) { + if (referencedFn && referencedFn > 0) { recursiveFunctionIds = getRecursiveFunctionIds(referencedFn, deref); } @@ -284,7 +284,7 @@ function getRecursiveFunctionIds(referencedFn: number, deref: ASTDereferencer, v (fnCall.expression.nodeType === 'Identifier' || fnCall.expression.nodeType === 'MemberAccess') ) { const referencedId = fnCall.expression.referencedDeclaration; - if (referencedId) { + if (referencedId && referencedId > 0) { result.push(...getRecursiveFunctionIds(referencedId, deref, visited)); } }