@openzeppelin/upgrades-core 1.34.0 → 1.34.2
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.
- package/CHANGELOG.md +8 -0
- package/dist/add-proxy-to-manifest.js +1 -2
- package/dist/add-proxy-to-manifest.js.map +1 -1
- package/dist/beacon.js +1 -2
- package/dist/beacon.js.map +1 -1
- package/dist/call-optional-signature.js +1 -2
- package/dist/call-optional-signature.js.map +1 -1
- package/dist/cli/validate/build-info-file.js +1 -2
- package/dist/cli/validate/build-info-file.js.map +1 -1
- package/dist/cli/validate/contract-report.js +2 -2
- package/dist/cli/validate/contract-report.js.map +1 -1
- package/dist/cli/validate/find-contract.js +2 -2
- package/dist/cli/validate/find-contract.js.map +1 -1
- package/dist/cli/validate/project-report.d.ts.map +1 -1
- package/dist/cli/validate/project-report.js +2 -2
- package/dist/cli/validate/project-report.js.map +1 -1
- package/dist/cli/validate/upgradeability-assessment.js +1 -2
- package/dist/cli/validate/upgradeability-assessment.js.map +1 -1
- package/dist/cli/validate/validate-upgrade-safety.js +3 -4
- package/dist/cli/validate/validate-upgrade-safety.js.map +1 -1
- package/dist/cli/validate/validations.js +1 -2
- package/dist/cli/validate/validations.js.map +1 -1
- package/dist/cli/validate.js +3 -4
- package/dist/cli/validate.js.map +1 -1
- package/dist/deployment.js +4 -4
- package/dist/deployment.js.map +1 -1
- package/dist/eip-1967-type.js +3 -4
- package/dist/eip-1967-type.js.map +1 -1
- package/dist/eip-1967.js +7 -7
- package/dist/eip-1967.js.map +1 -1
- package/dist/error.d.ts +0 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/impl-address.js +3 -3
- package/dist/impl-address.js.map +1 -1
- package/dist/impl-store.js +5 -6
- package/dist/impl-store.js.map +1 -1
- package/dist/levenshtein.js +1 -2
- package/dist/levenshtein.js.map +1 -1
- package/dist/link-refs.js +2 -3
- package/dist/link-refs.js.map +1 -1
- package/dist/manifest-storage-layout.js +2 -3
- package/dist/manifest-storage-layout.js.map +1 -1
- package/dist/manifest.js +3 -3
- package/dist/manifest.js.map +1 -1
- package/dist/provider.js +15 -15
- package/dist/provider.js.map +1 -1
- package/dist/proxy-kind.js +3 -4
- package/dist/proxy-kind.js.map +1 -1
- package/dist/scripts/migrate-oz-cli-project.js +4 -5
- package/dist/scripts/migrate-oz-cli-project.js.map +1 -1
- package/dist/src-decoder.js +1 -2
- package/dist/src-decoder.js.map +1 -1
- package/dist/storage/compare.js +4 -4
- package/dist/storage/compare.js.map +1 -1
- package/dist/storage/extract.js +4 -5
- package/dist/storage/extract.js.map +1 -1
- package/dist/storage/gap.js +2 -3
- package/dist/storage/gap.js.map +1 -1
- package/dist/storage/index.js +4 -4
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/layout.js +4 -5
- package/dist/storage/layout.js.map +1 -1
- package/dist/storage/namespace.js +3 -4
- package/dist/storage/namespace.js.map +1 -1
- package/dist/stub-provider.d.ts.map +1 -1
- package/dist/stub-provider.js +1 -2
- package/dist/stub-provider.js.map +1 -1
- package/dist/upgrade-interface-version.d.ts +0 -1
- package/dist/upgrade-interface-version.d.ts.map +1 -1
- package/dist/upgrade-interface-version.js +1 -2
- package/dist/upgrade-interface-version.js.map +1 -1
- package/dist/usage-error.js +2 -2
- package/dist/usage-error.js.map +1 -1
- package/dist/utils/address.js +1 -2
- package/dist/utils/address.js.map +1 -1
- package/dist/utils/annotations.js +3 -4
- package/dist/utils/annotations.js.map +1 -1
- package/dist/utils/assert.js +2 -3
- package/dist/utils/assert.js.map +1 -1
- package/dist/utils/contract-name.js +1 -2
- package/dist/utils/contract-name.js.map +1 -1
- package/dist/utils/curry.js +1 -2
- package/dist/utils/curry.js.map +1 -1
- package/dist/utils/deep-array.js +1 -2
- package/dist/utils/deep-array.js.map +1 -1
- package/dist/utils/execall.js +1 -2
- package/dist/utils/execall.js.map +1 -1
- package/dist/utils/function.js +1 -2
- package/dist/utils/function.js.map +1 -1
- package/dist/utils/indent.js +1 -2
- package/dist/utils/indent.js.map +1 -1
- package/dist/utils/is-nullish.js +1 -2
- package/dist/utils/is-nullish.js.map +1 -1
- package/dist/utils/is-value-type.js +1 -2
- package/dist/utils/is-value-type.js.map +1 -1
- package/dist/utils/itemize.js +2 -3
- package/dist/utils/itemize.js.map +1 -1
- package/dist/utils/log.js +3 -4
- package/dist/utils/log.js.map +1 -1
- package/dist/utils/make-namespaced.d.ts.map +1 -1
- package/dist/utils/make-namespaced.js +41 -21
- package/dist/utils/make-namespaced.js.map +1 -1
- package/dist/utils/make-namespaced.test.js +1 -1
- package/dist/utils/make-namespaced.test.js.map +1 -1
- package/dist/utils/make-non-enumerable.js +1 -2
- package/dist/utils/make-non-enumerable.js.map +1 -1
- package/dist/utils/map-values.js +1 -2
- package/dist/utils/map-values.js.map +1 -1
- package/dist/utils/parse-type-id.js +1 -2
- package/dist/utils/parse-type-id.js.map +1 -1
- package/dist/utils/pick.js +1 -2
- package/dist/utils/pick.js.map +1 -1
- package/dist/utils/stabilize-layout.d.ts +15 -15
- package/dist/utils/stabilize-layout.js +1 -2
- package/dist/utils/stabilize-layout.js.map +1 -1
- package/dist/utils/type-id.js +3 -4
- package/dist/utils/type-id.js.map +1 -1
- package/dist/validate/data.js +3 -4
- package/dist/validate/data.js.map +1 -1
- package/dist/validate/overrides.js +3 -3
- package/dist/validate/overrides.js.map +1 -1
- package/dist/validate/query.js +12 -13
- package/dist/validate/query.js.map +1 -1
- package/dist/validate/run.d.ts.map +1 -1
- package/dist/validate/run.js +29 -5
- package/dist/validate/run.js.map +1 -1
- package/dist/validate.test.js +26 -15
- package/dist/validate.test.js.map +1 -1
- package/dist/version.js +3 -4
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/src/utils/make-namespaced.test.ts +1 -1
- package/src/utils/make-namespaced.test.ts.md +46 -23
- package/src/utils/make-namespaced.test.ts.snap +0 -0
- package/src/utils/make-namespaced.ts +44 -18
- package/src/validate/run.ts +30 -1
- package/src/validate.test.ts +38 -18
|
@@ -46,22 +46,22 @@ Generated by [AVA](https://avajs.dev).
|
|
|
46
46
|
} SecondaryStorage $SecondaryStorage_random;␊
|
|
47
47
|
␊
|
|
48
48
|
/// @notice some natspec␊
|
|
49
|
-
|
|
49
|
+
function foo() public {}␊
|
|
50
50
|
␊
|
|
51
51
|
/// @param a docs␊
|
|
52
|
-
|
|
52
|
+
function foo1(uint a) public {}␊
|
|
53
53
|
␊
|
|
54
54
|
/// @param a docs␊
|
|
55
|
-
|
|
55
|
+
function foo2(uint a) internal {}␊
|
|
56
56
|
struct MyStruct { uint b; }␊
|
|
57
57
|
␊
|
|
58
58
|
// keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~bytes32(uint256(0xff));␊
|
|
59
59
|
bytes32 private constant MAIN_STORAGE_LOCATION =␊
|
|
60
60
|
0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500;␊
|
|
61
61
|
␊
|
|
62
|
-
|
|
62
|
+
function _getMainStorage() private pure returns (bool) {}␊
|
|
63
63
|
␊
|
|
64
|
-
|
|
64
|
+
function _getXTimesY() internal view returns (bool) {}␊
|
|
65
65
|
␊
|
|
66
66
|
/// @notice standlone natspec␊
|
|
67
67
|
␊
|
|
@@ -77,14 +77,14 @@ Generated by [AVA](https://avajs.dev).
|
|
|
77
77
|
/**␊
|
|
78
78
|
* doc block without natspec␊
|
|
79
79
|
*/␊
|
|
80
|
-
|
|
80
|
+
function foo3() public {}␊
|
|
81
81
|
␊
|
|
82
82
|
/**␊
|
|
83
83
|
* doc block with natspec␊
|
|
84
84
|
*␊
|
|
85
85
|
* @notice some natspec␊
|
|
86
86
|
*/␊
|
|
87
|
-
|
|
87
|
+
function foo4() public {}␊
|
|
88
88
|
␊
|
|
89
89
|
/**␊
|
|
90
90
|
* @dev a custom error inside a contract␊
|
|
@@ -99,35 +99,39 @@ Generated by [AVA](https://avajs.dev).
|
|
|
99
99
|
}␊
|
|
100
100
|
␊
|
|
101
101
|
contract HasFunction {␊
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
␊
|
|
103
|
+
function foo() pure public returns (bool) {}␊
|
|
104
104
|
}␊
|
|
105
105
|
␊
|
|
106
106
|
contract UsingFunction is HasFunction {␊
|
|
107
107
|
enum $astId_id_random { dummy }␊
|
|
108
108
|
}␊
|
|
109
109
|
␊
|
|
110
|
-
|
|
110
|
+
function FreeFunctionUsingSelector() pure returns (bool) {}␊
|
|
111
111
|
␊
|
|
112
|
-
|
|
112
|
+
bytes4 constant CONSTANT_USING_SELECTOR = HasFunction.foo.selector;␊
|
|
113
113
|
␊
|
|
114
114
|
library Lib {␊
|
|
115
|
-
|
|
115
|
+
function usingSelector() pure public returns (bool) {}␊
|
|
116
116
|
␊
|
|
117
|
-
|
|
117
|
+
function plusOne(uint x) pure public returns (bool) {}␊
|
|
118
118
|
}␊
|
|
119
119
|
␊
|
|
120
120
|
contract Consumer {␊
|
|
121
121
|
enum $astId_id_random { dummy }␊
|
|
122
122
|
␊
|
|
123
|
-
|
|
123
|
+
function usingFreeFunction() pure public returns (bool) {}␊
|
|
124
124
|
␊
|
|
125
|
-
|
|
125
|
+
function usingConstant() pure public returns (bool) {}␊
|
|
126
126
|
␊
|
|
127
|
-
|
|
127
|
+
function usingLibraryFunction() pure public returns (bool) {}␊
|
|
128
128
|
}␊
|
|
129
129
|
␊
|
|
130
|
-
|
|
130
|
+
contract HasConstantWithSelector {␊
|
|
131
|
+
bytes4 constant CONTRACT_CONSTANT_USING_SELECTOR = HasFunction.foo.selector;␊
|
|
132
|
+
}␊
|
|
133
|
+
␊
|
|
134
|
+
function plusTwo(uint x) pure returns (bool) {}␊
|
|
131
135
|
␊
|
|
132
136
|
/**␊
|
|
133
137
|
* @notice originally orphaned natspec␊
|
|
@@ -137,7 +141,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
137
141
|
* @dev plusThree␊
|
|
138
142
|
* @param x x␊
|
|
139
143
|
*/␊
|
|
140
|
-
|
|
144
|
+
function plusThree(uint x) pure returns (bool) {}␊
|
|
141
145
|
␊
|
|
142
146
|
/// @notice originally orphaned natspec 2␊
|
|
143
147
|
␊
|
|
@@ -146,9 +150,9 @@ Generated by [AVA](https://avajs.dev).
|
|
|
146
150
|
* @param x x␊
|
|
147
151
|
* @param y y␊
|
|
148
152
|
*/␊
|
|
149
|
-
|
|
153
|
+
function plusThree(uint x, uint y) pure returns (bool) {}␊
|
|
150
154
|
␊
|
|
151
|
-
|
|
155
|
+
function originallyNoDocumentation() pure {}␊
|
|
152
156
|
␊
|
|
153
157
|
/**␊
|
|
154
158
|
* @param foo foo␊
|
|
@@ -158,7 +162,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
158
162
|
contract UsingForDirectives {␊
|
|
159
163
|
enum $astId_id_random { dummy }␊
|
|
160
164
|
␊
|
|
161
|
-
|
|
165
|
+
function usingFor(uint x) pure public returns (bool) {}␊
|
|
162
166
|
}␊
|
|
163
167
|
␊
|
|
164
168
|
/**␊
|
|
@@ -179,19 +183,38 @@ Generated by [AVA](https://avajs.dev).
|
|
|
179
183
|
*/␊
|
|
180
184
|
enum CustomErrorOutsideContract { dummy }␊
|
|
181
185
|
␊
|
|
186
|
+
int8 constant MAX_SIZE_C = 2;␊
|
|
187
|
+
␊
|
|
182
188
|
contract StructArrayUsesConstant {␊
|
|
183
189
|
uint16 private constant MAX_SIZE = 10;␊
|
|
184
190
|
␊
|
|
185
191
|
struct NotNamespaced {␊
|
|
186
192
|
uint16 a;␊
|
|
187
193
|
uint256[MAX_SIZE] b;␊
|
|
194
|
+
uint256[MAX_SIZE_C] c;␊
|
|
188
195
|
}␊
|
|
189
196
|
␊
|
|
190
197
|
/// @custom:storage-location erc7201:uses.constant␊
|
|
191
198
|
struct MainStorage {␊
|
|
192
199
|
uint256 x;␊
|
|
193
200
|
uint256[MAX_SIZE] y;␊
|
|
201
|
+
uint256[MAX_SIZE_C] c;␊
|
|
194
202
|
} MainStorage $MainStorage_random;␊
|
|
203
|
+
}␊
|
|
204
|
+
␊
|
|
205
|
+
address constant MY_ADDRESS = address(0);␊
|
|
206
|
+
uint constant CONVERTED_ADDRESS = uint160(MY_ADDRESS);␊
|
|
207
|
+
␊
|
|
208
|
+
interface IDummy {␊
|
|
209
|
+
}␊
|
|
210
|
+
␊
|
|
211
|
+
contract UsesAddress {␊
|
|
212
|
+
IDummy public constant MY_CONTRACT = IDummy(MY_ADDRESS);␊
|
|
213
|
+
}␊
|
|
214
|
+
␊
|
|
215
|
+
contract HasFunctionWithRequiredReturn {␊
|
|
216
|
+
struct S { uint x; }␊
|
|
217
|
+
function foo(S calldata s) internal pure returns (bool) {}␊
|
|
195
218
|
}`,
|
|
196
219
|
},
|
|
197
220
|
'contracts/test/NamespacedToModifyImported.sol': {
|
|
@@ -234,8 +257,8 @@ Generated by [AVA](https://avajs.dev).
|
|
|
234
257
|
pragma solidity 0.7.6;␊
|
|
235
258
|
␊
|
|
236
259
|
contract HasFunction {␊
|
|
237
|
-
|
|
238
|
-
|
|
260
|
+
␊
|
|
261
|
+
function foo() pure public returns (bool) {}␊
|
|
239
262
|
}␊
|
|
240
263
|
␊
|
|
241
264
|
contract UsingFunction is HasFunction {␊
|
|
Binary file
|
|
@@ -3,6 +3,7 @@ import { Node } from 'solidity-ast/node';
|
|
|
3
3
|
import { SolcInput, SolcOutput } from '../solc-api';
|
|
4
4
|
import { getStorageLocationAnnotation } from '../storage/namespace';
|
|
5
5
|
import { assert } from './assert';
|
|
6
|
+
import { FunctionDefinition } from 'solidity-ast';
|
|
6
7
|
|
|
7
8
|
const OUTPUT_SELECTION = {
|
|
8
9
|
'*': {
|
|
@@ -40,7 +41,6 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
40
41
|
|
|
41
42
|
const orig = Buffer.from(source.content, 'utf8');
|
|
42
43
|
|
|
43
|
-
const replacedIdentifiers = new Set<string>();
|
|
44
44
|
const modifications: Modification[] = [];
|
|
45
45
|
|
|
46
46
|
for (const node of output.sources[sourcePath].ast.nodes) {
|
|
@@ -60,6 +60,10 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
60
60
|
const contractNodes = contractDef.nodes;
|
|
61
61
|
for (const contractNode of contractNodes) {
|
|
62
62
|
switch (contractNode.nodeType) {
|
|
63
|
+
case 'FunctionDefinition': {
|
|
64
|
+
replaceFunction(contractNode, orig, modifications);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
63
67
|
case 'VariableDeclaration': {
|
|
64
68
|
// If variable is a constant, keep it since it may be referenced in a struct
|
|
65
69
|
if (contractNode.constant) {
|
|
@@ -69,7 +73,6 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
69
73
|
}
|
|
70
74
|
case 'ErrorDefinition':
|
|
71
75
|
case 'EventDefinition':
|
|
72
|
-
case 'FunctionDefinition':
|
|
73
76
|
case 'ModifierDefinition':
|
|
74
77
|
case 'UsingForDirective': {
|
|
75
78
|
// Replace with an enum based on astId (the original name is not needed, since nothing should reference it)
|
|
@@ -100,27 +103,30 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
100
103
|
break;
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
case 'FunctionDefinition': {
|
|
107
|
+
replaceFunction(node, orig, modifications);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// - VariableDeclaration and ErrorDefinition might be imported by other files, so they cannot be deleted.
|
|
106
112
|
// However, we need to remove their values to avoid referencing other deleted nodes.
|
|
107
|
-
// We do this by converting them to dummy enums
|
|
108
|
-
case 'UsingForDirective':
|
|
109
|
-
case 'ErrorDefinition':
|
|
110
|
-
case 'FunctionDefinition':
|
|
113
|
+
// We do this by converting them to dummy enums with the same name.
|
|
111
114
|
case 'VariableDeclaration': {
|
|
112
|
-
// If
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// should have failed if there were conflicts in the first place.
|
|
116
|
-
if ('name' in node && !replacedIdentifiers.has(node.name)) {
|
|
117
|
-
modifications.push(makeReplace(node, orig, toDummyEnumWithName(node.name)));
|
|
118
|
-
replacedIdentifiers.add(node.name);
|
|
119
|
-
} else {
|
|
120
|
-
modifications.push(makeReplace(node, orig, toDummyEnumWithAstId(node.id)));
|
|
115
|
+
// If variable is a constant, keep it since it may be referenced in a struct
|
|
116
|
+
if (node.constant) {
|
|
117
|
+
break;
|
|
121
118
|
}
|
|
119
|
+
// Otherwise, fall through to convert to dummy enum
|
|
120
|
+
}
|
|
121
|
+
case 'ErrorDefinition': {
|
|
122
|
+
modifications.push(makeReplace(node, orig, toDummyEnumWithName(node.name)));
|
|
122
123
|
break;
|
|
123
124
|
}
|
|
125
|
+
// - UsingForDirective isn't needed, but it might have NatSpec documentation which is not included in the AST.
|
|
126
|
+
// We convert it to a dummy enum to avoid orphaning any possible documentation.
|
|
127
|
+
case 'UsingForDirective':
|
|
128
|
+
modifications.push(makeReplace(node, orig, toDummyEnumWithAstId(node.id)));
|
|
129
|
+
break;
|
|
124
130
|
case 'EnumDefinition':
|
|
125
131
|
case 'ImportDirective':
|
|
126
132
|
case 'PragmaDirective':
|
|
@@ -158,6 +164,26 @@ function toDummyEnumWithAstId(astId: number) {
|
|
|
158
164
|
return `enum $astId_${astId}_${(Math.random() * 1e6).toFixed(0)} { dummy }`;
|
|
159
165
|
}
|
|
160
166
|
|
|
167
|
+
function replaceFunction(node: FunctionDefinition, orig: Buffer, modifications: Modification[]) {
|
|
168
|
+
if (node.kind === 'constructor') {
|
|
169
|
+
modifications.push(makeDelete(node, orig));
|
|
170
|
+
} else {
|
|
171
|
+
if (node.modifiers.length > 0) {
|
|
172
|
+
for (const modifier of node.modifiers) {
|
|
173
|
+
modifications.push(makeDelete(modifier, orig));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (node.returnParameters.parameters.length > 0) {
|
|
178
|
+
modifications.push(makeReplace(node.returnParameters, orig, '(bool)'));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (node.body) {
|
|
182
|
+
modifications.push(makeReplace(node.body, orig, '{}'));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
161
187
|
function getPositions(node: Node) {
|
|
162
188
|
const [start, length] = node.src.split(':').map(Number);
|
|
163
189
|
const end = start + length;
|
package/src/validate/run.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
StructDefinition,
|
|
7
7
|
TypeName,
|
|
8
8
|
UserDefinedTypeName,
|
|
9
|
+
VariableDeclaration,
|
|
9
10
|
} from 'solidity-ast';
|
|
10
11
|
import debug from '../utils/debug';
|
|
11
12
|
|
|
@@ -586,7 +587,7 @@ function* getInternalFunctionStorageErrors(
|
|
|
586
587
|
): Generator<ValidationError> {
|
|
587
588
|
// Note: Solidity does not allow annotations for non-public state variables, nor recursive types for public variables,
|
|
588
589
|
// so annotations cannot be used to skip these checks.
|
|
589
|
-
for (const variableDec of
|
|
590
|
+
for (const variableDec of getVariableDeclarations(contractOrStructDef, visitedNodeIds)) {
|
|
590
591
|
if (variableDec.typeName?.nodeType === 'FunctionTypeName' && variableDec.typeName.visibility === 'internal') {
|
|
591
592
|
// Find internal function types directly in this node's scope
|
|
592
593
|
yield {
|
|
@@ -608,6 +609,34 @@ function* getInternalFunctionStorageErrors(
|
|
|
608
609
|
}
|
|
609
610
|
}
|
|
610
611
|
|
|
612
|
+
/**
|
|
613
|
+
* Gets variables declared directly in a contract or in a struct definition.
|
|
614
|
+
*
|
|
615
|
+
* If this is a contract with struct definitions annotated with a storage location according to ERC-7201,
|
|
616
|
+
* then the struct members are also included.
|
|
617
|
+
*/
|
|
618
|
+
function* getVariableDeclarations(
|
|
619
|
+
contractOrStructDef: ContractDefinition | StructDefinition,
|
|
620
|
+
visitedNodeIds: Set<number>,
|
|
621
|
+
): Generator<VariableDeclaration, void, undefined> {
|
|
622
|
+
if (contractOrStructDef.nodeType === 'ContractDefinition') {
|
|
623
|
+
for (const node of contractOrStructDef.nodes) {
|
|
624
|
+
if (node.nodeType === 'VariableDeclaration') {
|
|
625
|
+
yield node;
|
|
626
|
+
} else if (
|
|
627
|
+
node.nodeType === 'StructDefinition' &&
|
|
628
|
+
getStorageLocationAnnotation(node) !== undefined &&
|
|
629
|
+
!visitedNodeIds.has(node.id)
|
|
630
|
+
) {
|
|
631
|
+
visitedNodeIds.add(node.id);
|
|
632
|
+
yield* getVariableDeclarations(node, visitedNodeIds);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
} else if (contractOrStructDef.nodeType === 'StructDefinition') {
|
|
636
|
+
yield* contractOrStructDef.members;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
611
640
|
/**
|
|
612
641
|
* Recursively traverse array and mapping types to find user-defined types (which may be struct references).
|
|
613
642
|
*/
|
package/src/validate.test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
assertUpgradeSafe,
|
|
9
9
|
ValidationOptions,
|
|
10
10
|
RunValidation,
|
|
11
|
+
ValidationErrors,
|
|
11
12
|
} from './validate';
|
|
12
13
|
import { solcInputOutputDecoder } from './src-decoder';
|
|
13
14
|
|
|
@@ -23,6 +24,7 @@ test.before(async t => {
|
|
|
23
24
|
'contracts/test/ValidationsNatspec.sol:HasNonEmptyConstructorNatspec1',
|
|
24
25
|
'contracts/test/Proxiable.sol:ChildOfProxiable',
|
|
25
26
|
'contracts/test/ValidationsUDVT.sol:ValidationsUDVT',
|
|
27
|
+
'contracts/test/ValidationsFunctionPointers.sol:InternalFunctionPointer',
|
|
26
28
|
];
|
|
27
29
|
|
|
28
30
|
t.context.validation = {} as RunValidation;
|
|
@@ -38,11 +40,21 @@ test.before(async t => {
|
|
|
38
40
|
}
|
|
39
41
|
});
|
|
40
42
|
|
|
41
|
-
function testValid(name: string, kind: ValidationOptions['kind'], valid: boolean) {
|
|
42
|
-
testOverride(name, kind, {}, valid);
|
|
43
|
+
function testValid(name: string, kind: ValidationOptions['kind'], valid: boolean, numExpectedErrors?: number) {
|
|
44
|
+
testOverride(name, kind, {}, valid, numExpectedErrors);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
function testOverride(
|
|
47
|
+
function testOverride(
|
|
48
|
+
name: string,
|
|
49
|
+
kind: ValidationOptions['kind'],
|
|
50
|
+
opts: ValidationOptions,
|
|
51
|
+
valid: boolean,
|
|
52
|
+
numExpectedErrors?: number,
|
|
53
|
+
) {
|
|
54
|
+
if (numExpectedErrors !== undefined && numExpectedErrors > 0 && valid) {
|
|
55
|
+
throw new Error('Cannot expect errors for a valid contract');
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
const optKeys = Object.keys(opts);
|
|
47
59
|
const describeOpts = optKeys.length > 0 ? '(' + optKeys.join(', ') + ')' : '';
|
|
48
60
|
const testName = [valid ? 'accepts' : 'rejects', kind, name, describeOpts].join(' ');
|
|
@@ -52,7 +64,10 @@ function testOverride(name: string, kind: ValidationOptions['kind'], opts: Valid
|
|
|
52
64
|
if (valid) {
|
|
53
65
|
t.notThrows(assertUpgSafe);
|
|
54
66
|
} else {
|
|
55
|
-
t.throws(assertUpgSafe);
|
|
67
|
+
const error = t.throws(assertUpgSafe) as ValidationErrors;
|
|
68
|
+
if (numExpectedErrors !== undefined) {
|
|
69
|
+
t.is(error.errors.length, numExpectedErrors);
|
|
70
|
+
}
|
|
56
71
|
}
|
|
57
72
|
});
|
|
58
73
|
}
|
|
@@ -140,18 +155,31 @@ testValid('TransitiveLibraryIsUnsafe', 'transparent', false);
|
|
|
140
155
|
testValid('contracts/test/ValidationsSameNameSafe.sol:SameName', 'transparent', true);
|
|
141
156
|
testValid('contracts/test/ValidationsSameNameUnsafe.sol:SameName', 'transparent', false);
|
|
142
157
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
158
|
+
test('ambiguous name', t => {
|
|
159
|
+
const error = t.throws(() => getContractVersion(t.context.validation, 'SameName'));
|
|
160
|
+
t.is(
|
|
161
|
+
error?.message,
|
|
162
|
+
'Contract SameName is ambiguous. Use one of the following:\n' +
|
|
163
|
+
'contracts/test/ValidationsSameNameSafe.sol:SameName\n' +
|
|
164
|
+
'contracts/test/ValidationsSameNameUnsafe.sol:SameName',
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
testValid('NamespacedExternalFunctionPointer', 'transparent', true);
|
|
169
|
+
testValid('NamespacedInternalFunctionPointer', 'transparent', false);
|
|
170
|
+
testValid('NamespacedInternalFunctionPointerUsed', 'transparent', false, 1);
|
|
171
|
+
testValid('StructInternalFunctionPointerUsed', 'transparent', false, 1);
|
|
172
|
+
testValid('NonNamespacedInternalFunctionPointer', 'transparent', true);
|
|
173
|
+
testValid('NamespacedImpliedInternalFunctionPointer', 'transparent', false);
|
|
146
174
|
testOverride(
|
|
147
|
-
'
|
|
175
|
+
'NamespacedImpliedInternalFunctionPointer',
|
|
148
176
|
'transparent',
|
|
149
177
|
{ unsafeAllow: ['internal-function-storage'] },
|
|
150
178
|
true,
|
|
151
179
|
);
|
|
152
180
|
|
|
153
181
|
testValid('UsesStandaloneStructInternalFn', 'transparent', false);
|
|
154
|
-
testValid('
|
|
182
|
+
testValid('NamespacedUsesStandaloneStructInternalFn', 'transparent', false);
|
|
155
183
|
testValid('RecursiveStructInternalFn', 'transparent', false);
|
|
156
184
|
testValid('MappingRecursiveStructInternalFn', 'transparent', false);
|
|
157
185
|
testValid('ArrayRecursiveStructInternalFn', 'transparent', false);
|
|
@@ -163,12 +191,4 @@ testValid('InternalFunctionPointer', 'transparent', false);
|
|
|
163
191
|
testValid('ImpliedInternalFunctionPointer', 'transparent', false);
|
|
164
192
|
testOverride('ImpliedInternalFunctionPointer', 'transparent', { unsafeAllow: ['internal-function-storage'] }, true);
|
|
165
193
|
|
|
166
|
-
|
|
167
|
-
const error = t.throws(() => getContractVersion(t.context.validation, 'SameName'));
|
|
168
|
-
t.is(
|
|
169
|
-
error?.message,
|
|
170
|
-
'Contract SameName is ambiguous. Use one of the following:\n' +
|
|
171
|
-
'contracts/test/ValidationsSameNameSafe.sol:SameName\n' +
|
|
172
|
-
'contracts/test/ValidationsSameNameUnsafe.sol:SameName',
|
|
173
|
-
);
|
|
174
|
-
});
|
|
194
|
+
testValid('FunctionWithInternalFunctionPointer', 'transparent', true);
|