diff --git a/packages/core/src/validate-initializers.test.ts b/packages/core/src/validate-initializers.test.ts index df85bda12..e27b3cdd9 100644 --- a/packages/core/src/validate-initializers.test.ts +++ b/packages/core/src/validate-initializers.test.ts @@ -33,8 +33,8 @@ test.before(async t => { } }); -function testValid(name: string, kind: ValidationOptions['kind'], valid: boolean, numExpectedErrors?: number) { - testOverride(name, kind, {}, valid, numExpectedErrors); +function testValid(name: string, kind: ValidationOptions['kind'], valid: boolean, expectedErrorContains?: string) { + testOverride(name, kind, {}, valid, expectedErrorContains); } function testOverride( @@ -42,9 +42,9 @@ function testOverride( kind: ValidationOptions['kind'], opts: ValidationOptions, valid: boolean, - numExpectedErrors?: number, + expectedErrorContains?: string, ) { - if (numExpectedErrors !== undefined && numExpectedErrors > 0 && valid) { + if (expectedErrorContains !== undefined && valid) { throw new Error('Cannot expect errors for a valid contract'); } @@ -58,8 +58,8 @@ function testOverride( t.notThrows(assertUpgSafe); } else { const error = t.throws(assertUpgSafe) as ValidationErrors; - if (numExpectedErrors !== undefined) { - t.is(error.errors.length, numExpectedErrors); + if (expectedErrorContains !== undefined) { + t.true(error.message.includes(expectedErrorContains), error.message); } } }); @@ -68,23 +68,43 @@ function testOverride( testValid('Child_Of_NoInitializer_Ok', 'transparent', true); testValid('Child_Of_InitializerModifier_Ok', 'transparent', true); -testValid('Child_Of_InitializerModifier_Bad', 'transparent', false, 1); +testValid( + 'Child_Of_InitializerModifier_Bad', + 'transparent', + false, + 'Contract is missing a call to a parent initializer', +); testValid('Child_Of_InitializerModifier_UsesSuper_Ok', 'transparent', true); testValid('Child_Of_ReinitializerModifier_Ok', 'transparent', true); -testValid('Child_Of_ReinitializerModifier_Bad', 'transparent', false, 1); +testValid( + 'Child_Of_ReinitializerModifier_Bad', + 'transparent', + false, + 'Contract is missing a call to a parent initializer', +); testValid('Child_Of_OnlyInitializingModifier_Ok', 'transparent', true); -testValid('Child_Of_OnlyInitializingModifier_Bad', 'transparent', false, 1); +testValid( + 'Child_Of_OnlyInitializingModifier_Bad', + 'transparent', + false, + 'Contract is missing a call to a parent initializer', +); -testValid('MissingInitializer_Bad', 'transparent', false, 1); +testValid('MissingInitializer_Bad', 'transparent', false, 'Contract is missing an initializer'); testValid('MissingInitializer_UnsafeAllow_Contract', 'transparent', true); testOverride('MissingInitializer_Bad', 'transparent', { unsafeAllow: ['missing-initializer'] }, true); testValid('InitializationOrder_Ok', 'transparent', true); testValid('InitializationOrder_Ok_2', 'transparent', true); -testValid('InitializationOrder_WrongOrder_Bad', 'transparent', false, 1); +testValid( + 'InitializationOrder_WrongOrder_Bad', + 'transparent', + false, + 'Contract has an incorrect order of parent initializer calls. Expected initializers to be called for parent contracts in the following order: A, B, C', +); testValid('InitializationOrder_WrongOrder_UnsafeAllow_Contract', 'transparent', true); testValid('InitializationOrder_WrongOrder_UnsafeAllow_Function', 'transparent', true); testOverride( @@ -94,12 +114,22 @@ testOverride( true, ); -testValid('InitializationOrder_MissingCall_Bad', 'transparent', false, 1); +testValid( + 'InitializationOrder_MissingCall_Bad', + 'transparent', + false, + 'Contract is missing a call to a parent initializer', +); testValid('InitializationOrder_MissingCall_UnsafeAllow_Contract', 'transparent', true); testValid('InitializationOrder_MissingCall_UnsafeAllow_Function', 'transparent', true); testOverride('InitializationOrder_MissingCall_Bad', 'transparent', { unsafeAllow: ['missing-initializer-call'] }, true); -testValid('InitializationOrder_Duplicate_Bad', 'transparent', false, 1); +testValid( + 'InitializationOrder_Duplicate_Bad', + 'transparent', + false, + 'Contract has multiple calls to a parent initializer', +); testValid('InitializationOrder_Duplicate_UnsafeAllow_Contract', 'transparent', true); testValid('InitializationOrder_Duplicate_UnsafeAllow_Function', 'transparent', true); testValid('InitializationOrder_Duplicate_UnsafeAllow_Call', 'transparent', true); diff --git a/packages/core/src/validate/report.ts b/packages/core/src/validate/report.ts index d139a5da8..a606ec2d8 100644 --- a/packages/core/src/validate/report.ts +++ b/packages/core/src/validate/report.ts @@ -88,7 +88,8 @@ const errorInfo: ErrorDescriptions = { link: 'https://zpl.in/upgrades/error-001', }, 'incorrect-initializer-order': { - msg: e => `Contract has an incorrect order of parent initializer calls. Expected initializers to be called for parent contracts in the following order: ${e.expectedLinearization.join(', ')}`, + msg: e => + `Contract has an incorrect order of parent initializer calls. Expected initializers to be called for parent contracts in the following order: ${e.expectedLinearization.join(', ')}`, hint: () => `Call parent initializers in the order they are inherited`, link: 'https://zpl.in/upgrades/error-001', }, diff --git a/packages/core/src/validate/run.ts b/packages/core/src/validate/run.ts index 531d6f4ee..6acf305ba 100644 --- a/packages/core/src/validate/run.ts +++ b/packages/core/src/validate/run.ts @@ -761,9 +761,9 @@ function getPossibleInitializers(contractDef: ContractDefinition) { fnDef => (fnDef.modifiers.some(modifier => ['initializer', 'reinitializer', 'onlyInitializing'].includes(modifier.modifierName.name), - ) || ['initialize', 'initializer', 'reinitialize', 'reinitializer'].includes(fnDef.name)) - && - !(fnDef.virtual && !fnDef.body) // Skip virtual functions without a body, since that indicates an abstract function and is not itself an initializer + ) || + ['initialize', 'initializer', 'reinitialize', 'reinitializer'].includes(fnDef.name)) && + !(fnDef.virtual && !fnDef.body), // Skip virtual functions without a body, since that indicates an abstract function and is not itself an initializer ); }