@openzeppelin/upgrades-core 1.20.6 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ava_1 = __importDefault(require("ava"));
7
+ const run_1 = require("./run");
8
+ (0, ava_1.default)('getAnnotationArgs', t => {
9
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor selfdestruct';
10
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
11
+ });
12
+ (0, ava_1.default)('getAnnotationArgs no arg', t => {
13
+ const doc = ' @custom:oz-upgrades-unsafe-allow';
14
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), []);
15
+ });
16
+ (0, ava_1.default)('getAnnotationArgs space no arg', t => {
17
+ const doc = ' @custom:oz-upgrades-unsafe-allow ';
18
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), []);
19
+ });
20
+ (0, ava_1.default)('getAnnotationArgs whitespace at end', t => {
21
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor ';
22
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor']);
23
+ });
24
+ (0, ava_1.default)('getAnnotationArgs same type', t => {
25
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor\n @custom:oz-upgrades-unsafe-allow selfdestruct';
26
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
27
+ });
28
+ (0, ava_1.default)('getAnnotationArgs multiline', t => {
29
+ const doc = ' othercomments\n @custom:oz-upgrades-unsafe-allow constructor selfdestruct\n @custom:oz-upgrades-unsafe-allow-reachable delegatecall';
30
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
31
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
32
+ });
33
+ (0, ava_1.default)('getAnnotationArgs multiline with spaces and comments', t => {
34
+ const doc = ' some other comments\n @custom:oz-upgrades-unsafe-allow \n constructor \n selfdestruct \n @custom:oz-upgrades-unsafe-allow-reachable \n delegatecall';
35
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
36
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
37
+ });
38
+ (0, ava_1.default)('getAnnotationArgs multiline multiple preceding spaces', t => {
39
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor selfdestruct \n @custom:oz-upgrades-unsafe-allow-reachable delegatecall ';
40
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
41
+ t.deepEqual((0, run_1.getAnnotationArgs)(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
42
+ });
43
+ //# sourceMappingURL=run.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.test.js","sourceRoot":"","sources":["../../src/validate/run.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAAuB;AAEvB,+BAA0C;AAE1C,IAAA,aAAI,EAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE;IAC5B,MAAM,GAAG,GAAG,4DAA4D,CAAC;IACzE,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;AACnG,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE;IACnC,MAAM,GAAG,GAAG,mCAAmC,CAAC;IAChD,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,EAAE,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,gCAAgC,EAAE,CAAC,CAAC,EAAE;IACzC,MAAM,GAAG,GAAG,oCAAoC,CAAC;IACjD,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,EAAE,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,qCAAqC,EAAE,CAAC,CAAC,EAAE;IAC9C,MAAM,GAAG,GAAG,gDAAgD,CAAC;IAC7D,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;AACnF,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,6BAA6B,EAAE,CAAC,CAAC,EAAE;IACtC,MAAM,GAAG,GAAG,+FAA+F,CAAC;IAC5G,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;AACnG,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,6BAA6B,EAAE,CAAC,CAAC,EAAE;IACtC,MAAM,GAAG,GACP,sIAAsI,CAAC;IACzI,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,oCAAoC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,sDAAsD,EAAE,CAAC,CAAC,EAAE;IAC/D,MAAM,GAAG,GACP,mKAAmK,CAAC;IACtK,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,oCAAoC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,uDAAuD,EAAE,CAAC,CAAC,EAAE;IAChE,MAAM,GAAG,GACP,mIAAmI,CAAC;IACtI,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,0BAA0B,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,SAAS,CAAC,IAAA,uBAAiB,EAAC,GAAG,EAAE,oCAAoC,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate-ignore-errors.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-ignore-errors.test.d.ts","sourceRoot":"","sources":["../src/validate-ignore-errors.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ava_1 = __importDefault(require("ava"));
7
+ const hardhat_1 = require("hardhat");
8
+ const validate_1 = require("./validate");
9
+ const src_decoder_1 = require("./src-decoder");
10
+ const test = ava_1.default;
11
+ test.before(async (t) => {
12
+ const contracts = [
13
+ 'contracts/test/ignore-errors/SafeContract.sol:SafeContract',
14
+ 'contracts/test/ignore-errors/SafeContractWithFreeFunctionCall.sol:SafeContractWithFreeFunctionCall',
15
+ 'contracts/test/ignore-errors/SafeContractWithLibraryCall.sol:SafeContractWithLibraryCall',
16
+ 'contracts/test/ignore-errors/SafeContractWithLibraryImport.sol:SafeContractWithLibraryImport',
17
+ 'contracts/test/ignore-errors/SafeContractWithLibraryUsingFor.sol:SafeContractWithLibraryUsingFor',
18
+ 'contracts/test/ignore-errors/SafeContractWithTransitiveLibraryCall.sol:SafeContractWithTransitiveLibraryCall',
19
+ 'contracts/test/ignore-errors/SafeContractWithParentCall.sol:SafeContractWithParentCall',
20
+ 'contracts/test/ignore-errors/RiskyParentContract.sol:RiskyParentContract',
21
+ 'contracts/test/ignore-errors/UnsafeContract.sol:UnsafeContract',
22
+ 'contracts/test/ignore-errors/UnsafeContractWithFreeFunctionCall.sol:UnsafeContractWithFreeFunctionCall',
23
+ 'contracts/test/ignore-errors/UnsafeContractWithLibraryCall.sol:UnsafeContractWithLibraryCall',
24
+ 'contracts/test/ignore-errors/UnsafeContractWithLibraryUsingFor.sol:UnsafeContractWithLibraryUsingFor',
25
+ 'contracts/test/ignore-errors/UnsafeContractWithTransitiveLibraryCall.sol:UnsafeContractWithTransitiveLibraryCall',
26
+ 'contracts/test/ignore-errors/UnsafeContractWithParentCall.sol:UnsafeContractWithParentCall',
27
+ 'contracts/test/ignore-errors/UnsafeContractWithInheritedParent.sol:UnsafeContractWithInheritedParent',
28
+ 'contracts/test/ignore-errors/UnsafeContractWithInheritedTransitiveParent.sol:UnsafeContractWithInheritedTransitiveParent',
29
+ 'contracts/test/ignore-errors/UnsafeAllow.sol:UnsafeAllow',
30
+ 'contracts/test/ignore-errors/AllowReachable.sol:AllowReachable',
31
+ 'contracts/test/ignore-errors/UnsafeAllowReachableDifferentOpcode.sol:UnsafeAllowReachableDifferentOpcode',
32
+ 'contracts/test/ignore-errors/UnsafeAllowParent.sol:UnsafeAllowParent',
33
+ 'contracts/test/ignore-errors/AllowReachableParent.sol:AllowReachableParent',
34
+ 'contracts/test/ignore-errors/UnsafeAllowReachableParentDifferentOpcode.sol:UnsafeAllowReachableParentDifferentOpcode',
35
+ 'contracts/test/ignore-errors/AllowChildInheritedTransitive.sol:AllowChildInheritedTransitive',
36
+ 'contracts/test/ignore-errors/AllowChild.sol:AllowChild',
37
+ 'contracts/test/ignore-errors/AllowChildCallTransitive.sol:AllowChildCallTransitive',
38
+ 'contracts/test/ignore-errors/AllowChildSelfReachable.sol:AllowChildSelfReachable',
39
+ 'contracts/test/ignore-errors/SafeRecursion.sol:SafeRecursion',
40
+ 'contracts/test/ignore-errors/UnsafeRecursion.sol:UnsafeRecursion',
41
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeChild1',
42
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeChild2',
43
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeChild3',
44
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeChild4',
45
+ 'contracts/test/ignore-errors/Constructors.sol:AllowChild5',
46
+ 'contracts/test/ignore-errors/Constructors.sol:AllowChild6',
47
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeAllowChild7',
48
+ 'contracts/test/ignore-errors/Constructors.sol:AllowReachableChild8',
49
+ 'contracts/test/ignore-errors/Constructors.sol:UnsafeChild9',
50
+ // 'contracts/test/ignore-errors/Modifiers.sol:ModifierNotUsed',
51
+ 'contracts/test/ignore-errors/Modifiers.sol:ModifierUsed',
52
+ ];
53
+ t.context.validation = {};
54
+ for (const contract of contracts) {
55
+ const buildInfo = await hardhat_1.artifacts.getBuildInfo(contract);
56
+ if (buildInfo === undefined) {
57
+ throw new Error(`Build info not found for contract ${contract}`);
58
+ }
59
+ const solcOutput = buildInfo.output;
60
+ const solcInput = buildInfo.input;
61
+ const decodeSrc = (0, src_decoder_1.solcInputOutputDecoder)(solcInput, solcOutput);
62
+ Object.assign(t.context.validation, (0, validate_1.validate)(solcOutput, decodeSrc));
63
+ }
64
+ });
65
+ function testValid(name, kind, valid) {
66
+ testOverride(name, kind, {}, valid);
67
+ }
68
+ function testOverride(name, kind, opts, valid) {
69
+ const optKeys = Object.keys(opts);
70
+ const describeOpts = optKeys.length > 0 ? '(' + optKeys.join(', ') + ')' : '';
71
+ const testName = [valid ? 'accepts' : 'rejects', kind, name, describeOpts].join(' ');
72
+ test(testName, t => {
73
+ const version = (0, validate_1.getContractVersion)(t.context.validation, name);
74
+ const assertUpgSafe = () => (0, validate_1.assertUpgradeSafe)([t.context.validation], version, { kind, ...opts });
75
+ if (valid) {
76
+ t.notThrows(assertUpgSafe);
77
+ }
78
+ else {
79
+ t.throws(assertUpgSafe);
80
+ }
81
+ });
82
+ }
83
+ testValid('SafeContract', 'transparent', true);
84
+ testValid('SafeContractWithFreeFunctionCall', 'transparent', true);
85
+ testValid('SafeContractWithLibraryCall', 'transparent', true);
86
+ testValid('SafeContractWithLibraryImport', 'transparent', true);
87
+ testValid('SafeContractWithLibraryUsingFor', 'transparent', true);
88
+ testValid('SafeContractWithTransitiveLibraryCall', 'transparent', true);
89
+ testValid('SafeContractWithParentCall', 'transparent', true);
90
+ testValid('RiskyParentContract', 'transparent', false);
91
+ testValid('UnsafeContract', 'transparent', false);
92
+ testValid('UnsafeContractWithFreeFunctionCall', 'transparent', false);
93
+ testValid('UnsafeContractWithLibraryCall', 'transparent', false);
94
+ testValid('UnsafeContractWithLibraryUsingFor', 'transparent', false);
95
+ testValid('UnsafeContractWithTransitiveLibraryCall', 'transparent', false);
96
+ testValid('UnsafeContractWithParentCall', 'transparent', false);
97
+ testValid('UnsafeContractWithInheritedParent', 'transparent', false);
98
+ testValid('UnsafeContractWithInheritedTransitiveParent', 'transparent', false);
99
+ testValid('UnsafeAllow', 'transparent', false);
100
+ testValid('AllowReachable', 'transparent', true);
101
+ testValid('UnsafeAllowReachableDifferentOpcode', 'transparent', false);
102
+ testValid('UnsafeAllowParent', 'transparent', false);
103
+ testValid('AllowReachableParent', 'transparent', true);
104
+ testValid('UnsafeAllowReachableParentDifferentOpcode', 'transparent', false);
105
+ testValid('AllowChildInheritedTransitive', 'transparent', true);
106
+ testValid('AllowChild', 'transparent', true);
107
+ testValid('AllowChildCallTransitive', 'transparent', true);
108
+ testValid('AllowChildSelfReachable', 'transparent', true);
109
+ testValid('SafeRecursion', 'transparent', true);
110
+ testValid('UnsafeRecursion', 'transparent', false);
111
+ testValid('UnsafeChild1', 'transparent', false);
112
+ testValid('UnsafeChild2', 'transparent', false);
113
+ testValid('UnsafeChild3', 'transparent', false);
114
+ testValid('UnsafeChild4', 'transparent', false);
115
+ testValid('AllowChild5', 'transparent', true);
116
+ testValid('AllowChild6', 'transparent', true);
117
+ testValid('UnsafeAllowChild7', 'transparent', false);
118
+ testValid('AllowReachableChild8', 'transparent', true);
119
+ testValid('UnsafeChild9', 'transparent', false);
120
+ // TODO: do not throw an error in this case
121
+ // testValid('ModifierNotUsed', 'transparent', true);
122
+ testValid('ModifierUsed', 'transparent', false);
123
+ //# sourceMappingURL=validate-ignore-errors.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-ignore-errors.test.js","sourceRoot":"","sources":["../src/validate-ignore-errors.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAAoC;AACpC,qCAAoC;AAEpC,yCAA+G;AAC/G,+CAAuD;AAMvD,MAAM,IAAI,GAAG,aAAwB,CAAC;AAEtC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAC,CAAC,EAAC,EAAE;IACpB,MAAM,SAAS,GAAG;QAChB,4DAA4D;QAC5D,oGAAoG;QACpG,0FAA0F;QAC1F,8FAA8F;QAC9F,kGAAkG;QAClG,8GAA8G;QAC9G,wFAAwF;QACxF,0EAA0E;QAC1E,gEAAgE;QAChE,wGAAwG;QACxG,8FAA8F;QAC9F,sGAAsG;QACtG,kHAAkH;QAClH,4FAA4F;QAC5F,sGAAsG;QACtG,0HAA0H;QAC1H,0DAA0D;QAC1D,gEAAgE;QAChE,0GAA0G;QAC1G,sEAAsE;QACtE,4EAA4E;QAC5E,sHAAsH;QACtH,8FAA8F;QAC9F,wDAAwD;QACxD,oFAAoF;QACpF,kFAAkF;QAClF,8DAA8D;QAC9D,kEAAkE;QAClE,4DAA4D;QAC5D,4DAA4D;QAC5D,4DAA4D;QAC5D,4DAA4D;QAC5D,2DAA2D;QAC3D,2DAA2D;QAC3D,iEAAiE;QACjE,oEAAoE;QACpE,4DAA4D;QAC5D,gEAAgE;QAChE,yDAAyD;KAC1D,CAAC;IAEF,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG,EAAmB,CAAC;IAC3C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAChC,MAAM,SAAS,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,SAAS,KAAK,SAAS,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;SAClE;QACD,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC;QACpC,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC;QAClC,MAAM,SAAS,GAAG,IAAA,oCAAsB,EAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,IAAA,mBAAQ,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;KACtE;AACH,CAAC,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,IAAY,EAAE,IAA+B,EAAE,KAAc;IAC9E,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,IAA+B,EAAE,IAAuB,EAAE,KAAc;IAC1G,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrF,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE;QACjB,MAAM,OAAO,GAAG,IAAA,6BAAkB,EAAC,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAA,4BAAiB,EAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAClG,IAAI,KAAK,EAAE;YACT,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;SAC5B;aAAM;YACL,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;SACzB;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC/C,SAAS,CAAC,kCAAkC,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACnE,SAAS,CAAC,6BAA6B,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC9D,SAAS,CAAC,+BAA+B,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAChE,SAAS,CAAC,iCAAiC,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAClE,SAAS,CAAC,uCAAuC,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACxE,SAAS,CAAC,4BAA4B,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAE7D,SAAS,CAAC,qBAAqB,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAEvD,SAAS,CAAC,gBAAgB,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAClD,SAAS,CAAC,oCAAoC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACtE,SAAS,CAAC,+BAA+B,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACjE,SAAS,CAAC,mCAAmC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACrE,SAAS,CAAC,yCAAyC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAC3E,SAAS,CAAC,8BAA8B,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAChE,SAAS,CAAC,mCAAmC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACrE,SAAS,CAAC,6CAA6C,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAE/E,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAC/C,SAAS,CAAC,gBAAgB,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACjD,SAAS,CAAC,qCAAqC,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAEvE,SAAS,CAAC,mBAAmB,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACrD,SAAS,CAAC,sBAAsB,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACvD,SAAS,CAAC,2CAA2C,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAE7E,SAAS,CAAC,+BAA+B,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAChE,SAAS,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC7C,SAAS,CAAC,0BAA0B,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAE3D,SAAS,CAAC,yBAAyB,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAE1D,SAAS,CAAC,eAAe,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAChD,SAAS,CAAC,iBAAiB,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAEnD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAChD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAChD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAChD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAChD,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC9C,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC9C,SAAS,CAAC,mBAAmB,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AACrD,SAAS,CAAC,sBAAsB,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AACvD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;AAEhD,2CAA2C;AAC3C,qDAAqD;AAErD,SAAS,CAAC,cAAc,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/upgrades-core",
3
- "version": "1.20.6",
3
+ "version": "1.21.0",
4
4
  "description": "",
5
5
  "repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core",
6
6
  "license": "MIT",
@@ -58,5 +58,5 @@
58
58
  "proper-lockfile": "^4.1.1",
59
59
  "solidity-ast": "^0.4.15"
60
60
  },
61
- "gitHead": "56dd6059cc916a95378d9e5893306fbb9020f071"
61
+ "gitHead": "b2b7123c20d0df0362c5b7509135670b68f31705"
62
62
  }
package/src/provider.ts CHANGED
@@ -106,6 +106,8 @@ export const networkNames: { [chainId in number]?: string } = Object.freeze({
106
106
  80001: 'polygon-mumbai',
107
107
  43113: 'avalanche-fuji',
108
108
  43114: 'avalanche',
109
+ 42220: 'celo',
110
+ 44787: 'celo-alfajores',
109
111
  });
110
112
 
111
113
  export async function isDevelopmentNetwork(provider: EthereumProvider): Promise<boolean> {
@@ -19,7 +19,7 @@ export function solcInputOutputDecoder(solcInput: SolcInput, solcOutput: SolcOut
19
19
  if (sourcePath === undefined) {
20
20
  throw new Error(`Source file not available`);
21
21
  }
22
- const content = solcInput.sources[sourcePath].content;
22
+ const content = solcInput.sources[sourcePath]?.content;
23
23
  const name = path.relative(basePath, sourcePath);
24
24
  if (content === undefined) {
25
25
  throw new Error(`Content for ${name} not available`);
@@ -1,5 +1,5 @@
1
1
  import { Version, getVersion } from '../version';
2
- import { ValidationRunData, ValidationError } from './run';
2
+ import { ValidationRunData, ValidationError, isOpcodeError } from './run';
3
3
  import { StorageLayout } from '../storage/layout';
4
4
  import { unlinkBytecode } from '../link-refs';
5
5
  import { ValidationOptions, processExceptions } from './overrides';
@@ -143,9 +143,7 @@ export function getErrors(data: ValidationData, version: Version, opts: Validati
143
143
  const [fullContractName, runValidation] = getContractNameAndRunValidation(dataV3, version);
144
144
  const c = runValidation[fullContractName];
145
145
 
146
- const errors = getUsedContractsAndLibraries(fullContractName, runValidation).flatMap(
147
- name => runValidation[name].errors,
148
- );
146
+ const errors = getAllErrors(runValidation, fullContractName);
149
147
 
150
148
  const selfAndInheritedMethods = getAllMethods(runValidation, fullContractName);
151
149
 
@@ -159,21 +157,27 @@ export function getErrors(data: ValidationData, version: Version, opts: Validati
159
157
  return processExceptions(fullContractName, errors, opts);
160
158
  }
161
159
 
160
+ function getAllErrors(runValidation: ValidationRunData, fullContractName: string) {
161
+ // add self's opcode errors only, since opcode errors already include parents
162
+ const opcodeErrors = runValidation[fullContractName].errors.filter(error => isOpcodeError(error));
163
+
164
+ // add other errors from self and inherited contracts
165
+ const otherErrors = getUsedContracts(fullContractName, runValidation)
166
+ .flatMap(name => runValidation[name].errors)
167
+ .filter(error => !isOpcodeError(error));
168
+
169
+ return [...opcodeErrors, ...otherErrors];
170
+ }
171
+
162
172
  function getAllMethods(runValidation: ValidationRunData, fullContractName: string): string[] {
163
173
  const c = runValidation[fullContractName];
164
174
  return c.methods.concat(...c.inherit.map(name => runValidation[name].methods));
165
175
  }
166
176
 
167
- function getUsedContractsAndLibraries(contractName: string, runValidation: ValidationRunData) {
177
+ function getUsedContracts(contractName: string, runValidation: ValidationRunData) {
168
178
  const c = runValidation[contractName];
169
179
  // Add current contract and all of its parents
170
180
  const res = new Set([contractName, ...c.inherit]);
171
- // Add used libraries transitively until no more are found
172
- for (const c1 of res) {
173
- for (const c2 of runValidation[c1].libraries) {
174
- res.add(c2);
175
- }
176
- }
177
181
  return Array.from(res);
178
182
  }
179
183
 
@@ -0,0 +1,49 @@
1
+ import test from 'ava';
2
+
3
+ import { getAnnotationArgs } from './run';
4
+
5
+ test('getAnnotationArgs', t => {
6
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor selfdestruct';
7
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
8
+ });
9
+
10
+ test('getAnnotationArgs no arg', t => {
11
+ const doc = ' @custom:oz-upgrades-unsafe-allow';
12
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), []);
13
+ });
14
+
15
+ test('getAnnotationArgs space no arg', t => {
16
+ const doc = ' @custom:oz-upgrades-unsafe-allow ';
17
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), []);
18
+ });
19
+
20
+ test('getAnnotationArgs whitespace at end', t => {
21
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor ';
22
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor']);
23
+ });
24
+
25
+ test('getAnnotationArgs same type', t => {
26
+ const doc = ' @custom:oz-upgrades-unsafe-allow constructor\n @custom:oz-upgrades-unsafe-allow selfdestruct';
27
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
28
+ });
29
+
30
+ test('getAnnotationArgs multiline', t => {
31
+ const doc =
32
+ ' othercomments\n @custom:oz-upgrades-unsafe-allow constructor selfdestruct\n @custom:oz-upgrades-unsafe-allow-reachable delegatecall';
33
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
34
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
35
+ });
36
+
37
+ test('getAnnotationArgs multiline with spaces and comments', t => {
38
+ const doc =
39
+ ' some other comments\n @custom:oz-upgrades-unsafe-allow \n constructor \n selfdestruct \n @custom:oz-upgrades-unsafe-allow-reachable \n delegatecall';
40
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
41
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
42
+ });
43
+
44
+ test('getAnnotationArgs multiline multiple preceding spaces', t => {
45
+ const doc =
46
+ ' @custom:oz-upgrades-unsafe-allow constructor selfdestruct \n @custom:oz-upgrades-unsafe-allow-reachable delegatecall ';
47
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow'), ['constructor', 'selfdestruct']);
48
+ t.deepEqual(getAnnotationArgs(doc, 'oz-upgrades-unsafe-allow-reachable'), ['delegatecall']);
49
+ });
@@ -1,6 +1,6 @@
1
1
  import { Node } from 'solidity-ast/node';
2
- import { isNodeType, findAll } from 'solidity-ast/utils';
3
- import type { ContractDefinition } from 'solidity-ast';
2
+ import { isNodeType, findAll, ASTDereferencer } from 'solidity-ast/utils';
3
+ import type { ContractDefinition, FunctionDefinition } from 'solidity-ast';
4
4
 
5
5
  import { SolcOutput, SolcBytecode } from '../solc-api';
6
6
  import { SrcDecoder } from '../src-decoder';
@@ -68,6 +68,26 @@ interface ValidationErrorOpcode extends ValidationErrorBase {
68
68
  kind: 'delegatecall' | 'selfdestruct';
69
69
  }
70
70
 
71
+ interface OpcodePattern {
72
+ kind: 'delegatecall' | 'selfdestruct';
73
+ pattern: RegExp;
74
+ }
75
+
76
+ const OPCODES = {
77
+ delegatecall: {
78
+ kind: 'delegatecall',
79
+ pattern: /^t_function_baredelegatecall_/,
80
+ },
81
+ selfdestruct: {
82
+ kind: 'selfdestruct',
83
+ pattern: /^t_function_selfdestruct_/,
84
+ },
85
+ } as const;
86
+
87
+ export function isOpcodeError(error: ValidationErrorBase): error is ValidationErrorOpcode {
88
+ return error.kind === 'delegatecall' || error.kind === 'selfdestruct';
89
+ }
90
+
71
91
  interface ValidationErrorUpgradeability extends ValidationErrorBase {
72
92
  kind: 'missing-public-upgradeto';
73
93
  }
@@ -84,34 +104,49 @@ function* execall(re: RegExp, text: string) {
84
104
  }
85
105
  }
86
106
 
87
- function getAllowed(node: Node): string[] {
107
+ function getAllowed(node: Node, reachable: boolean): string[] {
88
108
  if ('documentation' in node) {
109
+ const tag = `oz-upgrades-unsafe-allow${reachable ? '-reachable' : ''}`;
89
110
  const doc = typeof node.documentation === 'string' ? node.documentation : node.documentation?.text ?? '';
111
+ return getAnnotationArgs(doc, tag);
112
+ } else {
113
+ return [];
114
+ }
115
+ }
90
116
 
91
- const result: string[] = [];
92
- for (const { groups } of execall(
93
- /^\s*(?:@(?<title>\w+)(?::(?<tag>[a-z][a-z-]*))? )?(?<args>(?:(?!^\s@\w+)[^])*)/m,
94
- doc,
95
- )) {
96
- if (groups && groups.title === 'custom' && groups.tag === 'oz-upgrades-unsafe-allow') {
97
- result.push(...groups.args.split(/\s+/));
117
+ /**
118
+ * Get args from the doc string matching the given tag
119
+ */
120
+ export function getAnnotationArgs(doc: string, tag: string) {
121
+ const result: string[] = [];
122
+ for (const { groups } of execall(
123
+ /^\s*(?:@(?<title>\w+)(?::(?<tag>[a-z][a-z-]*))? )?(?<args>(?:(?!^\s*@\w+)[^])*)/m,
124
+ doc,
125
+ )) {
126
+ if (groups && groups.title === 'custom' && groups.tag === tag) {
127
+ const trimmedArgs = groups.args.trim();
128
+ if (trimmedArgs.length > 0) {
129
+ result.push(...trimmedArgs.split(/\s+/));
98
130
  }
99
131
  }
132
+ }
100
133
 
101
- result.forEach(arg => {
102
- if (!(errorKinds as readonly string[]).includes(arg)) {
103
- throw new Error(`NatSpec: oz-upgrades-unsafe-allow argument not recognized: ${arg}`);
104
- }
105
- });
134
+ result.forEach(arg => {
135
+ if (!(errorKinds as readonly string[]).includes(arg)) {
136
+ throw new Error(`NatSpec: ${tag} argument not recognized: ${arg}`);
137
+ }
138
+ });
106
139
 
107
- return result;
108
- } else {
109
- return [];
110
- }
140
+ return result;
141
+ }
142
+
143
+ function skipCheckReachable(error: string, node: Node): boolean {
144
+ return getAllowed(node, true).includes(error);
111
145
  }
112
146
 
113
147
  function skipCheck(error: string, node: Node): boolean {
114
- return getAllowed(node).includes(error);
148
+ // skip both allow and allow-reachable errors in the lexical scope
149
+ return getAllowed(node, false).includes(error) || getAllowed(node, true).includes(error);
115
150
  }
116
151
 
117
152
  function getFullyQualifiedName(source: string, contractName: string) {
@@ -163,7 +198,7 @@ export function validate(solcOutput: SolcOutput, decodeSrc: SrcDecoder, solcVers
163
198
  validation[key].src = decodeSrc(contractDef);
164
199
  validation[key].errors = [
165
200
  ...getConstructorErrors(contractDef, decodeSrc),
166
- ...getOpcodeErrors(contractDef, decodeSrc),
201
+ ...getOpcodeErrors(contractDef, deref, decodeSrc),
167
202
  ...getStateVariableErrors(contractDef, decodeSrc),
168
203
  // TODO: add linked libraries support
169
204
  // https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/52
@@ -206,27 +241,151 @@ function* getConstructorErrors(contractDef: ContractDefinition, decodeSrc: SrcDe
206
241
  }
207
242
  }
208
243
 
209
- function* getOpcodeErrors(contractDef: ContractDefinition, decodeSrc: SrcDecoder): Generator<ValidationErrorOpcode> {
210
- for (const fnCall of findAll('FunctionCall', contractDef, node => skipCheck('delegatecall', node))) {
244
+ function* getOpcodeErrors(
245
+ contractDef: ContractDefinition,
246
+ deref: ASTDereferencer,
247
+ decodeSrc: SrcDecoder,
248
+ ): Generator<ValidationErrorOpcode> {
249
+ yield* getContractOpcodeErrors(contractDef, deref, decodeSrc, OPCODES.delegatecall, 'main');
250
+ yield* getContractOpcodeErrors(contractDef, deref, decodeSrc, OPCODES.selfdestruct, 'main');
251
+ }
252
+
253
+ /**
254
+ * Whether this node is being visited as part of a main contract, or as an inherited contract or function
255
+ */
256
+ type Scope = 'main' | 'inherited';
257
+
258
+ function* getContractOpcodeErrors(
259
+ contractDef: ContractDefinition,
260
+ deref: ASTDereferencer,
261
+ decodeSrc: SrcDecoder,
262
+ opcode: OpcodePattern,
263
+ scope: Scope,
264
+ visitedNodeIds = new Map<number, Scope>(),
265
+ ): Generator<ValidationErrorOpcode> {
266
+ if (wasVisited(contractDef.id, scope, visitedNodeIds)) {
267
+ // We return early here, but the errors from this node were emitted when the node was marked as visited.
268
+ return;
269
+ } else {
270
+ visitedNodeIds.set(contractDef.id, scope);
271
+ }
272
+
273
+ yield* getFunctionOpcodeErrors(contractDef, deref, decodeSrc, opcode, scope, visitedNodeIds);
274
+ yield* getInheritedContractOpcodeErrors(contractDef, deref, decodeSrc, opcode, visitedNodeIds);
275
+ }
276
+
277
+ function wasVisited(key: number, scope: Scope, visitedNodeIds: Map<number, Scope>) {
278
+ return (
279
+ (scope === 'inherited' && visitedNodeIds.has(key)) || // looking up an inherited contract, and it was previously checked as a main contract OR inherited contract
280
+ (scope === 'main' && visitedNodeIds.get(key) === 'main') // looking up a main contract, and it was previously checked as a main contract
281
+ );
282
+ }
283
+
284
+ function* getFunctionOpcodeErrors(
285
+ contractOrFunctionDef: ContractDefinition | FunctionDefinition,
286
+ deref: ASTDereferencer,
287
+ decodeSrc: SrcDecoder,
288
+ opcode: OpcodePattern,
289
+ scope: Scope,
290
+ visitedNodeIds: Map<number, Scope>,
291
+ ): Generator<ValidationErrorOpcode> {
292
+ const parentContractDef = getParentDefinition(deref, contractOrFunctionDef);
293
+ if (parentContractDef === undefined || !skipCheck(opcode.kind, parentContractDef)) {
294
+ yield* getDirectFunctionOpcodeErrors(contractOrFunctionDef, decodeSrc, opcode, scope);
295
+ }
296
+ if (parentContractDef === undefined || !skipCheckReachable(opcode.kind, parentContractDef)) {
297
+ yield* getReferencedFunctionOpcodeErrors(contractOrFunctionDef, deref, decodeSrc, opcode, scope, visitedNodeIds);
298
+ }
299
+ }
300
+
301
+ function* getDirectFunctionOpcodeErrors(
302
+ contractOrFunctionDef: ContractDefinition | FunctionDefinition,
303
+ decodeSrc: SrcDecoder,
304
+ opcode: OpcodePattern,
305
+ scope: Scope,
306
+ ) {
307
+ for (const fnCall of findAll(
308
+ 'FunctionCall',
309
+ contractOrFunctionDef,
310
+ node => skipCheck(opcode.kind, node) || (scope === 'inherited' && isInternalFunction(node)),
311
+ )) {
211
312
  const fn = fnCall.expression;
212
- if (fn.typeDescriptions.typeIdentifier?.match(/^t_function_baredelegatecall_/)) {
313
+ if (fn.typeDescriptions.typeIdentifier?.match(opcode.pattern)) {
213
314
  yield {
214
- kind: 'delegatecall',
315
+ kind: opcode.kind,
215
316
  src: decodeSrc(fnCall),
216
317
  };
217
318
  }
218
319
  }
219
- for (const fnCall of findAll('FunctionCall', contractDef, node => skipCheck('selfdestruct', node))) {
320
+ }
321
+
322
+ function* getReferencedFunctionOpcodeErrors(
323
+ contractOrFunctionDef: ContractDefinition | FunctionDefinition,
324
+ deref: ASTDereferencer,
325
+ decodeSrc: SrcDecoder,
326
+ opcode: OpcodePattern,
327
+ scope: Scope,
328
+ visitedNodeIds: Map<number, Scope>,
329
+ ) {
330
+ for (const fnCall of findAll(
331
+ 'FunctionCall',
332
+ contractOrFunctionDef,
333
+ node => skipCheckReachable(opcode.kind, node) || (scope === 'inherited' && isInternalFunction(node)),
334
+ )) {
220
335
  const fn = fnCall.expression;
221
- if (fn.typeDescriptions.typeIdentifier?.match(/^t_function_selfdestruct_/)) {
222
- yield {
223
- kind: 'selfdestruct',
224
- src: decodeSrc(fnCall),
225
- };
336
+ if ('referencedDeclaration' in fn && fn.referencedDeclaration && fn.referencedDeclaration > 0) {
337
+ // non-positive references refer to built-in functions
338
+ const referencedNode = tryDerefFunction(deref, fn.referencedDeclaration);
339
+ if (referencedNode !== undefined) {
340
+ if (!wasVisited(referencedNode.id, scope, visitedNodeIds)) {
341
+ visitedNodeIds.set(referencedNode.id, scope);
342
+ yield* getFunctionOpcodeErrors(referencedNode, deref, decodeSrc, opcode, scope, visitedNodeIds);
343
+ }
344
+ }
226
345
  }
227
346
  }
228
347
  }
229
348
 
349
+ function tryDerefFunction(deref: ASTDereferencer, referencedDeclaration: number): FunctionDefinition | undefined {
350
+ try {
351
+ return deref(['FunctionDefinition'], referencedDeclaration);
352
+ } catch (e: any) {
353
+ if (!e.message.includes('No node with id')) {
354
+ throw e;
355
+ }
356
+ }
357
+ }
358
+
359
+ function* getInheritedContractOpcodeErrors(
360
+ contractDef: ContractDefinition,
361
+ deref: ASTDereferencer,
362
+ decodeSrc: SrcDecoder,
363
+ opcode: OpcodePattern,
364
+ visitedNodeIds: Map<number, Scope>,
365
+ ) {
366
+ if (!skipCheckReachable(opcode.kind, contractDef)) {
367
+ for (const base of contractDef.baseContracts) {
368
+ const referencedContract = deref('ContractDefinition', base.baseName.referencedDeclaration);
369
+ yield* getContractOpcodeErrors(referencedContract, deref, decodeSrc, opcode, 'inherited', visitedNodeIds);
370
+ }
371
+ }
372
+ }
373
+
374
+ function getParentDefinition(deref: ASTDereferencer, contractOrFunctionDef: ContractDefinition | FunctionDefinition) {
375
+ const parentNode = deref(['ContractDefinition', 'SourceUnit'], contractOrFunctionDef.scope);
376
+ if (parentNode.nodeType === 'ContractDefinition') {
377
+ return parentNode;
378
+ }
379
+ }
380
+
381
+ function isInternalFunction(node: Node) {
382
+ return (
383
+ node.nodeType === 'FunctionDefinition' &&
384
+ node.kind !== 'constructor' && // do not consider constructors as internal, because they are always called by children contracts' constructors
385
+ (node.visibility === 'internal' || node.visibility === 'private')
386
+ );
387
+ }
388
+
230
389
  function* getStateVariableErrors(
231
390
  contractDef: ContractDefinition,
232
391
  decodeSrc: SrcDecoder,