@openzeppelin/upgrades-core 1.34.4 → 1.35.1
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 +9 -0
- package/dist/utils/make-namespaced.d.ts +8 -3
- package/dist/utils/make-namespaced.d.ts.map +1 -1
- package/dist/utils/make-namespaced.js +92 -17
- package/dist/utils/make-namespaced.js.map +1 -1
- package/dist/utils/make-namespaced.test.js +7 -2
- package/dist/utils/make-namespaced.test.js.map +1 -1
- package/dist/utils/slang/trivia.d.ts +9 -0
- package/dist/utils/slang/trivia.d.ts.map +1 -0
- package/dist/utils/slang/trivia.js +23 -0
- package/dist/utils/slang/trivia.js.map +1 -0
- package/package.json +2 -1
- package/src/utils/make-namespaced.test.ts +12 -1
- package/src/utils/make-namespaced.test.ts.md +309 -16
- package/src/utils/make-namespaced.test.ts.snap +0 -0
- package/src/utils/make-namespaced.ts +111 -24
- package/src/utils/slang/trivia.ts +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.35.1 (2024-08-13)
|
|
4
|
+
|
|
5
|
+
- Fix Hardhat compile error when `fallback` or `receive` functions are present. ([#1060](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1060))
|
|
6
|
+
|
|
7
|
+
## 1.35.0 (2024-07-31)
|
|
8
|
+
|
|
9
|
+
- Fix Hardhat compile error when public variables are used to implement interface functions. ([#1055](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1055))
|
|
10
|
+
- Remove non-struct NatSpec from Hardhat compilation step for namespaced storage layout validations. ([#1051](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1051))
|
|
11
|
+
|
|
3
12
|
## 1.34.4 (2024-07-22)
|
|
4
13
|
|
|
5
14
|
- Fix Hardhat compile error when return parameter names are documented as param. ([#1050](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/1050))
|
|
@@ -5,15 +5,20 @@ import { SolcInput, SolcOutput } from '../solc-api';
|
|
|
5
5
|
*
|
|
6
6
|
* This makes the following modifications to the input:
|
|
7
7
|
* - Adds a state variable for each namespaced struct definition
|
|
8
|
-
* - For each contract, for all node types that are not needed for storage layout or may
|
|
8
|
+
* - For each contract, for all node types that are not needed for storage layout or may call functions and constructors, converts them to dummy enums with random id
|
|
9
9
|
* - Converts all using for directives (at file level and in contracts) to dummy enums with random id (do not delete them to avoid orphaning possible NatSpec documentation)
|
|
10
|
-
* - Converts all custom errors
|
|
10
|
+
* - Converts all custom errors and constants (at file level) to dummy enums with the same name (do not delete them since they might be imported by other files)
|
|
11
|
+
* - Replaces functions as follows:
|
|
12
|
+
* - For regular function and free function, keep declarations since they may be referenced by constants (free functions may also be imported by other files). But simplify compilation by removing modifiers and body, and replace return parameters with bools which can be default initialized.
|
|
13
|
+
* - Constructors are not needed, since we removed anything that may call constructors. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
14
|
+
* - Fallback and receive functions are not needed, since they don't have signatures. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
11
15
|
*
|
|
12
16
|
* Also sets the outputSelection to only include storageLayout and ast, since the other outputs are not needed.
|
|
13
17
|
*
|
|
14
18
|
* @param input The original solc input.
|
|
15
19
|
* @param output The original solc output.
|
|
20
|
+
* @param solcVersion The version of the solc compiler that was originally used to compile the input.
|
|
16
21
|
* @returns The modified solc input with storage layout that includes namespaced type information.
|
|
17
22
|
*/
|
|
18
|
-
export declare function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcInput;
|
|
23
|
+
export declare function makeNamespacedInput(input: SolcInput, output: SolcOutput, solcVersion?: string): SolcInput;
|
|
19
24
|
//# sourceMappingURL=make-namespaced.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-namespaced.d.ts","sourceRoot":"","sources":["../../src/utils/make-namespaced.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAYpD
|
|
1
|
+
{"version":3,"file":"make-namespaced.d.ts","sourceRoot":"","sources":["../../src/utils/make-namespaced.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAYpD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAgIzG"}
|
|
@@ -16,17 +16,22 @@ const OUTPUT_SELECTION = {
|
|
|
16
16
|
*
|
|
17
17
|
* This makes the following modifications to the input:
|
|
18
18
|
* - Adds a state variable for each namespaced struct definition
|
|
19
|
-
* - For each contract, for all node types that are not needed for storage layout or may
|
|
19
|
+
* - For each contract, for all node types that are not needed for storage layout or may call functions and constructors, converts them to dummy enums with random id
|
|
20
20
|
* - Converts all using for directives (at file level and in contracts) to dummy enums with random id (do not delete them to avoid orphaning possible NatSpec documentation)
|
|
21
|
-
* - Converts all custom errors
|
|
21
|
+
* - Converts all custom errors and constants (at file level) to dummy enums with the same name (do not delete them since they might be imported by other files)
|
|
22
|
+
* - Replaces functions as follows:
|
|
23
|
+
* - For regular function and free function, keep declarations since they may be referenced by constants (free functions may also be imported by other files). But simplify compilation by removing modifiers and body, and replace return parameters with bools which can be default initialized.
|
|
24
|
+
* - Constructors are not needed, since we removed anything that may call constructors. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
25
|
+
* - Fallback and receive functions are not needed, since they don't have signatures. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
22
26
|
*
|
|
23
27
|
* Also sets the outputSelection to only include storageLayout and ast, since the other outputs are not needed.
|
|
24
28
|
*
|
|
25
29
|
* @param input The original solc input.
|
|
26
30
|
* @param output The original solc output.
|
|
31
|
+
* @param solcVersion The version of the solc compiler that was originally used to compile the input.
|
|
27
32
|
* @returns The modified solc input with storage layout that includes namespaced type information.
|
|
28
33
|
*/
|
|
29
|
-
function makeNamespacedInput(input, output) {
|
|
34
|
+
function makeNamespacedInput(input, output, solcVersion) {
|
|
30
35
|
const modifiedSources = {};
|
|
31
36
|
for (const [sourcePath] of Object.entries(input.sources)) {
|
|
32
37
|
const source = input.sources[sourcePath];
|
|
@@ -40,6 +45,11 @@ function makeNamespacedInput(input, output) {
|
|
|
40
45
|
switch (node.nodeType) {
|
|
41
46
|
case 'ContractDefinition': {
|
|
42
47
|
const contractDef = node;
|
|
48
|
+
// Mark contracts as abstract, since state variables are converted to dummy enums
|
|
49
|
+
// which would not generate public getters for inherited interface functions
|
|
50
|
+
if (contractDef.contractKind === 'contract' && !contractDef.abstract) {
|
|
51
|
+
modifications.push(makeInsertBefore(contractDef, 'abstract '));
|
|
52
|
+
}
|
|
43
53
|
// Remove any calls to parent constructors from the inheritance list
|
|
44
54
|
const inherits = contractDef.baseContracts;
|
|
45
55
|
for (const inherit of inherits) {
|
|
@@ -131,10 +141,59 @@ function makeNamespacedInput(input, output) {
|
|
|
131
141
|
}
|
|
132
142
|
}
|
|
133
143
|
}
|
|
134
|
-
|
|
144
|
+
const modifiedSource = tryRemoveNonStructNatSpec(getModifiedSource(orig, modifications), solcVersion);
|
|
145
|
+
modifiedSources[sourcePath] = { ...source, content: modifiedSource };
|
|
135
146
|
}
|
|
136
147
|
return { ...input, sources: modifiedSources, settings: { ...input.settings, outputSelection: OUTPUT_SELECTION } };
|
|
137
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* If Slang is supported for the current platform and we have the compiler version available,
|
|
151
|
+
* use Slang to parse and remove all NatSpec comments that do not precede a struct definition and return the modified content.
|
|
152
|
+
*
|
|
153
|
+
* Otherwise, return the original content.
|
|
154
|
+
*/
|
|
155
|
+
function tryRemoveNonStructNatSpec(origContent, solcVersion) {
|
|
156
|
+
const natSpecRemovals = [];
|
|
157
|
+
if (solcVersion !== undefined && tryRequire('@nomicfoundation/slang')) {
|
|
158
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
159
|
+
const { Language } = require('@nomicfoundation/slang/language');
|
|
160
|
+
const { NonterminalKind, TerminalKind } = require('@nomicfoundation/slang/kinds');
|
|
161
|
+
const { TerminalNode } = require('@nomicfoundation/slang/cst');
|
|
162
|
+
const { isTrivia } = require('./slang/trivia');
|
|
163
|
+
/* eslint-enable @typescript-eslint/no-var-requires */
|
|
164
|
+
const language = new Language(solcVersion);
|
|
165
|
+
const parseOutput = language.parse(NonterminalKind.SourceUnit, origContent);
|
|
166
|
+
const cursor = parseOutput.createTreeCursor();
|
|
167
|
+
while (cursor.goToNextTerminalWithKinds([TerminalKind.MultiLineNatSpecComment, TerminalKind.SingleLineNatSpecComment])) {
|
|
168
|
+
// Lookahead to determine if the next non-trivia node is the struct keyword.
|
|
169
|
+
// If so, this NatSpec is part of the struct definition and should not be removed.
|
|
170
|
+
const lookaheadCursor = cursor.clone();
|
|
171
|
+
while (lookaheadCursor.goToNextTerminal() && isTrivia(lookaheadCursor.node())) {
|
|
172
|
+
// skip over trivia nodes
|
|
173
|
+
}
|
|
174
|
+
if (lookaheadCursor.node().kind === TerminalKind.StructKeyword) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const triviaNode = cursor.node();
|
|
178
|
+
(0, assert_1.assert)(triviaNode instanceof TerminalNode);
|
|
179
|
+
natSpecRemovals.push(makeDeleteRange(cursor.textRange.start.utf8, cursor.textRange.end.utf8));
|
|
180
|
+
}
|
|
181
|
+
return getModifiedSource(Buffer.from(origContent, 'utf8'), natSpecRemovals);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
return origContent;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function tryRequire(id) {
|
|
188
|
+
try {
|
|
189
|
+
require(id);
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
// do nothing
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
138
197
|
function toDummyEnumWithName(name) {
|
|
139
198
|
return `enum ${name} { dummy }`;
|
|
140
199
|
}
|
|
@@ -142,21 +201,30 @@ function toDummyEnumWithAstId(astId) {
|
|
|
142
201
|
return `enum $astId_${astId}_${(Math.random() * 1e6).toFixed(0)} { dummy }`;
|
|
143
202
|
}
|
|
144
203
|
function replaceFunction(node, orig, modifications) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
204
|
+
switch (node.kind) {
|
|
205
|
+
case 'freeFunction':
|
|
206
|
+
case 'function': {
|
|
207
|
+
if (node.modifiers.length > 0) {
|
|
208
|
+
for (const modifier of node.modifiers) {
|
|
209
|
+
modifications.push(makeDelete(modifier, orig));
|
|
210
|
+
}
|
|
152
211
|
}
|
|
212
|
+
if (node.returnParameters.parameters.length > 0) {
|
|
213
|
+
modifications.push(makeReplace(node.returnParameters, orig, `(${node.returnParameters.parameters.map(param => toReturnParameterReplacement(param)).join(', ')})`));
|
|
214
|
+
}
|
|
215
|
+
if (node.body) {
|
|
216
|
+
modifications.push(makeReplace(node.body, orig, '{}'));
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
153
219
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
220
|
+
case 'constructor':
|
|
221
|
+
case 'fallback':
|
|
222
|
+
case 'receive': {
|
|
223
|
+
modifications.push(makeReplace(node, orig, toDummyEnumWithAstId(node.id)));
|
|
224
|
+
break;
|
|
159
225
|
}
|
|
226
|
+
default:
|
|
227
|
+
return (0, assert_1.assertUnreachable)(node.kind);
|
|
160
228
|
}
|
|
161
229
|
}
|
|
162
230
|
function toReturnParameterReplacement(param) {
|
|
@@ -177,6 +245,10 @@ function makeReplace(node, orig, text) {
|
|
|
177
245
|
const { start, end } = makeDelete(node, orig);
|
|
178
246
|
return { start, end, text };
|
|
179
247
|
}
|
|
248
|
+
function makeInsertBefore(node, text) {
|
|
249
|
+
const { start } = getPositions(node);
|
|
250
|
+
return { start: start, end: start, text };
|
|
251
|
+
}
|
|
180
252
|
function makeInsertAfter(node, text) {
|
|
181
253
|
const { end } = getPositions(node);
|
|
182
254
|
return { start: end, end, text };
|
|
@@ -193,7 +265,10 @@ function makeDelete(node, orig) {
|
|
|
193
265
|
end += 1;
|
|
194
266
|
}
|
|
195
267
|
}
|
|
196
|
-
return
|
|
268
|
+
return makeDeleteRange(positions.start, end);
|
|
269
|
+
}
|
|
270
|
+
function makeDeleteRange(start, end) {
|
|
271
|
+
return { start, end };
|
|
197
272
|
}
|
|
198
273
|
function getModifiedSource(orig, modifications) {
|
|
199
274
|
let result = '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-namespaced.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"make-namespaced.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,18 +11,22 @@ const make_namespaced_1 = require("./make-namespaced");
|
|
|
11
11
|
const origBuildInfo = await hardhat_1.artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
|
|
12
12
|
await testMakeNamespaced(origBuildInfo, t, '0.8.20');
|
|
13
13
|
});
|
|
14
|
+
(0, ava_1.default)('make namespaced input - keep all natspec', async (t) => {
|
|
15
|
+
const origBuildInfo = await hardhat_1.artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
|
|
16
|
+
await testMakeNamespaced(origBuildInfo, t, '0.8.20', true);
|
|
17
|
+
});
|
|
14
18
|
(0, ava_1.default)('make namespaced input - solc 0.7', async (t) => {
|
|
15
19
|
// The nameNamespacedInput function must work for different solc versions, since it is called before we check whether namespaces are used with solc >= 0.8.20
|
|
16
20
|
const origBuildInfo = await hardhat_1.artifacts.getBuildInfo('contracts/test/NamespacedToModify07.sol:HasFunction');
|
|
17
21
|
await testMakeNamespaced(origBuildInfo, t, '0.7.6');
|
|
18
22
|
});
|
|
19
|
-
async function testMakeNamespaced(origBuildInfo, t, solcVersion) {
|
|
23
|
+
async function testMakeNamespaced(origBuildInfo, t, solcVersion, keepAllNatSpec = false) {
|
|
20
24
|
if (origBuildInfo === undefined) {
|
|
21
25
|
throw new Error('Build info not found');
|
|
22
26
|
}
|
|
23
27
|
// Inefficient, but we want to test that we don't actually modify the original input object
|
|
24
28
|
const origInput = JSON.parse(JSON.stringify(origBuildInfo.input));
|
|
25
|
-
const modifiedInput = (0, make_namespaced_1.makeNamespacedInput)(origBuildInfo.input, origBuildInfo.output);
|
|
29
|
+
const modifiedInput = (0, make_namespaced_1.makeNamespacedInput)(origBuildInfo.input, origBuildInfo.output, keepAllNatSpec ? undefined : origBuildInfo.solcVersion);
|
|
26
30
|
// Run hardhat compile on the modified input and make sure it has no errors
|
|
27
31
|
const modifiedOutput = await hardhatCompile(modifiedInput, solcVersion);
|
|
28
32
|
t.is(modifiedOutput.errors, undefined, JSON.stringify(modifiedInput.sources, null, 2));
|
|
@@ -37,6 +41,7 @@ function normalizeIdentifiers(input) {
|
|
|
37
41
|
source.content = source.content
|
|
38
42
|
.replace(/\$MainStorage_\d{1,6}/g, '$MainStorage_random')
|
|
39
43
|
.replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random')
|
|
44
|
+
.replace(/\$StorageWithComment_\d{1,6}/g, '$StorageWithComment_random')
|
|
40
45
|
.replace(/\$astId_\d+_\d{1,6}/g, '$astId_id_random');
|
|
41
46
|
}
|
|
42
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-namespaced.test.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAA6C;AAC7C,qCAAyC;AACzC,iEAI0C;AAE1C,uDAAwD;AAKxD,IAAA,aAAI,EAAC,uBAAuB,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACtC,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,uDAAuD,CAAC,CAAC;IAC5G,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,kCAAkC,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACjD,6JAA6J;IAC7J,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,qDAAqD,CAAC,CAAC;IAC1G,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,kBAAkB,CAC/B,aAAoC,EACpC,CAA4B,EAC5B,WAAmB;
|
|
1
|
+
{"version":3,"file":"make-namespaced.test.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Node } from '@nomicfoundation/slang/cst';
|
|
2
|
+
/**
|
|
3
|
+
* Returns true if the node is a trivia terminal (whitespace or comment or NatSpec)
|
|
4
|
+
*
|
|
5
|
+
* CAUTION: This must be imported dynamically.
|
|
6
|
+
* Only import this file if Slang is supported on the current platform, otherwise an error will be thrown on import.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isTrivia(node: Node): boolean;
|
|
9
|
+
//# sourceMappingURL=trivia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trivia.d.ts","sourceRoot":"","sources":["../../../src/utils/slang/trivia.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAgB,MAAM,4BAA4B,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,WAElC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isTrivia = isTrivia;
|
|
4
|
+
const kinds_1 = require("@nomicfoundation/slang/kinds");
|
|
5
|
+
const cst_1 = require("@nomicfoundation/slang/cst");
|
|
6
|
+
/**
|
|
7
|
+
* Returns true if the node is a trivia terminal (whitespace or comment or NatSpec)
|
|
8
|
+
*
|
|
9
|
+
* CAUTION: This must be imported dynamically.
|
|
10
|
+
* Only import this file if Slang is supported on the current platform, otherwise an error will be thrown on import.
|
|
11
|
+
*/
|
|
12
|
+
function isTrivia(node) {
|
|
13
|
+
return node instanceof cst_1.TerminalNode && isTriviaKind(node.kind);
|
|
14
|
+
}
|
|
15
|
+
function isTriviaKind(kind) {
|
|
16
|
+
return (kind === kinds_1.TerminalKind.EndOfLine ||
|
|
17
|
+
kind === kinds_1.TerminalKind.MultiLineComment ||
|
|
18
|
+
kind === kinds_1.TerminalKind.MultiLineNatSpecComment ||
|
|
19
|
+
kind === kinds_1.TerminalKind.SingleLineComment ||
|
|
20
|
+
kind === kinds_1.TerminalKind.SingleLineNatSpecComment ||
|
|
21
|
+
kind === kinds_1.TerminalKind.Whitespace);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=trivia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trivia.js","sourceRoot":"","sources":["../../../src/utils/slang/trivia.ts"],"names":[],"mappings":";;AASA,4BAEC;AAXD,wDAA4D;AAC5D,oDAAgE;AAEhE;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,IAAU;IACjC,OAAO,IAAI,YAAY,kBAAY,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,YAAY,CAAC,IAAkB;IACtC,OAAO,CACL,IAAI,KAAK,oBAAY,CAAC,SAAS;QAC/B,IAAI,KAAK,oBAAY,CAAC,gBAAgB;QACtC,IAAI,KAAK,oBAAY,CAAC,uBAAuB;QAC7C,IAAI,KAAK,oBAAY,CAAC,iBAAiB;QACvC,IAAI,KAAK,oBAAY,CAAC,wBAAwB;QAC9C,IAAI,KAAK,oBAAY,CAAC,UAAU,CACjC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/upgrades-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"typescript": "^5.0.0"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
+
"@nomicfoundation/slang": "^0.15.1",
|
|
64
65
|
"cbor": "^9.0.0",
|
|
65
66
|
"chalk": "^4.1.0",
|
|
66
67
|
"compare-versions": "^6.0.0",
|
|
@@ -16,6 +16,11 @@ test('make namespaced input', async t => {
|
|
|
16
16
|
await testMakeNamespaced(origBuildInfo, t, '0.8.20');
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
test('make namespaced input - keep all natspec', async t => {
|
|
20
|
+
const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
|
|
21
|
+
await testMakeNamespaced(origBuildInfo, t, '0.8.20', true);
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
test('make namespaced input - solc 0.7', async t => {
|
|
20
25
|
// The nameNamespacedInput function must work for different solc versions, since it is called before we check whether namespaces are used with solc >= 0.8.20
|
|
21
26
|
const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModify07.sol:HasFunction');
|
|
@@ -26,6 +31,7 @@ async function testMakeNamespaced(
|
|
|
26
31
|
origBuildInfo: BuildInfo | undefined,
|
|
27
32
|
t: ExecutionContext<unknown>,
|
|
28
33
|
solcVersion: string,
|
|
34
|
+
keepAllNatSpec = false,
|
|
29
35
|
) {
|
|
30
36
|
if (origBuildInfo === undefined) {
|
|
31
37
|
throw new Error('Build info not found');
|
|
@@ -34,7 +40,11 @@ async function testMakeNamespaced(
|
|
|
34
40
|
// Inefficient, but we want to test that we don't actually modify the original input object
|
|
35
41
|
const origInput = JSON.parse(JSON.stringify(origBuildInfo.input));
|
|
36
42
|
|
|
37
|
-
const modifiedInput = makeNamespacedInput(
|
|
43
|
+
const modifiedInput = makeNamespacedInput(
|
|
44
|
+
origBuildInfo.input,
|
|
45
|
+
origBuildInfo.output,
|
|
46
|
+
keepAllNatSpec ? undefined : origBuildInfo.solcVersion,
|
|
47
|
+
);
|
|
38
48
|
|
|
39
49
|
// Run hardhat compile on the modified input and make sure it has no errors
|
|
40
50
|
const modifiedOutput = await hardhatCompile(modifiedInput, solcVersion);
|
|
@@ -53,6 +63,7 @@ function normalizeIdentifiers(input: SolcInput): void {
|
|
|
53
63
|
source.content = source.content
|
|
54
64
|
.replace(/\$MainStorage_\d{1,6}/g, '$MainStorage_random')
|
|
55
65
|
.replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random')
|
|
66
|
+
.replace(/\$StorageWithComment_\d{1,6}/g, '$StorageWithComment_random')
|
|
56
67
|
.replace(/\$astId_\d+_\d{1,6}/g, '$astId_id_random');
|
|
57
68
|
}
|
|
58
69
|
}
|
|
@@ -32,7 +32,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
32
32
|
content: `// SPDX-License-Identifier: MIT␊
|
|
33
33
|
pragma solidity ^0.8.20;␊
|
|
34
34
|
␊
|
|
35
|
-
contract Example {␊
|
|
35
|
+
abstract contract Example {␊
|
|
36
36
|
/// @custom:storage-location erc7201:example.main␊
|
|
37
37
|
struct MainStorage {␊
|
|
38
38
|
uint256 x;␊
|
|
@@ -44,6 +44,266 @@ Generated by [AVA](https://avajs.dev).
|
|
|
44
44
|
uint256 a;␊
|
|
45
45
|
uint256 b;␊
|
|
46
46
|
} SecondaryStorage $SecondaryStorage_random;␊
|
|
47
|
+
␊
|
|
48
|
+
/// @custom:storage-location erc7201:example.with.following.comment␊
|
|
49
|
+
// some comment␊
|
|
50
|
+
struct StorageWithComment {␊
|
|
51
|
+
uint256 a;␊
|
|
52
|
+
uint256 b;␊
|
|
53
|
+
} StorageWithComment $StorageWithComment_random;␊
|
|
54
|
+
␊
|
|
55
|
+
␊
|
|
56
|
+
function foo() public {}␊
|
|
57
|
+
␊
|
|
58
|
+
␊
|
|
59
|
+
function foo1(uint a) public {}␊
|
|
60
|
+
␊
|
|
61
|
+
␊
|
|
62
|
+
function foo2(uint a) internal {}␊
|
|
63
|
+
struct MyStruct { uint b; }␊
|
|
64
|
+
␊
|
|
65
|
+
// keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~bytes32(uint256(0xff));␊
|
|
66
|
+
bytes32 private constant MAIN_STORAGE_LOCATION =␊
|
|
67
|
+
0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500;␊
|
|
68
|
+
␊
|
|
69
|
+
function _getMainStorage() private pure returns (bool $) {}␊
|
|
70
|
+
␊
|
|
71
|
+
function _getXTimesY() internal view returns (bool) {}␊
|
|
72
|
+
␊
|
|
73
|
+
␊
|
|
74
|
+
␊
|
|
75
|
+
␊
|
|
76
|
+
enum $astId_id_random { dummy }␊
|
|
77
|
+
␊
|
|
78
|
+
// standalone doc␊
|
|
79
|
+
␊
|
|
80
|
+
␊
|
|
81
|
+
␊
|
|
82
|
+
␊
|
|
83
|
+
function foo3() public {}␊
|
|
84
|
+
␊
|
|
85
|
+
␊
|
|
86
|
+
function foo4() public {}␊
|
|
87
|
+
␊
|
|
88
|
+
␊
|
|
89
|
+
enum $astId_id_random { dummy }␊
|
|
90
|
+
␊
|
|
91
|
+
enum $astId_id_random { dummy }␊
|
|
92
|
+
enum $astId_id_random { dummy }␊
|
|
93
|
+
enum $astId_id_random { dummy }␊
|
|
94
|
+
enum $astId_id_random { dummy }␊
|
|
95
|
+
enum $astId_id_random { dummy }␊
|
|
96
|
+
}␊
|
|
97
|
+
␊
|
|
98
|
+
abstract contract HasFunction {␊
|
|
99
|
+
␊
|
|
100
|
+
enum $astId_id_random { dummy }␊
|
|
101
|
+
␊
|
|
102
|
+
function foo() pure public returns (bool) {}␊
|
|
103
|
+
}␊
|
|
104
|
+
␊
|
|
105
|
+
abstract contract UsingFunction is HasFunction {␊
|
|
106
|
+
enum $astId_id_random { dummy }␊
|
|
107
|
+
}␊
|
|
108
|
+
␊
|
|
109
|
+
function FreeFunctionUsingSelector() pure returns (bool) {}␊
|
|
110
|
+
␊
|
|
111
|
+
bytes4 constant CONSTANT_USING_SELECTOR = HasFunction.foo.selector;␊
|
|
112
|
+
␊
|
|
113
|
+
library Lib {␊
|
|
114
|
+
function usingSelector() pure public returns (bool) {}␊
|
|
115
|
+
␊
|
|
116
|
+
function plusOne(uint x) pure public returns (bool) {}␊
|
|
117
|
+
}␊
|
|
118
|
+
␊
|
|
119
|
+
abstract contract Consumer {␊
|
|
120
|
+
enum $astId_id_random { dummy }␊
|
|
121
|
+
␊
|
|
122
|
+
function usingFreeFunction() pure public returns (bool) {}␊
|
|
123
|
+
␊
|
|
124
|
+
function usingConstant() pure public returns (bool) {}␊
|
|
125
|
+
␊
|
|
126
|
+
function usingLibraryFunction() pure public returns (bool) {}␊
|
|
127
|
+
}␊
|
|
128
|
+
␊
|
|
129
|
+
abstract contract HasConstantWithSelector {␊
|
|
130
|
+
bytes4 constant CONTRACT_CONSTANT_USING_SELECTOR = HasFunction.foo.selector;␊
|
|
131
|
+
}␊
|
|
132
|
+
␊
|
|
133
|
+
function plusTwo(uint x) pure returns (bool) {}␊
|
|
134
|
+
␊
|
|
135
|
+
␊
|
|
136
|
+
␊
|
|
137
|
+
␊
|
|
138
|
+
function plusThree(uint x) pure returns (bool) {}␊
|
|
139
|
+
␊
|
|
140
|
+
␊
|
|
141
|
+
␊
|
|
142
|
+
␊
|
|
143
|
+
function plusThree(uint x, uint y) pure returns (bool) {}␊
|
|
144
|
+
␊
|
|
145
|
+
function originallyNoDocumentation() pure {}␊
|
|
146
|
+
␊
|
|
147
|
+
␊
|
|
148
|
+
enum $astId_id_random { dummy }␊
|
|
149
|
+
␊
|
|
150
|
+
abstract contract UsingForDirectives {␊
|
|
151
|
+
enum $astId_id_random { dummy }␊
|
|
152
|
+
␊
|
|
153
|
+
function usingFor(uint x) pure public returns (bool) {}␊
|
|
154
|
+
}␊
|
|
155
|
+
␊
|
|
156
|
+
␊
|
|
157
|
+
enum FreeEnum { MyEnum }␊
|
|
158
|
+
␊
|
|
159
|
+
␊
|
|
160
|
+
enum CustomErrorOutsideContract { dummy }␊
|
|
161
|
+
␊
|
|
162
|
+
int8 constant MAX_SIZE_C = 2;␊
|
|
163
|
+
␊
|
|
164
|
+
abstract contract StructArrayUsesConstant {␊
|
|
165
|
+
uint16 private constant MAX_SIZE = 10;␊
|
|
166
|
+
␊
|
|
167
|
+
struct NotNamespaced {␊
|
|
168
|
+
uint16 a;␊
|
|
169
|
+
uint256[MAX_SIZE] b;␊
|
|
170
|
+
uint256[MAX_SIZE_C] c;␊
|
|
171
|
+
}␊
|
|
172
|
+
␊
|
|
173
|
+
/// @custom:storage-location erc7201:uses.constant␊
|
|
174
|
+
struct MainStorage {␊
|
|
175
|
+
uint256 x;␊
|
|
176
|
+
uint256[MAX_SIZE] y;␊
|
|
177
|
+
uint256[MAX_SIZE_C] c;␊
|
|
178
|
+
} MainStorage $MainStorage_random;␊
|
|
179
|
+
}␊
|
|
180
|
+
␊
|
|
181
|
+
address constant MY_ADDRESS = address(0);␊
|
|
182
|
+
uint constant CONVERTED_ADDRESS = uint160(MY_ADDRESS);␊
|
|
183
|
+
␊
|
|
184
|
+
interface IDummy {␊
|
|
185
|
+
}␊
|
|
186
|
+
␊
|
|
187
|
+
abstract contract UsesAddress {␊
|
|
188
|
+
IDummy public constant MY_CONTRACT = IDummy(MY_ADDRESS);␊
|
|
189
|
+
}␊
|
|
190
|
+
␊
|
|
191
|
+
abstract contract HasFunctionWithRequiredReturn {␊
|
|
192
|
+
struct S { uint x; }␊
|
|
193
|
+
function foo(S calldata s) internal pure returns (bool) {}␊
|
|
194
|
+
}␊
|
|
195
|
+
␊
|
|
196
|
+
␊
|
|
197
|
+
function hasMultipleReturns() pure returns (bool, bool) {}␊
|
|
198
|
+
␊
|
|
199
|
+
␊
|
|
200
|
+
function hasMultipleNamedReturns() pure returns (bool a, bool b) {}␊
|
|
201
|
+
␊
|
|
202
|
+
␊
|
|
203
|
+
function hasReturnsDocumentedAsParams() pure returns (bool a, bool b) {}␊
|
|
204
|
+
␊
|
|
205
|
+
abstract contract HasNatSpecWithMultipleReturns {␊
|
|
206
|
+
␊
|
|
207
|
+
function hasMultipleReturnsInContract() public pure returns (bool, bool) {}␊
|
|
208
|
+
␊
|
|
209
|
+
␊
|
|
210
|
+
function hasMultipleNamedReturnsInContract() public pure returns (bool a, bool b) {}␊
|
|
211
|
+
␊
|
|
212
|
+
␊
|
|
213
|
+
function hasReturnsDocumentedAsParamsInContract() public pure returns (bool a, bool b) {}␊
|
|
214
|
+
}␊
|
|
215
|
+
␊
|
|
216
|
+
interface IHasExternalViewFunction {␊
|
|
217
|
+
function foo() external view returns (bool);␊
|
|
218
|
+
}␊
|
|
219
|
+
␊
|
|
220
|
+
abstract contract HasExternalViewFunction is IHasExternalViewFunction {␊
|
|
221
|
+
// This generates a getter function that conforms to the interface␊
|
|
222
|
+
enum $astId_id_random { dummy }␊
|
|
223
|
+
␊
|
|
224
|
+
// References a selector in an interface␊
|
|
225
|
+
bytes4 constant USING_INTERFACE_FUNCTION_SELECTOR = IHasExternalViewFunction.foo.selector;␊
|
|
226
|
+
␊
|
|
227
|
+
// References a getter generated for a public variable␊
|
|
228
|
+
enum $astId_id_random { dummy }␊
|
|
229
|
+
}␊
|
|
230
|
+
␊
|
|
231
|
+
abstract contract DeploysContractToImmutable {␊
|
|
232
|
+
enum $astId_id_random { dummy }␊
|
|
233
|
+
}␊
|
|
234
|
+
␊
|
|
235
|
+
abstract contract HasSpecialFunctions {␊
|
|
236
|
+
␊
|
|
237
|
+
␊
|
|
238
|
+
enum $astId_id_random { dummy }␊
|
|
239
|
+
␊
|
|
240
|
+
enum $astId_id_random { dummy }␊
|
|
241
|
+
␊
|
|
242
|
+
// Regular function but payable␊
|
|
243
|
+
function hasPayable() public payable {}␊
|
|
244
|
+
␊
|
|
245
|
+
bytes4 constant PAYABLE_SELECTOR = this.hasPayable.selector;␊
|
|
246
|
+
}`,
|
|
247
|
+
},
|
|
248
|
+
'contracts/test/NamespacedToModifyImported.sol': {
|
|
249
|
+
content: `// SPDX-License-Identifier: MIT␊
|
|
250
|
+
pragma solidity ^0.8.20;␊
|
|
251
|
+
␊
|
|
252
|
+
import {CONSTANT_USING_SELECTOR, plusTwo, plusThree, CustomErrorOutsideContract} from "./NamespacedToModify.sol";␊
|
|
253
|
+
␊
|
|
254
|
+
abstract contract Example {}␊
|
|
255
|
+
`,
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
## make namespaced input - keep all natspec
|
|
261
|
+
|
|
262
|
+
> Snapshot 1
|
|
263
|
+
|
|
264
|
+
{
|
|
265
|
+
language: 'Solidity',
|
|
266
|
+
settings: {
|
|
267
|
+
evmVersion: 'paris',
|
|
268
|
+
optimizer: {
|
|
269
|
+
enabled: true,
|
|
270
|
+
runs: 200,
|
|
271
|
+
},
|
|
272
|
+
outputSelection: {
|
|
273
|
+
'*': {
|
|
274
|
+
'': [
|
|
275
|
+
'ast',
|
|
276
|
+
],
|
|
277
|
+
'*': [
|
|
278
|
+
'storageLayout',
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
sources: {
|
|
284
|
+
'contracts/test/NamespacedToModify.sol': {
|
|
285
|
+
content: `// SPDX-License-Identifier: MIT␊
|
|
286
|
+
pragma solidity ^0.8.20;␊
|
|
287
|
+
␊
|
|
288
|
+
abstract contract Example {␊
|
|
289
|
+
/// @custom:storage-location erc7201:example.main␊
|
|
290
|
+
struct MainStorage {␊
|
|
291
|
+
uint256 x;␊
|
|
292
|
+
uint256 y;␊
|
|
293
|
+
} MainStorage $MainStorage_random;␊
|
|
294
|
+
␊
|
|
295
|
+
/// @custom:storage-location erc7201:example.secondary␊
|
|
296
|
+
struct SecondaryStorage {␊
|
|
297
|
+
uint256 a;␊
|
|
298
|
+
uint256 b;␊
|
|
299
|
+
} SecondaryStorage $SecondaryStorage_random;␊
|
|
300
|
+
␊
|
|
301
|
+
/// @custom:storage-location erc7201:example.with.following.comment␊
|
|
302
|
+
// some comment␊
|
|
303
|
+
struct StorageWithComment {␊
|
|
304
|
+
uint256 a;␊
|
|
305
|
+
uint256 b;␊
|
|
306
|
+
} StorageWithComment $StorageWithComment_random;␊
|
|
47
307
|
␊
|
|
48
308
|
/// @notice some natspec␊
|
|
49
309
|
function foo() public {}␊
|
|
@@ -98,12 +358,14 @@ Generated by [AVA](https://avajs.dev).
|
|
|
98
358
|
enum $astId_id_random { dummy }␊
|
|
99
359
|
}␊
|
|
100
360
|
␊
|
|
101
|
-
contract HasFunction {␊
|
|
102
|
-
␊
|
|
361
|
+
abstract contract HasFunction {␊
|
|
362
|
+
/// @param myInt an integer␊
|
|
363
|
+
enum $astId_id_random { dummy }␊
|
|
364
|
+
␊
|
|
103
365
|
function foo() pure public returns (bool) {}␊
|
|
104
366
|
}␊
|
|
105
367
|
␊
|
|
106
|
-
contract UsingFunction is HasFunction {␊
|
|
368
|
+
abstract contract UsingFunction is HasFunction {␊
|
|
107
369
|
enum $astId_id_random { dummy }␊
|
|
108
370
|
}␊
|
|
109
371
|
␊
|
|
@@ -117,7 +379,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
117
379
|
function plusOne(uint x) pure public returns (bool) {}␊
|
|
118
380
|
}␊
|
|
119
381
|
␊
|
|
120
|
-
contract Consumer {␊
|
|
382
|
+
abstract contract Consumer {␊
|
|
121
383
|
enum $astId_id_random { dummy }␊
|
|
122
384
|
␊
|
|
123
385
|
function usingFreeFunction() pure public returns (bool) {}␊
|
|
@@ -127,7 +389,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
127
389
|
function usingLibraryFunction() pure public returns (bool) {}␊
|
|
128
390
|
}␊
|
|
129
391
|
␊
|
|
130
|
-
contract HasConstantWithSelector {␊
|
|
392
|
+
abstract contract HasConstantWithSelector {␊
|
|
131
393
|
bytes4 constant CONTRACT_CONSTANT_USING_SELECTOR = HasFunction.foo.selector;␊
|
|
132
394
|
}␊
|
|
133
395
|
␊
|
|
@@ -159,7 +421,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
159
421
|
*/␊
|
|
160
422
|
enum $astId_id_random { dummy }␊
|
|
161
423
|
␊
|
|
162
|
-
contract UsingForDirectives {␊
|
|
424
|
+
abstract contract UsingForDirectives {␊
|
|
163
425
|
enum $astId_id_random { dummy }␊
|
|
164
426
|
␊
|
|
165
427
|
function usingFor(uint x) pure public returns (bool) {}␊
|
|
@@ -185,7 +447,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
185
447
|
␊
|
|
186
448
|
int8 constant MAX_SIZE_C = 2;␊
|
|
187
449
|
␊
|
|
188
|
-
contract StructArrayUsesConstant {␊
|
|
450
|
+
abstract contract StructArrayUsesConstant {␊
|
|
189
451
|
uint16 private constant MAX_SIZE = 10;␊
|
|
190
452
|
␊
|
|
191
453
|
struct NotNamespaced {␊
|
|
@@ -208,11 +470,11 @@ Generated by [AVA](https://avajs.dev).
|
|
|
208
470
|
interface IDummy {␊
|
|
209
471
|
}␊
|
|
210
472
|
␊
|
|
211
|
-
contract UsesAddress {␊
|
|
473
|
+
abstract contract UsesAddress {␊
|
|
212
474
|
IDummy public constant MY_CONTRACT = IDummy(MY_ADDRESS);␊
|
|
213
475
|
}␊
|
|
214
476
|
␊
|
|
215
|
-
contract HasFunctionWithRequiredReturn {␊
|
|
477
|
+
abstract contract HasFunctionWithRequiredReturn {␊
|
|
216
478
|
struct S { uint x; }␊
|
|
217
479
|
function foo(S calldata s) internal pure returns (bool) {}␊
|
|
218
480
|
}␊
|
|
@@ -235,7 +497,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
235
497
|
*/␊
|
|
236
498
|
function hasReturnsDocumentedAsParams() pure returns (bool a, bool b) {}␊
|
|
237
499
|
␊
|
|
238
|
-
contract HasNatSpecWithMultipleReturns {␊
|
|
500
|
+
abstract contract HasNatSpecWithMultipleReturns {␊
|
|
239
501
|
/**␊
|
|
240
502
|
* @return uint 1␊
|
|
241
503
|
* @return uint 2␊
|
|
@@ -254,7 +516,38 @@ Generated by [AVA](https://avajs.dev).
|
|
|
254
516
|
*/␊
|
|
255
517
|
function hasReturnsDocumentedAsParamsInContract() public pure returns (bool a, bool b) {}␊
|
|
256
518
|
}␊
|
|
257
|
-
|
|
519
|
+
␊
|
|
520
|
+
interface IHasExternalViewFunction {␊
|
|
521
|
+
function foo() external view returns (bool);␊
|
|
522
|
+
}␊
|
|
523
|
+
␊
|
|
524
|
+
abstract contract HasExternalViewFunction is IHasExternalViewFunction {␊
|
|
525
|
+
// This generates a getter function that conforms to the interface␊
|
|
526
|
+
enum $astId_id_random { dummy }␊
|
|
527
|
+
␊
|
|
528
|
+
// References a selector in an interface␊
|
|
529
|
+
bytes4 constant USING_INTERFACE_FUNCTION_SELECTOR = IHasExternalViewFunction.foo.selector;␊
|
|
530
|
+
␊
|
|
531
|
+
// References a getter generated for a public variable␊
|
|
532
|
+
enum $astId_id_random { dummy }␊
|
|
533
|
+
}␊
|
|
534
|
+
␊
|
|
535
|
+
abstract contract DeploysContractToImmutable {␊
|
|
536
|
+
enum $astId_id_random { dummy }␊
|
|
537
|
+
}␊
|
|
538
|
+
␊
|
|
539
|
+
abstract contract HasSpecialFunctions {␊
|
|
540
|
+
/// @param data call data␊
|
|
541
|
+
/// @return dataReturn returned data␊
|
|
542
|
+
enum $astId_id_random { dummy }␊
|
|
543
|
+
␊
|
|
544
|
+
enum $astId_id_random { dummy }␊
|
|
545
|
+
␊
|
|
546
|
+
// Regular function but payable␊
|
|
547
|
+
function hasPayable() public payable {}␊
|
|
548
|
+
␊
|
|
549
|
+
bytes4 constant PAYABLE_SELECTOR = this.hasPayable.selector;␊
|
|
550
|
+
}`,
|
|
258
551
|
},
|
|
259
552
|
'contracts/test/NamespacedToModifyImported.sol': {
|
|
260
553
|
content: `// SPDX-License-Identifier: MIT␊
|
|
@@ -262,7 +555,7 @@ Generated by [AVA](https://avajs.dev).
|
|
|
262
555
|
␊
|
|
263
556
|
import {CONSTANT_USING_SELECTOR, plusTwo, plusThree, CustomErrorOutsideContract} from "./NamespacedToModify.sol";␊
|
|
264
557
|
␊
|
|
265
|
-
contract Example {}␊
|
|
558
|
+
abstract contract Example {}␊
|
|
266
559
|
`,
|
|
267
560
|
},
|
|
268
561
|
},
|
|
@@ -295,12 +588,12 @@ Generated by [AVA](https://avajs.dev).
|
|
|
295
588
|
content: `// SPDX-License-Identifier: MIT␊
|
|
296
589
|
pragma solidity 0.7.6;␊
|
|
297
590
|
␊
|
|
298
|
-
contract HasFunction {␊
|
|
299
|
-
␊
|
|
591
|
+
abstract contract HasFunction {␊
|
|
592
|
+
enum $astId_id_random { dummy }␊
|
|
300
593
|
function foo() pure public returns (bool) {}␊
|
|
301
594
|
}␊
|
|
302
595
|
␊
|
|
303
|
-
contract UsingFunction is HasFunction {␊
|
|
596
|
+
abstract contract UsingFunction is HasFunction {␊
|
|
304
597
|
enum $astId_id_random { dummy }␊
|
|
305
598
|
}␊
|
|
306
599
|
`,
|
|
Binary file
|
|
@@ -2,7 +2,7 @@ import { isNodeType } from 'solidity-ast/utils';
|
|
|
2
2
|
import { Node } from 'solidity-ast/node';
|
|
3
3
|
import { SolcInput, SolcOutput } from '../solc-api';
|
|
4
4
|
import { getStorageLocationAnnotation } from '../storage/namespace';
|
|
5
|
-
import { assert } from './assert';
|
|
5
|
+
import { assert, assertUnreachable } from './assert';
|
|
6
6
|
import { FunctionDefinition, VariableDeclaration } from 'solidity-ast';
|
|
7
7
|
|
|
8
8
|
const OUTPUT_SELECTION = {
|
|
@@ -18,17 +18,22 @@ const OUTPUT_SELECTION = {
|
|
|
18
18
|
*
|
|
19
19
|
* This makes the following modifications to the input:
|
|
20
20
|
* - Adds a state variable for each namespaced struct definition
|
|
21
|
-
* - For each contract, for all node types that are not needed for storage layout or may
|
|
21
|
+
* - For each contract, for all node types that are not needed for storage layout or may call functions and constructors, converts them to dummy enums with random id
|
|
22
22
|
* - Converts all using for directives (at file level and in contracts) to dummy enums with random id (do not delete them to avoid orphaning possible NatSpec documentation)
|
|
23
|
-
* - Converts all custom errors
|
|
23
|
+
* - Converts all custom errors and constants (at file level) to dummy enums with the same name (do not delete them since they might be imported by other files)
|
|
24
|
+
* - Replaces functions as follows:
|
|
25
|
+
* - For regular function and free function, keep declarations since they may be referenced by constants (free functions may also be imported by other files). But simplify compilation by removing modifiers and body, and replace return parameters with bools which can be default initialized.
|
|
26
|
+
* - Constructors are not needed, since we removed anything that may call constructors. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
27
|
+
* - Fallback and receive functions are not needed, since they don't have signatures. Convert to dummy enums to avoid orphaning possible NatSpec.
|
|
24
28
|
*
|
|
25
29
|
* Also sets the outputSelection to only include storageLayout and ast, since the other outputs are not needed.
|
|
26
30
|
*
|
|
27
31
|
* @param input The original solc input.
|
|
28
32
|
* @param output The original solc output.
|
|
33
|
+
* @param solcVersion The version of the solc compiler that was originally used to compile the input.
|
|
29
34
|
* @returns The modified solc input with storage layout that includes namespaced type information.
|
|
30
35
|
*/
|
|
31
|
-
export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcInput {
|
|
36
|
+
export function makeNamespacedInput(input: SolcInput, output: SolcOutput, solcVersion?: string): SolcInput {
|
|
32
37
|
const modifiedSources: Record<string, { content?: string }> = {};
|
|
33
38
|
|
|
34
39
|
for (const [sourcePath] of Object.entries(input.sources)) {
|
|
@@ -48,6 +53,12 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
48
53
|
case 'ContractDefinition': {
|
|
49
54
|
const contractDef = node;
|
|
50
55
|
|
|
56
|
+
// Mark contracts as abstract, since state variables are converted to dummy enums
|
|
57
|
+
// which would not generate public getters for inherited interface functions
|
|
58
|
+
if (contractDef.contractKind === 'contract' && !contractDef.abstract) {
|
|
59
|
+
modifications.push(makeInsertBefore(contractDef, 'abstract '));
|
|
60
|
+
}
|
|
61
|
+
|
|
51
62
|
// Remove any calls to parent constructors from the inheritance list
|
|
52
63
|
const inherits = contractDef.baseContracts;
|
|
53
64
|
for (const inherit of inherits) {
|
|
@@ -144,12 +155,68 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
|
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
157
|
|
|
147
|
-
|
|
158
|
+
const modifiedSource = tryRemoveNonStructNatSpec(getModifiedSource(orig, modifications), solcVersion);
|
|
159
|
+
|
|
160
|
+
modifiedSources[sourcePath] = { ...source, content: modifiedSource };
|
|
148
161
|
}
|
|
149
162
|
|
|
150
163
|
return { ...input, sources: modifiedSources, settings: { ...input.settings, outputSelection: OUTPUT_SELECTION } };
|
|
151
164
|
}
|
|
152
165
|
|
|
166
|
+
/**
|
|
167
|
+
* If Slang is supported for the current platform and we have the compiler version available,
|
|
168
|
+
* use Slang to parse and remove all NatSpec comments that do not precede a struct definition and return the modified content.
|
|
169
|
+
*
|
|
170
|
+
* Otherwise, return the original content.
|
|
171
|
+
*/
|
|
172
|
+
function tryRemoveNonStructNatSpec(origContent: string, solcVersion: string | undefined): string {
|
|
173
|
+
const natSpecRemovals: Modification[] = [];
|
|
174
|
+
|
|
175
|
+
if (solcVersion !== undefined && tryRequire('@nomicfoundation/slang')) {
|
|
176
|
+
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
177
|
+
const { Language } = require('@nomicfoundation/slang/language');
|
|
178
|
+
const { NonterminalKind, TerminalKind } = require('@nomicfoundation/slang/kinds');
|
|
179
|
+
const { TerminalNode } = require('@nomicfoundation/slang/cst');
|
|
180
|
+
const { isTrivia } = require('./slang/trivia');
|
|
181
|
+
/* eslint-enable @typescript-eslint/no-var-requires */
|
|
182
|
+
|
|
183
|
+
const language = new Language(solcVersion);
|
|
184
|
+
const parseOutput = language.parse(NonterminalKind.SourceUnit, origContent);
|
|
185
|
+
const cursor = parseOutput.createTreeCursor();
|
|
186
|
+
|
|
187
|
+
while (
|
|
188
|
+
cursor.goToNextTerminalWithKinds([TerminalKind.MultiLineNatSpecComment, TerminalKind.SingleLineNatSpecComment])
|
|
189
|
+
) {
|
|
190
|
+
// Lookahead to determine if the next non-trivia node is the struct keyword.
|
|
191
|
+
// If so, this NatSpec is part of the struct definition and should not be removed.
|
|
192
|
+
const lookaheadCursor = cursor.clone();
|
|
193
|
+
while (lookaheadCursor.goToNextTerminal() && isTrivia(lookaheadCursor.node())) {
|
|
194
|
+
// skip over trivia nodes
|
|
195
|
+
}
|
|
196
|
+
if (lookaheadCursor.node().kind === TerminalKind.StructKeyword) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const triviaNode = cursor.node();
|
|
201
|
+
assert(triviaNode instanceof TerminalNode);
|
|
202
|
+
natSpecRemovals.push(makeDeleteRange(cursor.textRange.start.utf8, cursor.textRange.end.utf8));
|
|
203
|
+
}
|
|
204
|
+
return getModifiedSource(Buffer.from(origContent, 'utf8'), natSpecRemovals);
|
|
205
|
+
} else {
|
|
206
|
+
return origContent;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function tryRequire(id: string) {
|
|
211
|
+
try {
|
|
212
|
+
require(id);
|
|
213
|
+
return true;
|
|
214
|
+
} catch (e: any) {
|
|
215
|
+
// do nothing
|
|
216
|
+
}
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
153
220
|
interface Modification {
|
|
154
221
|
start: number;
|
|
155
222
|
end: number;
|
|
@@ -165,28 +232,39 @@ function toDummyEnumWithAstId(astId: number) {
|
|
|
165
232
|
}
|
|
166
233
|
|
|
167
234
|
function replaceFunction(node: FunctionDefinition, orig: Buffer, modifications: Modification[]) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
235
|
+
switch (node.kind) {
|
|
236
|
+
case 'freeFunction':
|
|
237
|
+
case 'function': {
|
|
238
|
+
if (node.modifiers.length > 0) {
|
|
239
|
+
for (const modifier of node.modifiers) {
|
|
240
|
+
modifications.push(makeDelete(modifier, orig));
|
|
241
|
+
}
|
|
174
242
|
}
|
|
175
|
-
}
|
|
176
243
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
244
|
+
if (node.returnParameters.parameters.length > 0) {
|
|
245
|
+
modifications.push(
|
|
246
|
+
makeReplace(
|
|
247
|
+
node.returnParameters,
|
|
248
|
+
orig,
|
|
249
|
+
`(${node.returnParameters.parameters.map(param => toReturnParameterReplacement(param)).join(', ')})`,
|
|
250
|
+
),
|
|
251
|
+
);
|
|
252
|
+
}
|
|
186
253
|
|
|
187
|
-
|
|
188
|
-
|
|
254
|
+
if (node.body) {
|
|
255
|
+
modifications.push(makeReplace(node.body, orig, '{}'));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
break;
|
|
189
259
|
}
|
|
260
|
+
case 'constructor':
|
|
261
|
+
case 'fallback':
|
|
262
|
+
case 'receive': {
|
|
263
|
+
modifications.push(makeReplace(node, orig, toDummyEnumWithAstId(node.id)));
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
default:
|
|
267
|
+
return assertUnreachable(node.kind);
|
|
190
268
|
}
|
|
191
269
|
}
|
|
192
270
|
|
|
@@ -210,6 +288,11 @@ function makeReplace(node: Node, orig: Buffer, text: string): Modification {
|
|
|
210
288
|
return { start, end, text };
|
|
211
289
|
}
|
|
212
290
|
|
|
291
|
+
function makeInsertBefore(node: Node, text: string): Modification {
|
|
292
|
+
const { start } = getPositions(node);
|
|
293
|
+
return { start: start, end: start, text };
|
|
294
|
+
}
|
|
295
|
+
|
|
213
296
|
function makeInsertAfter(node: Node, text: string): Modification {
|
|
214
297
|
const { end } = getPositions(node);
|
|
215
298
|
return { start: end, end, text };
|
|
@@ -227,7 +310,11 @@ function makeDelete(node: Node, orig: Buffer): Modification {
|
|
|
227
310
|
end += 1;
|
|
228
311
|
}
|
|
229
312
|
}
|
|
230
|
-
return
|
|
313
|
+
return makeDeleteRange(positions.start, end);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function makeDeleteRange(start: number, end: number): Modification {
|
|
317
|
+
return { start, end };
|
|
231
318
|
}
|
|
232
319
|
|
|
233
320
|
function getModifiedSource(orig: Buffer, modifications: Modification[]): string {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TerminalKind } from '@nomicfoundation/slang/kinds';
|
|
2
|
+
import { Node, TerminalNode } from '@nomicfoundation/slang/cst';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns true if the node is a trivia terminal (whitespace or comment or NatSpec)
|
|
6
|
+
*
|
|
7
|
+
* CAUTION: This must be imported dynamically.
|
|
8
|
+
* Only import this file if Slang is supported on the current platform, otherwise an error will be thrown on import.
|
|
9
|
+
*/
|
|
10
|
+
export function isTrivia(node: Node) {
|
|
11
|
+
return node instanceof TerminalNode && isTriviaKind(node.kind);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isTriviaKind(kind: TerminalKind) {
|
|
15
|
+
return (
|
|
16
|
+
kind === TerminalKind.EndOfLine ||
|
|
17
|
+
kind === TerminalKind.MultiLineComment ||
|
|
18
|
+
kind === TerminalKind.MultiLineNatSpecComment ||
|
|
19
|
+
kind === TerminalKind.SingleLineComment ||
|
|
20
|
+
kind === TerminalKind.SingleLineNatSpecComment ||
|
|
21
|
+
kind === TerminalKind.Whitespace
|
|
22
|
+
);
|
|
23
|
+
}
|