@openzeppelin/upgrades-core 1.13.1 → 1.14.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/dist/proxy-kind.d.ts +4 -0
- package/dist/proxy-kind.d.ts.map +1 -1
- package/dist/proxy-kind.js +4 -0
- package/dist/proxy-kind.js.map +1 -1
- package/dist/standalone.test.js +9 -0
- package/dist/standalone.test.js.map +1 -1
- package/dist/storage/compare.d.ts +15 -4
- package/dist/storage/compare.d.ts.map +1 -1
- package/dist/storage/compare.js +49 -4
- package/dist/storage/compare.js.map +1 -1
- package/dist/storage/extract.d.ts.map +1 -1
- package/dist/storage/extract.js +27 -3
- package/dist/storage/extract.js.map +1 -1
- package/dist/storage/layout.d.ts +14 -0
- package/dist/storage/layout.d.ts.map +1 -1
- package/dist/storage/layout.js +6 -2
- package/dist/storage/layout.js.map +1 -1
- package/dist/storage/report-rename-retype.test.d.ts +2 -0
- package/dist/storage/report-rename-retype.test.d.ts.map +1 -0
- package/dist/storage/report-rename-retype.test.js +93 -0
- package/dist/storage/report-rename-retype.test.js.map +1 -0
- package/dist/storage/report.d.ts.map +1 -1
- package/dist/storage/report.js +32 -2
- package/dist/storage/report.js.map +1 -1
- package/dist/storage/report.test.js +6 -0
- package/dist/storage/report.test.js.map +1 -1
- package/dist/storage.test.js +1 -1
- package/dist/utils/execall.d.ts +2 -0
- package/dist/utils/execall.d.ts.map +1 -0
- package/dist/utils/execall.js +17 -0
- package/dist/utils/execall.js.map +1 -0
- package/package.json +2 -2
- package/src/proxy-kind.ts +4 -0
- package/src/standalone.test.ts +12 -0
- package/src/storage/compare.ts +61 -8
- package/src/storage/extract.ts +31 -5
- package/src/storage/layout.ts +17 -2
- package/src/storage/report-rename-retype.test.ts +106 -0
- package/src/storage/report-rename-retype.test.ts.md +44 -0
- package/src/storage/report-rename-retype.test.ts.snap +0 -0
- package/src/storage/report.test.ts +7 -0
- package/src/storage/report.test.ts.md +11 -0
- package/src/storage/report.test.ts.snap +0 -0
- package/src/storage/report.ts +39 -4
- package/src/storage.test.ts +1 -1
- package/src/storage.test.ts.md +146 -0
- package/src/storage.test.ts.snap +0 -0
- package/src/utils/execall.ts +11 -0
package/dist/storage/report.js
CHANGED
|
@@ -21,8 +21,12 @@ class LayoutCompatibilityReport {
|
|
|
21
21
|
explain(color = true) {
|
|
22
22
|
const chalk = new chalk_1.default.Instance({ level: color && chalk_1.default.supportsColor ? chalk_1.default.supportsColor.level : 0 });
|
|
23
23
|
const res = [];
|
|
24
|
-
for (const op of this.ops) {
|
|
24
|
+
for (const [i, op] of this.ops.entries()) {
|
|
25
25
|
const src = 'updated' in op ? op.updated.src : op.original.contract;
|
|
26
|
+
// Only print layoutchange if it's the first op, otherwise we assume it will be explained by previous ops.
|
|
27
|
+
if (op.kind === 'layoutchange' && i !== 0) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
26
30
|
res.push(chalk.bold(src) + ':' + (0, indent_1.indent)(explainStorageOperation(op, { kind: 'layout', allowAppend: true }), 2, 1));
|
|
27
31
|
}
|
|
28
32
|
return res.join('\n\n');
|
|
@@ -44,6 +48,11 @@ function explainStorageOperation(op, ctx) {
|
|
|
44
48
|
return `Renamed ${label(op.original)} to ${label(op.updated)}`;
|
|
45
49
|
case 'replace':
|
|
46
50
|
return `Replaced ${label(op.original)} with ${label(op.updated)} of incompatible type`;
|
|
51
|
+
case 'layoutchange': {
|
|
52
|
+
return (`Layout ${op.change.uncertain ? 'could have changed' : 'changed'} for ${label(op.updated)} ` +
|
|
53
|
+
`(${op.original.type.item.label} -> ${op.updated.type.item.label})\n` +
|
|
54
|
+
describeLayoutTransition(op.change)).trimEnd();
|
|
55
|
+
}
|
|
47
56
|
default: {
|
|
48
57
|
const title = explainBasicOperation(op, t => t.label);
|
|
49
58
|
const hints = [];
|
|
@@ -73,6 +82,8 @@ function explainStorageOperation(op, ctx) {
|
|
|
73
82
|
}
|
|
74
83
|
function explainTypeChange(ch) {
|
|
75
84
|
switch (ch.kind) {
|
|
85
|
+
case 'visibility change':
|
|
86
|
+
return `Bad upgrade ${describeTransition(ch.original, ch.updated)}\nDifferent visibility`;
|
|
76
87
|
case 'obvious mismatch':
|
|
77
88
|
case 'struct members':
|
|
78
89
|
case 'enum members':
|
|
@@ -141,7 +152,15 @@ function explainTypeChangeDetails(ch) {
|
|
|
141
152
|
case 'struct members': {
|
|
142
153
|
const { allowAppend } = ch;
|
|
143
154
|
return (`In ${ch.updated.item.label}\n` +
|
|
144
|
-
(0, itemize_1.itemize)(...ch.ops.
|
|
155
|
+
(0, itemize_1.itemize)(...ch.ops.flatMap((op, i) => {
|
|
156
|
+
if (op.kind === 'layoutchange' && i !== 0) {
|
|
157
|
+
// Only print layoutchange if it's the first op, otherwise we assume it will be explained by previous ops.
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return [explainStorageOperation(op, { kind: 'struct', allowAppend })];
|
|
162
|
+
}
|
|
163
|
+
})));
|
|
145
164
|
}
|
|
146
165
|
case 'enum members':
|
|
147
166
|
return `In ${ch.updated.item.label}\n` + (0, itemize_1.itemize)(...ch.ops.map(explainEnumOperation));
|
|
@@ -175,6 +194,17 @@ function describeTransition(original, updated) {
|
|
|
175
194
|
return `from ${originalLabel} to ${updatedLabel}`;
|
|
176
195
|
}
|
|
177
196
|
}
|
|
197
|
+
function describeLayoutTransition(change) {
|
|
198
|
+
const res = [];
|
|
199
|
+
for (const k of ['slot', 'offset', 'bytes']) {
|
|
200
|
+
const ch = change[k];
|
|
201
|
+
if (ch) {
|
|
202
|
+
const label = (k === 'bytes' ? 'number of bytes' : k).replace(/^./, c => c.toUpperCase());
|
|
203
|
+
res.push(`${label} changed from ${ch.from} to ${ch.to}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return (0, itemize_1.itemize)(...res);
|
|
207
|
+
}
|
|
178
208
|
function label(variable) {
|
|
179
209
|
return '`' + variable.label + '`';
|
|
180
210
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/storage/report.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA2B;AAK3B,8CAAwD;AACxD,4CAAyC;AACzC,4CAAyC;AAEzC,MAAa,yBAAyB;IACpC,YAAqB,GAAoC;QAApC,QAAG,GAAH,GAAG,CAAiC;IAAG,CAAC;IAE7D,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,KAAK,GAAG,IAAI;QAClB,MAAM,KAAK,GAAG,IAAI,eAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,eAAM,CAAC,aAAa,CAAC,CAAC,CAAC,eAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7G,MAAM,GAAG,GAAG,EAAE,CAAC;QAEf,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/storage/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,6 +49,12 @@ test('obvious mismatch', t => {
|
|
|
49
49
|
const report = getReport(v1, v2);
|
|
50
50
|
t.snapshot(report.explain());
|
|
51
51
|
});
|
|
52
|
+
test('function visibility change', t => {
|
|
53
|
+
const v1 = t.context.extractStorageLayout('StorageUpgrade_FunctionType_Visibility_V1');
|
|
54
|
+
const v2 = t.context.extractStorageLayout('StorageUpgrade_FunctionType_Visibility_V2_Bad');
|
|
55
|
+
const report = getReport(v1, v2);
|
|
56
|
+
t.snapshot(report.explain());
|
|
57
|
+
});
|
|
52
58
|
test('array', t => {
|
|
53
59
|
const v1 = t.context.extractStorageLayout('StorageUpgrade_Array_V1');
|
|
54
60
|
const v2 = t.context.extractStorageLayout('StorageUpgrade_Array_V2_Bad');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.test.js","sourceRoot":"","sources":["../../src/storage/report.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"report.test.js","sourceRoot":"","sources":["../../src/storage/report.test.ts"],"names":[],"mappings":"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"}
|
package/dist/storage.test.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execall.d.ts","sourceRoot":"","sources":["../../src/utils/execall.ts"],"names":[],"mappings":"AAAA,wBAAiB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,6CAUhD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.execall = void 0;
|
|
4
|
+
function* execall(re, text) {
|
|
5
|
+
re = new RegExp(re, re.flags + (re.sticky ? '' : 'y'));
|
|
6
|
+
while (true) {
|
|
7
|
+
const match = re.exec(text);
|
|
8
|
+
if (match && match[0] !== '') {
|
|
9
|
+
yield match;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.execall = execall;
|
|
17
|
+
//# sourceMappingURL=execall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execall.js","sourceRoot":"","sources":["../../src/utils/execall.ts"],"names":[],"mappings":";;;AAAA,QAAe,CAAC,CAAC,OAAO,CAAC,EAAU,EAAE,IAAY;IAC/C,EAAE,GAAG,IAAI,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,OAAO,IAAI,EAAE;QACX,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,MAAM,KAAK,CAAC;SACb;aAAM;YACL,MAAM;SACP;KACF;AACH,CAAC;AAVD,0BAUC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openzeppelin/upgrades-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"proper-lockfile": "^4.1.1",
|
|
60
60
|
"solidity-ast": "^0.4.15"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "c33ebd898c989fa96c858b14ea6ead63427d5e55"
|
|
63
63
|
}
|
package/src/proxy-kind.ts
CHANGED
|
@@ -62,6 +62,10 @@ export async function processProxyKind(
|
|
|
62
62
|
/**
|
|
63
63
|
* Detects the kind of proxy at an address by reading its ERC 1967 storage slots.
|
|
64
64
|
*
|
|
65
|
+
* @deprecated Not reliable since UUPS proxies can have admin storage slot set, which causes
|
|
66
|
+
* this function to treat it as transparent. Instead, if implementation contract signatures are
|
|
67
|
+
* available, infer the proxy kind using `inferProxyKind` instead.
|
|
68
|
+
*
|
|
65
69
|
* @param provider the Ethereum provider
|
|
66
70
|
* @param proxyAddress the proxy address
|
|
67
71
|
* @returns the proxy kind
|
package/src/standalone.test.ts
CHANGED
|
@@ -38,3 +38,15 @@ test('reports storage upgrade errors', t => {
|
|
|
38
38
|
const badReport = v1.getStorageUpgradeReport(v2Bad);
|
|
39
39
|
t.false(badReport.ok);
|
|
40
40
|
});
|
|
41
|
+
|
|
42
|
+
test('dont report renamed version update', t => {
|
|
43
|
+
const v1 = new UpgradeableContract('StandaloneRenameV1', t.context.solcInput, t.context.solcOutput);
|
|
44
|
+
|
|
45
|
+
const v2 = new UpgradeableContract('StandaloneRenameV2', t.context.solcInput, t.context.solcOutput);
|
|
46
|
+
const goodReport = v1.getStorageUpgradeReport(v2);
|
|
47
|
+
t.true(goodReport.ok);
|
|
48
|
+
|
|
49
|
+
const v3 = new UpgradeableContract('StandaloneRenameV3', t.context.solcInput, t.context.solcOutput);
|
|
50
|
+
const goodReport2 = v2.getStorageUpgradeReport(v3);
|
|
51
|
+
t.true(goodReport2.ok);
|
|
52
|
+
});
|
package/src/storage/compare.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { levenshtein, Operation } from '../levenshtein';
|
|
2
|
-
import { ParsedTypeDetailed,
|
|
2
|
+
import { hasLayout, ParsedTypeDetailed, isEnumMembers, isStructMembers } from './layout';
|
|
3
3
|
import { UpgradesError } from '../error';
|
|
4
|
-
import { StructMember as _StructMember,
|
|
4
|
+
import { StorageItem as _StorageItem, StructMember as _StructMember, StorageField as _StorageField } from './layout';
|
|
5
5
|
import { LayoutCompatibilityReport } from './report';
|
|
6
6
|
import { assert } from '../utils/assert';
|
|
7
7
|
import { isValueType } from '../utils/is-value-type';
|
|
@@ -9,7 +9,7 @@ import { isValueType } from '../utils/is-value-type';
|
|
|
9
9
|
export type StorageItem = _StorageItem<ParsedTypeDetailed>;
|
|
10
10
|
type StructMember = _StructMember<ParsedTypeDetailed>;
|
|
11
11
|
|
|
12
|
-
export type StorageField =
|
|
12
|
+
export type StorageField = _StorageField<ParsedTypeDetailed>;
|
|
13
13
|
export type StorageOperation<F extends StorageField> = Operation<F, StorageFieldChange<F>>;
|
|
14
14
|
|
|
15
15
|
export type EnumOperation = Operation<string, { kind: 'replace'; original: string; updated: string }>;
|
|
@@ -17,6 +17,7 @@ export type EnumOperation = Operation<string, { kind: 'replace'; original: strin
|
|
|
17
17
|
type StorageFieldChange<F extends StorageField> = (
|
|
18
18
|
| { kind: 'replace' | 'rename' }
|
|
19
19
|
| { kind: 'typechange'; change: TypeChange }
|
|
20
|
+
| { kind: 'layoutchange'; change: LayoutChange }
|
|
20
21
|
) & {
|
|
21
22
|
original: F;
|
|
22
23
|
updated: F;
|
|
@@ -28,6 +29,7 @@ export type TypeChange = (
|
|
|
28
29
|
| 'obvious mismatch'
|
|
29
30
|
| 'unknown'
|
|
30
31
|
| 'array grow'
|
|
32
|
+
| 'visibility change'
|
|
31
33
|
| 'array shrink'
|
|
32
34
|
| 'array dynamic'
|
|
33
35
|
| 'enum resize'
|
|
@@ -51,6 +53,13 @@ export type TypeChange = (
|
|
|
51
53
|
updated: ParsedTypeDetailed;
|
|
52
54
|
};
|
|
53
55
|
|
|
56
|
+
export interface LayoutChange {
|
|
57
|
+
uncertain?: boolean;
|
|
58
|
+
slot?: Record<'from' | 'to', string>;
|
|
59
|
+
offset?: Record<'from' | 'to', number>;
|
|
60
|
+
bytes?: Record<'from' | 'to', string>;
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
export class StorageLayoutComparator {
|
|
55
64
|
hasAllowedUncheckedCustomTypes = false;
|
|
56
65
|
|
|
@@ -78,16 +87,57 @@ export class StorageLayoutComparator {
|
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
const
|
|
90
|
+
getVisibilityChange(original: ParsedTypeDetailed, updated: ParsedTypeDetailed): TypeChange | undefined {
|
|
91
|
+
const re = /^t_function_(internal|external)/;
|
|
92
|
+
const originalVisibility = original.head.match(re);
|
|
93
|
+
const updatedVisibility = updated.head.match(re);
|
|
94
|
+
assert(originalVisibility && updatedVisibility);
|
|
95
|
+
if (originalVisibility[0] !== updatedVisibility[0]) {
|
|
96
|
+
return { kind: 'visibility change', original, updated };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
84
99
|
|
|
85
|
-
|
|
100
|
+
getFieldChange<F extends StorageField>(original: F, updated: F): StorageFieldChange<F> | undefined {
|
|
101
|
+
const nameChange =
|
|
102
|
+
!this.unsafeAllowRenames &&
|
|
103
|
+
original.label !== updated.renamedFrom &&
|
|
104
|
+
(updated.label !== original.label ||
|
|
105
|
+
(updated.renamedFrom !== undefined && updated.renamedFrom !== original.renamedFrom));
|
|
106
|
+
const retypedFromOriginal = original.type.item.label === updated.retypedFrom?.trim();
|
|
107
|
+
const typeChange = !retypedFromOriginal && this.getTypeChange(original.type, updated.type, { allowAppend: false });
|
|
108
|
+
const layoutChange = this.getLayoutChange(original, updated);
|
|
109
|
+
|
|
110
|
+
if (updated.retypedFrom && layoutChange) {
|
|
111
|
+
return { kind: 'layoutchange', original, updated, change: layoutChange };
|
|
112
|
+
} else if (typeChange && nameChange) {
|
|
86
113
|
return { kind: 'replace', original, updated };
|
|
87
114
|
} else if (nameChange) {
|
|
88
115
|
return { kind: 'rename', original, updated };
|
|
89
116
|
} else if (typeChange) {
|
|
90
117
|
return { kind: 'typechange', change: typeChange, original, updated };
|
|
118
|
+
} else if (layoutChange && !layoutChange.uncertain) {
|
|
119
|
+
// Any layout change should be caught earlier as a type change, but we
|
|
120
|
+
// add this check as a safety fallback.
|
|
121
|
+
return { kind: 'layoutchange', original, updated, change: layoutChange };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getLayoutChange(original: StorageField, updated: StorageField): LayoutChange | undefined {
|
|
126
|
+
const validPair = ['uint8', 'bool'];
|
|
127
|
+
const knownCompatibleTypes =
|
|
128
|
+
validPair.includes(original.type.item.label) && validPair.includes(updated.type.item.label);
|
|
129
|
+
if (original.type.item.label == updated.type.item.label || knownCompatibleTypes) {
|
|
130
|
+
return undefined;
|
|
131
|
+
} else if (hasLayout(original) && hasLayout(updated)) {
|
|
132
|
+
const change = <T>(from: T, to: T) => (from === to ? undefined : { from, to });
|
|
133
|
+
const slot = change(original.slot, updated.slot);
|
|
134
|
+
const offset = change(original.offset, updated.offset);
|
|
135
|
+
const bytes = change(original.type.item.numberOfBytes, updated.type.item.numberOfBytes);
|
|
136
|
+
if (slot || offset || bytes) {
|
|
137
|
+
return { slot, offset, bytes };
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
return { uncertain: true };
|
|
91
141
|
}
|
|
92
142
|
}
|
|
93
143
|
|
|
@@ -97,7 +147,6 @@ export class StorageLayoutComparator {
|
|
|
97
147
|
{ allowAppend }: { allowAppend: boolean },
|
|
98
148
|
): TypeChange | undefined {
|
|
99
149
|
const key = JSON.stringify({ original: original.id, updated: updated.id, allowAppend });
|
|
100
|
-
|
|
101
150
|
if (this.cache.has(key)) {
|
|
102
151
|
return this.cache.get(key);
|
|
103
152
|
}
|
|
@@ -121,6 +170,10 @@ export class StorageLayoutComparator {
|
|
|
121
170
|
updated: ParsedTypeDetailed,
|
|
122
171
|
{ allowAppend }: { allowAppend: boolean },
|
|
123
172
|
): TypeChange | undefined {
|
|
173
|
+
if (updated.head.startsWith('t_function')) {
|
|
174
|
+
return this.getVisibilityChange(original, updated);
|
|
175
|
+
}
|
|
176
|
+
|
|
124
177
|
if (original.head !== updated.head) {
|
|
125
178
|
return { kind: 'obvious mismatch', original, updated };
|
|
126
179
|
}
|
package/src/storage/extract.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { SrcDecoder } from '../src-decoder';
|
|
|
13
13
|
import { ASTDereferencer } from '../ast-dereferencer';
|
|
14
14
|
import { mapValues } from '../utils/map-values';
|
|
15
15
|
import { pick } from '../utils/pick';
|
|
16
|
+
import { execall } from '../utils/execall';
|
|
16
17
|
|
|
17
18
|
const currentLayoutVersion = '1.1';
|
|
18
19
|
|
|
@@ -31,7 +32,10 @@ export function extractStorageLayout(
|
|
|
31
32
|
layout.types = mapValues(storageLayout.types, m => {
|
|
32
33
|
return {
|
|
33
34
|
label: m.label,
|
|
34
|
-
members: m.members?.map(m =>
|
|
35
|
+
members: m.members?.map(m =>
|
|
36
|
+
typeof m === 'string' ? m : pick(m, ['label', 'type', 'offset', 'slot']),
|
|
37
|
+
) as TypeItem['members'],
|
|
38
|
+
numberOfBytes: m.numberOfBytes,
|
|
35
39
|
};
|
|
36
40
|
});
|
|
37
41
|
|
|
@@ -39,11 +43,12 @@ export function extractStorageLayout(
|
|
|
39
43
|
const origin = getOriginContract(contractDef, storage.astId, deref);
|
|
40
44
|
assert(origin, `Did not find variable declaration node for '${storage.label}'`);
|
|
41
45
|
const { varDecl, contract } = origin;
|
|
46
|
+
const { renamedFrom, retypedFrom } = getRetypedRenamed(varDecl);
|
|
42
47
|
// Solc layout doesn't bring members for enums so we get them using the ast method
|
|
43
48
|
loadLayoutType(varDecl, layout, deref);
|
|
44
49
|
const { label, offset, slot, type } = storage;
|
|
45
50
|
const src = decodeSrc(varDecl);
|
|
46
|
-
layout.storage.push({ label, offset, slot, type, contract, src });
|
|
51
|
+
layout.storage.push({ label, offset, slot, type, contract, src, retypedFrom, renamedFrom });
|
|
47
52
|
layout.flat = true;
|
|
48
53
|
}
|
|
49
54
|
} else {
|
|
@@ -51,12 +56,14 @@ export function extractStorageLayout(
|
|
|
51
56
|
if (isNodeType('VariableDeclaration', varDecl)) {
|
|
52
57
|
if (!varDecl.constant && varDecl.mutability !== 'immutable') {
|
|
53
58
|
const type = normalizeTypeIdentifier(typeDescriptions(varDecl).typeIdentifier);
|
|
54
|
-
|
|
59
|
+
const { renamedFrom, retypedFrom } = getRetypedRenamed(varDecl);
|
|
55
60
|
layout.storage.push({
|
|
56
61
|
contract: contractDef.name,
|
|
57
62
|
label: varDecl.name,
|
|
58
63
|
type,
|
|
59
64
|
src: decodeSrc(varDecl),
|
|
65
|
+
retypedFrom,
|
|
66
|
+
renamedFrom,
|
|
60
67
|
});
|
|
61
68
|
|
|
62
69
|
loadLayoutType(varDecl, layout, deref);
|
|
@@ -101,9 +108,8 @@ function getTypeMembers(typeDef: StructDefinition | EnumDefinition): TypeItem['m
|
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
function getOriginContract(contract: ContractDefinition, astId: number | undefined, deref: ASTDereferencer) {
|
|
104
|
-
for (const id of contract.linearizedBaseContracts
|
|
111
|
+
for (const id of contract.linearizedBaseContracts) {
|
|
105
112
|
const parentContract = deref(['ContractDefinition'], id);
|
|
106
|
-
|
|
107
113
|
const varDecl = parentContract.nodes.find(n => n.id == astId);
|
|
108
114
|
if (varDecl && isNodeType('VariableDeclaration', varDecl)) {
|
|
109
115
|
return { varDecl, contract: parentContract.name };
|
|
@@ -141,3 +147,23 @@ function loadLayoutType(varDecl: VariableDeclaration, layout: StorageLayout, der
|
|
|
141
147
|
}
|
|
142
148
|
}
|
|
143
149
|
}
|
|
150
|
+
|
|
151
|
+
function getRetypedRenamed(varDecl: VariableDeclaration) {
|
|
152
|
+
let retypedFrom, renamedFrom;
|
|
153
|
+
if ('documentation' in varDecl) {
|
|
154
|
+
const docs = typeof varDecl.documentation === 'string' ? varDecl.documentation : varDecl.documentation?.text ?? '';
|
|
155
|
+
for (const { groups } of execall(
|
|
156
|
+
/^\s*(?:@(?<title>\w+)(?::(?<tag>[a-z][a-z-]*))? )?(?<args>(?:(?!^\s@\w+)[^])*)/m,
|
|
157
|
+
docs,
|
|
158
|
+
)) {
|
|
159
|
+
if (groups?.title === 'custom') {
|
|
160
|
+
if (groups.tag === 'oz-retyped-from') {
|
|
161
|
+
retypedFrom = groups.args;
|
|
162
|
+
} else if (groups.tag === 'oz-renamed-from') {
|
|
163
|
+
renamedFrom = groups.args;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { retypedFrom, renamedFrom };
|
|
169
|
+
}
|
package/src/storage/layout.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface StorageLayout {
|
|
|
12
12
|
flat?: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export type StorageField<Type = string> = StorageItem<Type> | StructMember<Type>;
|
|
16
|
+
|
|
15
17
|
export interface StorageItem<Type = string> {
|
|
16
18
|
astId?: number;
|
|
17
19
|
contract: string;
|
|
@@ -20,11 +22,14 @@ export interface StorageItem<Type = string> {
|
|
|
20
22
|
src: string;
|
|
21
23
|
offset?: number;
|
|
22
24
|
slot?: string;
|
|
25
|
+
retypedFrom?: string;
|
|
26
|
+
renamedFrom?: string;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
export interface TypeItem<Type = string> {
|
|
26
30
|
label: string;
|
|
27
31
|
members?: TypeItemMembers<Type>;
|
|
32
|
+
numberOfBytes?: string;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
export type TypeItemMembers<Type = string> = StructMember<Type>[] | EnumMember[];
|
|
@@ -32,6 +37,10 @@ export type TypeItemMembers<Type = string> = StructMember<Type>[] | EnumMember[]
|
|
|
32
37
|
export interface StructMember<Type = string> {
|
|
33
38
|
label: string;
|
|
34
39
|
type: Type;
|
|
40
|
+
retypedFrom?: string;
|
|
41
|
+
renamedFrom?: string;
|
|
42
|
+
offset?: number;
|
|
43
|
+
slot?: string;
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
export type EnumMember = string;
|
|
@@ -46,7 +55,6 @@ type Replace<T, K extends string, V> = Omit<T, K> & Record<K, V>;
|
|
|
46
55
|
|
|
47
56
|
export function getDetailedLayout(layout: StorageLayout): StorageItem<ParsedTypeDetailed>[] {
|
|
48
57
|
const cache: Record<string, ParsedTypeDetailed> = {};
|
|
49
|
-
|
|
50
58
|
return layout.storage.map(parseWithDetails);
|
|
51
59
|
|
|
52
60
|
function parseWithDetails<I extends { type: string }>(item: I): Replace<I, 'type', ParsedTypeDetailed> {
|
|
@@ -75,7 +83,7 @@ export function getDetailedLayout(layout: StorageLayout): StorageItem<ParsedType
|
|
|
75
83
|
cache[parsed.id] = detailed;
|
|
76
84
|
|
|
77
85
|
detailed.args = parsed.args?.map(addDetailsToParsedType);
|
|
78
|
-
detailed.rets = parsed.
|
|
86
|
+
detailed.rets = parsed.rets?.map(addDetailsToParsedType);
|
|
79
87
|
detailed.item.members =
|
|
80
88
|
item?.members && (isStructMembers(item?.members) ? item.members.map(parseWithDetails) : item?.members);
|
|
81
89
|
|
|
@@ -90,3 +98,10 @@ export function isEnumMembers<T>(members: TypeItemMembers<T>): members is EnumMe
|
|
|
90
98
|
export function isStructMembers<T>(members: TypeItemMembers<T>): members is StructMember<T>[] {
|
|
91
99
|
return members.length === 0 || typeof members[0] === 'object';
|
|
92
100
|
}
|
|
101
|
+
|
|
102
|
+
export type StorageFieldWithLayout = StorageField<ParsedTypeDetailed> &
|
|
103
|
+
Required<Pick<StorageField, 'offset' | 'slot'>> & { type: { item: Required<Pick<TypeItem, 'numberOfBytes'>> } };
|
|
104
|
+
|
|
105
|
+
export function hasLayout(field: StorageField<ParsedTypeDetailed>): field is StorageFieldWithLayout {
|
|
106
|
+
return field.offset !== undefined && field.slot !== undefined && field.type.item.numberOfBytes !== undefined;
|
|
107
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import _test, { TestFn } from 'ava';
|
|
2
|
+
import { ContractDefinition } from 'solidity-ast';
|
|
3
|
+
import { ASTDereferencer, findAll } from 'solidity-ast/utils';
|
|
4
|
+
import { artifacts } from 'hardhat';
|
|
5
|
+
import { astDereferencer } from '../ast-dereferencer';
|
|
6
|
+
import { extractStorageLayout } from './extract';
|
|
7
|
+
import { StorageLayoutComparator } from './compare';
|
|
8
|
+
import { StorageLayout, getDetailedLayout } from './layout';
|
|
9
|
+
|
|
10
|
+
interface Context {
|
|
11
|
+
extractStorageLayout: (contract: string) => ReturnType<typeof extractStorageLayout>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const test = _test as TestFn<Context>;
|
|
15
|
+
|
|
16
|
+
const dummyDecodeSrc = () => 'file.sol:1';
|
|
17
|
+
const testContracts = [
|
|
18
|
+
'contracts/test/RenamedRetyped.sol:RenameV1',
|
|
19
|
+
'contracts/test/RenamedRetyped.sol:RenameV2',
|
|
20
|
+
'contracts/test/RenamedRetyped.sol:RetypeV1',
|
|
21
|
+
'contracts/test/RenamedRetyped.sol:RetypeV2',
|
|
22
|
+
'contracts/test/RenamedRetyped.sol:WronglyReportedRetypeV3',
|
|
23
|
+
'contracts/test/RenamedRetyped.sol:MissmatchingTypeRetypeV4',
|
|
24
|
+
'contracts/test/RenamedRetyped.sol:ConfusingRetypeV1',
|
|
25
|
+
'contracts/test/RenamedRetyped.sol:ConfusingRetypeV2',
|
|
26
|
+
'contracts/test/RenamedRetyped.sol:NonHardcodedRetypeV1',
|
|
27
|
+
'contracts/test/RenamedRetyped.sol:NonHardcodedRetypeV2',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
test.before(async t => {
|
|
31
|
+
const contracts: Record<string, ContractDefinition> = {};
|
|
32
|
+
const deref: Record<string, ASTDereferencer> = {};
|
|
33
|
+
const storageLayout: Record<string, StorageLayout> = {};
|
|
34
|
+
for (const contract of testContracts) {
|
|
35
|
+
const buildInfo = await artifacts.getBuildInfo(contract);
|
|
36
|
+
if (buildInfo === undefined) {
|
|
37
|
+
throw new Error(`Build info not found for contract ${contract}`);
|
|
38
|
+
}
|
|
39
|
+
const solcOutput = buildInfo.output;
|
|
40
|
+
for (const def of findAll('ContractDefinition', solcOutput.sources['contracts/test/RenamedRetyped.sol'].ast)) {
|
|
41
|
+
contracts[def.name] = def;
|
|
42
|
+
deref[def.name] = astDereferencer(solcOutput);
|
|
43
|
+
storageLayout[def.name] = (
|
|
44
|
+
solcOutput.contracts['contracts/test/RenamedRetyped.sol'][def.name] as any
|
|
45
|
+
).storageLayout;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
t.context.extractStorageLayout = name =>
|
|
50
|
+
extractStorageLayout(contracts[name], dummyDecodeSrc, deref[name], storageLayout[name]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
function getReport(original: StorageLayout, updated: StorageLayout) {
|
|
54
|
+
const originalDetailed = getDetailedLayout(original);
|
|
55
|
+
const updatedDetailed = getDetailedLayout(updated);
|
|
56
|
+
const comparator = new StorageLayoutComparator();
|
|
57
|
+
return comparator.compareLayouts(originalDetailed, updatedDetailed);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
test('succesful rename', t => {
|
|
61
|
+
const v1 = t.context.extractStorageLayout('RenameV1');
|
|
62
|
+
const v2 = t.context.extractStorageLayout('RenameV2');
|
|
63
|
+
const report = getReport(v1, v2);
|
|
64
|
+
t.true(report.ok);
|
|
65
|
+
t.snapshot(report.explain());
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('succesful retype', t => {
|
|
69
|
+
const v1 = t.context.extractStorageLayout('RetypeV1');
|
|
70
|
+
const v2 = t.context.extractStorageLayout('RetypeV2');
|
|
71
|
+
const report = getReport(v1, v2);
|
|
72
|
+
t.true(report.ok);
|
|
73
|
+
t.snapshot(report.explain());
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('wrongly reported retype', t => {
|
|
77
|
+
const v1 = t.context.extractStorageLayout('RetypeV1');
|
|
78
|
+
const v2 = t.context.extractStorageLayout('WronglyReportedRetypeV3');
|
|
79
|
+
const report = getReport(v1, v2);
|
|
80
|
+
t.false(report.ok);
|
|
81
|
+
t.snapshot(report.explain());
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('rightly reported retype but incompatible new type', t => {
|
|
85
|
+
const v1 = t.context.extractStorageLayout('RetypeV1');
|
|
86
|
+
const v2 = t.context.extractStorageLayout('MissmatchingTypeRetypeV4');
|
|
87
|
+
const report = getReport(v1, v2);
|
|
88
|
+
t.false(report.ok);
|
|
89
|
+
t.snapshot(report.explain());
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('confusing bad retype', t => {
|
|
93
|
+
const v1 = t.context.extractStorageLayout('ConfusingRetypeV1');
|
|
94
|
+
const v2 = t.context.extractStorageLayout('ConfusingRetypeV2');
|
|
95
|
+
const report = getReport(v1, v2);
|
|
96
|
+
t.false(report.ok);
|
|
97
|
+
t.snapshot(report.explain());
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('non-hardcoded retype', t => {
|
|
101
|
+
const v1 = t.context.extractStorageLayout('NonHardcodedRetypeV1');
|
|
102
|
+
const v2 = t.context.extractStorageLayout('NonHardcodedRetypeV2');
|
|
103
|
+
const report = getReport(v1, v2);
|
|
104
|
+
t.true(report.ok);
|
|
105
|
+
t.snapshot(report.explain());
|
|
106
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Snapshot report for `src/storage/report-rename-retype.test.ts`
|
|
2
|
+
|
|
3
|
+
The actual snapshot is saved in `report-rename-retype.test.ts.snap`.
|
|
4
|
+
|
|
5
|
+
Generated by [AVA](https://avajs.dev).
|
|
6
|
+
|
|
7
|
+
## succesful rename
|
|
8
|
+
|
|
9
|
+
> Snapshot 1
|
|
10
|
+
|
|
11
|
+
''
|
|
12
|
+
|
|
13
|
+
## succesful retype
|
|
14
|
+
|
|
15
|
+
> Snapshot 1
|
|
16
|
+
|
|
17
|
+
''
|
|
18
|
+
|
|
19
|
+
## wrongly reported retype
|
|
20
|
+
|
|
21
|
+
> Snapshot 1
|
|
22
|
+
|
|
23
|
+
`file.sol:1: Upgraded \`x\` to an incompatible type␊
|
|
24
|
+
- Bad upgrade from bool to uint8`
|
|
25
|
+
|
|
26
|
+
## rightly reported retype but incompatible new type
|
|
27
|
+
|
|
28
|
+
> Snapshot 1
|
|
29
|
+
|
|
30
|
+
`file.sol:1: Layout changed for \`x\` (bool -> bytes32)␊
|
|
31
|
+
- Number of bytes changed from 1 to 32`
|
|
32
|
+
|
|
33
|
+
## confusing bad retype
|
|
34
|
+
|
|
35
|
+
> Snapshot 1
|
|
36
|
+
|
|
37
|
+
`file.sol:1: Upgraded \`x\` to an incompatible type␊
|
|
38
|
+
- Bad upgrade from bool to uint8`
|
|
39
|
+
|
|
40
|
+
## non-hardcoded retype
|
|
41
|
+
|
|
42
|
+
> Snapshot 1
|
|
43
|
+
|
|
44
|
+
''
|
|
Binary file
|