@openzeppelin/upgrades-core 1.9.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 +110 -0
- package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +80 -0
- package/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +160 -0
- package/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +155 -0
- package/artifacts/AdminUpgradeabilityProxy.json +155 -0
- package/artifacts/ProxyAdmin.json +160 -0
- package/artifacts/contracts/proxy/AdminUpgradeabilityProxy.sol/AdminUpgradeabilityProxy.json +155 -0
- package/artifacts/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json +160 -0
- package/contracts/Initializable.sol +64 -0
- package/dist/ast-dereferencer.d.ts +8 -0
- package/dist/ast-dereferencer.d.ts.map +1 -0
- package/dist/ast-dereferencer.js +29 -0
- package/dist/ast-dereferencer.js.map +1 -0
- package/dist/deployment.d.ts +18 -0
- package/dist/deployment.d.ts.map +1 -0
- package/dist/deployment.js +110 -0
- package/dist/deployment.js.map +1 -0
- package/dist/deployment.test.d.ts +2 -0
- package/dist/deployment.test.d.ts.map +1 -0
- package/dist/deployment.test.js +92 -0
- package/dist/deployment.test.js.map +1 -0
- package/dist/eip-1967.d.ts +7 -0
- package/dist/eip-1967.d.ts.map +1 -0
- package/dist/eip-1967.js +63 -0
- package/dist/eip-1967.js.map +1 -0
- package/dist/error.d.ts +21 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +21 -0
- package/dist/error.js.map +1 -0
- package/dist/impl-store.d.ts +7 -0
- package/dist/impl-store.d.ts.map +1 -0
- package/dist/impl-store.js +94 -0
- package/dist/impl-store.js.map +1 -0
- package/dist/impl-store.test.d.ts +2 -0
- package/dist/impl-store.test.d.ts.map +1 -0
- package/dist/impl-store.test.js +55 -0
- package/dist/impl-store.test.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/levenshtein.d.ts +12 -0
- package/dist/levenshtein.d.ts.map +1 -0
- package/dist/levenshtein.js +89 -0
- package/dist/levenshtein.js.map +1 -0
- package/dist/levenshtein.test.d.ts +2 -0
- package/dist/levenshtein.test.d.ts.map +1 -0
- package/dist/levenshtein.test.js +88 -0
- package/dist/levenshtein.test.js.map +1 -0
- package/dist/link-refs.d.ts +11 -0
- package/dist/link-refs.d.ts.map +1 -0
- package/dist/link-refs.js +36 -0
- package/dist/link-refs.js.map +1 -0
- package/dist/link-refs.test.d.ts +2 -0
- package/dist/link-refs.test.d.ts.map +1 -0
- package/dist/link-refs.test.js +76 -0
- package/dist/link-refs.test.js.map +1 -0
- package/dist/manifest-storage-layout.d.ts +6 -0
- package/dist/manifest-storage-layout.d.ts.map +1 -0
- package/dist/manifest-storage-layout.js +95 -0
- package/dist/manifest-storage-layout.js.map +1 -0
- package/dist/manifest-storage-layout.test.d.ts +2 -0
- package/dist/manifest-storage-layout.test.d.ts.map +1 -0
- package/dist/manifest-storage-layout.test.js +105 -0
- package/dist/manifest-storage-layout.test.js.map +1 -0
- package/dist/manifest.d.ts +36 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +154 -0
- package/dist/manifest.js.map +1 -0
- package/dist/manifest.test.d.ts +2 -0
- package/dist/manifest.test.d.ts.map +1 -0
- package/dist/manifest.test.js +17 -0
- package/dist/manifest.test.js.map +1 -0
- package/dist/provider.d.ts +37 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +74 -0
- package/dist/provider.js.map +1 -0
- package/dist/provider.test.d.ts +2 -0
- package/dist/provider.test.d.ts.map +1 -0
- package/dist/provider.test.js +41 -0
- package/dist/provider.test.js.map +1 -0
- package/dist/scripts/migrate-oz-cli-project.d.ts +108 -0
- package/dist/scripts/migrate-oz-cli-project.d.ts.map +1 -0
- package/dist/scripts/migrate-oz-cli-project.js +321 -0
- package/dist/scripts/migrate-oz-cli-project.js.map +1 -0
- package/dist/scripts/migrate-oz-cli-project.test.d.ts +2 -0
- package/dist/scripts/migrate-oz-cli-project.test.d.ts.map +1 -0
- package/dist/scripts/migrate-oz-cli-project.test.js +60 -0
- package/dist/scripts/migrate-oz-cli-project.test.js.map +1 -0
- package/dist/set-proxy-kind.d.ts +5 -0
- package/dist/set-proxy-kind.d.ts.map +1 -0
- package/dist/set-proxy-kind.js +25 -0
- package/dist/set-proxy-kind.js.map +1 -0
- package/dist/solc-api.d.ts +39 -0
- package/dist/solc-api.d.ts.map +1 -0
- package/dist/solc-api.js +3 -0
- package/dist/solc-api.js.map +1 -0
- package/dist/src-decoder.d.ts +6 -0
- package/dist/src-decoder.d.ts.map +1 -0
- package/dist/src-decoder.js +36 -0
- package/dist/src-decoder.js.map +1 -0
- package/dist/src-decoder.test.d.ts +2 -0
- package/dist/src-decoder.test.d.ts.map +1 -0
- package/dist/src-decoder.test.js +29 -0
- package/dist/src-decoder.test.js.map +1 -0
- package/dist/storage/compare.d.ts +55 -0
- package/dist/storage/compare.d.ts.map +1 -0
- package/dist/storage/compare.js +181 -0
- package/dist/storage/compare.js.map +1 -0
- package/dist/storage/compat.d.ts +4 -0
- package/dist/storage/compat.d.ts.map +1 -0
- package/dist/storage/compat.js +9 -0
- package/dist/storage/compat.js.map +1 -0
- package/dist/storage/extract.d.ts +7 -0
- package/dist/storage/extract.d.ts.map +1 -0
- package/dist/storage/extract.js +86 -0
- package/dist/storage/extract.js.map +1 -0
- package/dist/storage/index.d.ts +8 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +65 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/layout.d.ts +31 -0
- package/dist/storage/layout.d.ts.map +1 -0
- package/dist/storage/layout.js +46 -0
- package/dist/storage/layout.js.map +1 -0
- package/dist/storage/report.d.ts +8 -0
- package/dist/storage/report.d.ts.map +1 -0
- package/dist/storage/report.js +175 -0
- package/dist/storage/report.js.map +1 -0
- package/dist/storage/report.test.d.ts +2 -0
- package/dist/storage/report.test.d.ts.map +1 -0
- package/dist/storage/report.test.js +82 -0
- package/dist/storage/report.test.js.map +1 -0
- package/dist/storage.test.d.ts +2 -0
- package/dist/storage.test.d.ts.map +1 -0
- package/dist/storage.test.js +436 -0
- package/dist/storage.test.js.map +1 -0
- package/dist/stub-provider.d.ts +14 -0
- package/dist/stub-provider.d.ts.map +1 -0
- package/dist/stub-provider.js +128 -0
- package/dist/stub-provider.js.map +1 -0
- package/dist/utils/assert.d.ts +3 -0
- package/dist/utils/assert.d.ts.map +1 -0
- package/dist/utils/assert.js +14 -0
- package/dist/utils/assert.js.map +1 -0
- package/dist/utils/curry.d.ts +6 -0
- package/dist/utils/curry.d.ts.map +1 -0
- package/dist/utils/curry.js +16 -0
- package/dist/utils/curry.js.map +1 -0
- package/dist/utils/debug.d.ts +4 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +8 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/deep-array.d.ts +3 -0
- package/dist/utils/deep-array.d.ts.map +1 -0
- package/dist/utils/deep-array.js +13 -0
- package/dist/utils/deep-array.js.map +1 -0
- package/dist/utils/deep-array.test.d.ts +2 -0
- package/dist/utils/deep-array.test.d.ts.map +1 -0
- package/dist/utils/deep-array.test.js +23 -0
- package/dist/utils/deep-array.test.js.map +1 -0
- package/dist/utils/function.d.ts +4 -0
- package/dist/utils/function.d.ts.map +1 -0
- package/dist/utils/function.js +43 -0
- package/dist/utils/function.js.map +1 -0
- package/dist/utils/function.test.d.ts +2 -0
- package/dist/utils/function.test.d.ts.map +1 -0
- package/dist/utils/function.test.js +34 -0
- package/dist/utils/function.test.js.map +1 -0
- package/dist/utils/indent.d.ts +2 -0
- package/dist/utils/indent.d.ts.map +1 -0
- package/dist/utils/indent.js +8 -0
- package/dist/utils/indent.js.map +1 -0
- package/dist/utils/is-nullish.d.ts +2 -0
- package/dist/utils/is-nullish.d.ts.map +1 -0
- package/dist/utils/is-nullish.js +8 -0
- package/dist/utils/is-nullish.js.map +1 -0
- package/dist/utils/is-nullish.test.d.ts +2 -0
- package/dist/utils/is-nullish.test.d.ts.map +1 -0
- package/dist/utils/is-nullish.test.js +17 -0
- package/dist/utils/is-nullish.test.js.map +1 -0
- package/dist/utils/is-value-type.d.ts +3 -0
- package/dist/utils/is-value-type.d.ts.map +1 -0
- package/dist/utils/is-value-type.js +8 -0
- package/dist/utils/is-value-type.js.map +1 -0
- package/dist/utils/itemize.d.ts +3 -0
- package/dist/utils/itemize.d.ts.map +1 -0
- package/dist/utils/itemize.js +18 -0
- package/dist/utils/itemize.js.map +1 -0
- package/dist/utils/log.d.ts +4 -0
- package/dist/utils/log.d.ts.map +1 -0
- package/dist/utils/log.js +35 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/make-non-enumerable.d.ts +2 -0
- package/dist/utils/make-non-enumerable.d.ts.map +1 -0
- package/dist/utils/make-non-enumerable.js +9 -0
- package/dist/utils/make-non-enumerable.js.map +1 -0
- package/dist/utils/map-values.d.ts +2 -0
- package/dist/utils/map-values.d.ts.map +1 -0
- package/dist/utils/map-values.js +12 -0
- package/dist/utils/map-values.js.map +1 -0
- package/dist/utils/parse-type-id.d.ts +9 -0
- package/dist/utils/parse-type-id.d.ts.map +1 -0
- package/dist/utils/parse-type-id.js +92 -0
- package/dist/utils/parse-type-id.js.map +1 -0
- package/dist/utils/parse-type-id.test.d.ts +2 -0
- package/dist/utils/parse-type-id.test.d.ts.map +1 -0
- package/dist/utils/parse-type-id.test.js +25 -0
- package/dist/utils/parse-type-id.test.js.map +1 -0
- package/dist/utils/pick.d.ts +2 -0
- package/dist/utils/pick.d.ts.map +1 -0
- package/dist/utils/pick.js +12 -0
- package/dist/utils/pick.js.map +1 -0
- package/dist/utils/type-id.d.ts +4 -0
- package/dist/utils/type-id.d.ts.map +1 -0
- package/dist/utils/type-id.js +65 -0
- package/dist/utils/type-id.js.map +1 -0
- package/dist/validate/compat.d.ts +6 -0
- package/dist/validate/compat.d.ts.map +1 -0
- package/dist/validate/compat.js +4 -0
- package/dist/validate/compat.js.map +1 -0
- package/dist/validate/data.d.ts +14 -0
- package/dist/validate/data.d.ts.map +1 -0
- package/dist/validate/data.js +50 -0
- package/dist/validate/data.js.map +1 -0
- package/dist/validate/error.d.ts +7 -0
- package/dist/validate/error.d.ts.map +1 -0
- package/dist/validate/error.js +78 -0
- package/dist/validate/error.js.map +1 -0
- package/dist/validate/index.d.ts +8 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +24 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/overrides.d.ts +14 -0
- package/dist/validate/overrides.d.ts.map +1 -0
- package/dist/validate/overrides.js +72 -0
- package/dist/validate/overrides.js.map +1 -0
- package/dist/validate/query.d.ts +15 -0
- package/dist/validate/query.d.ts.map +1 -0
- package/dist/validate/query.js +111 -0
- package/dist/validate/query.js.map +1 -0
- package/dist/validate/query.test.d.ts +2 -0
- package/dist/validate/query.test.d.ts.map +1 -0
- package/dist/validate/query.test.js +48 -0
- package/dist/validate/query.test.js.map +1 -0
- package/dist/validate/run.d.ts +39 -0
- package/dist/validate/run.d.ts.map +1 -0
- package/dist/validate/run.js +199 -0
- package/dist/validate/run.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +116 -0
- package/dist/validate.test.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +66 -0
- package/dist/version.js.map +1 -0
- package/dist/version.test.d.ts +2 -0
- package/dist/version.test.d.ts.map +1 -0
- package/dist/version.test.js +53 -0
- package/dist/version.test.js.map +1 -0
- package/package.json +58 -0
- package/src/ast-dereferencer.ts +42 -0
- package/src/deployment.test.ts +98 -0
- package/src/deployment.ts +122 -0
- package/src/eip-1967.ts +77 -0
- package/src/error.ts +26 -0
- package/src/impl-store.test.ts +59 -0
- package/src/impl-store.ts +124 -0
- package/src/index.ts +18 -0
- package/src/levenshtein.test.ts +91 -0
- package/src/levenshtein.ts +116 -0
- package/src/link-refs.test.ts +77 -0
- package/src/link-refs.ts +41 -0
- package/src/manifest-storage-layout.test.ts +118 -0
- package/src/manifest-storage-layout.ts +107 -0
- package/src/manifest.test.ts +13 -0
- package/src/manifest.ts +178 -0
- package/src/provider.test.ts +43 -0
- package/src/provider.ts +103 -0
- package/src/scripts/migratable-manifest.test.json +175 -0
- package/src/scripts/migrate-oz-cli-project.test.ts +70 -0
- package/src/scripts/migrate-oz-cli-project.test.ts.md +146 -0
- package/src/scripts/migrate-oz-cli-project.test.ts.snap +0 -0
- package/src/scripts/migrate-oz-cli-project.ts +484 -0
- package/src/scripts/project-file.test.json +25 -0
- package/src/set-proxy-kind.ts +27 -0
- package/src/solc-api.ts +42 -0
- package/src/src-decoder.test.ts +30 -0
- package/src/src-decoder.ts +37 -0
- package/src/storage/compare.ts +249 -0
- package/src/storage/compat.ts +3 -0
- package/src/storage/extract.ts +110 -0
- package/src/storage/index.ts +73 -0
- package/src/storage/layout.ts +88 -0
- package/src/storage/report.test.ts +95 -0
- package/src/storage/report.test.ts.md +154 -0
- package/src/storage/report.test.ts.snap +0 -0
- package/src/storage/report.ts +215 -0
- package/src/storage.test.ts +479 -0
- package/src/storage.test.ts.md +643 -0
- package/src/storage.test.ts.snap +0 -0
- package/src/stub-provider.ts +120 -0
- package/src/utils/assert.ts +9 -0
- package/src/utils/curry.ts +17 -0
- package/src/utils/debug.ts +3 -0
- package/src/utils/deep-array.test.ts +21 -0
- package/src/utils/deep-array.ts +9 -0
- package/src/utils/function.test.ts +37 -0
- package/src/utils/function.ts +53 -0
- package/src/utils/indent.ts +3 -0
- package/src/utils/is-nullish.test.ts +15 -0
- package/src/utils/is-nullish.ts +3 -0
- package/src/utils/is-value-type.ts +5 -0
- package/src/utils/itemize.ts +16 -0
- package/src/utils/log.ts +34 -0
- package/src/utils/make-non-enumerable.ts +4 -0
- package/src/utils/map-values.ts +7 -0
- package/src/utils/parse-type-id.test.ts +22 -0
- package/src/utils/parse-type-id.test.ts.md +264 -0
- package/src/utils/parse-type-id.test.ts.snap +0 -0
- package/src/utils/parse-type-id.ts +104 -0
- package/src/utils/pick.ts +7 -0
- package/src/utils/type-id.ts +57 -0
- package/src/validate/compat.ts +9 -0
- package/src/validate/data.ts +55 -0
- package/src/validate/error.ts +75 -0
- package/src/validate/index.ts +17 -0
- package/src/validate/overrides.ts +93 -0
- package/src/validate/query.test.ts +48 -0
- package/src/validate/query.ts +127 -0
- package/src/validate/run.ts +278 -0
- package/src/validate.test.ts +133 -0
- package/src/version.test.ts +59 -0
- package/src/version.ts +71 -0
|
Binary file
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
|
|
3
|
+
// This module parses type identifiers.
|
|
4
|
+
|
|
5
|
+
export interface ParsedTypeId {
|
|
6
|
+
id: string;
|
|
7
|
+
head: string;
|
|
8
|
+
args?: ParsedTypeId[];
|
|
9
|
+
tail?: string;
|
|
10
|
+
rets?: ParsedTypeId[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// The examples below illustrate the meaning of these properties.
|
|
14
|
+
|
|
15
|
+
// 1) id = t_struct(MyStruct)storage
|
|
16
|
+
// └──────┘ └──────┘ └─────┘
|
|
17
|
+
// head args[0] tail
|
|
18
|
+
// rets = undefined
|
|
19
|
+
|
|
20
|
+
// 2) id = t_function_internal_nonpayable(t_uint256,t_uint256)returns(t_address)
|
|
21
|
+
// └────────────────────────────┘ └───────┘ └───────┘ └───────┘
|
|
22
|
+
// head args[0] args[1] rets[0]
|
|
23
|
+
// tail = undefined
|
|
24
|
+
|
|
25
|
+
// 3) id = t_uint256
|
|
26
|
+
// └───────┘
|
|
27
|
+
// head
|
|
28
|
+
// args = undefined
|
|
29
|
+
// tail = undefined
|
|
30
|
+
// rets = undefined
|
|
31
|
+
|
|
32
|
+
export function parseTypeId(id: string): ParsedTypeId {
|
|
33
|
+
const matcher = new StatefulGlobalMatcher(id);
|
|
34
|
+
|
|
35
|
+
function parseList(): ParsedTypeId[] {
|
|
36
|
+
const args = [];
|
|
37
|
+
|
|
38
|
+
let i = matcher.index;
|
|
39
|
+
let delim;
|
|
40
|
+
|
|
41
|
+
while ((delim = matcher.match(/[(),]/))) {
|
|
42
|
+
if (delim[0] === '(') {
|
|
43
|
+
let depth = 1;
|
|
44
|
+
while (depth > 0) {
|
|
45
|
+
const paren = matcher.match(/[()]/)?.[0];
|
|
46
|
+
if (paren === '(') {
|
|
47
|
+
depth += 1;
|
|
48
|
+
} else if (paren === ')') {
|
|
49
|
+
depth -= 1;
|
|
50
|
+
} else {
|
|
51
|
+
throw new Error(`Malformed type id ${id}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
const subtype = id.slice(i, delim.index);
|
|
56
|
+
if (subtype) {
|
|
57
|
+
args.push(parseTypeId(subtype));
|
|
58
|
+
}
|
|
59
|
+
i = delim.index + 1;
|
|
60
|
+
if (delim[0] === ')') {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return args;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const openArgs = matcher.match(/\(/);
|
|
70
|
+
const head = id.slice(0, openArgs?.index);
|
|
71
|
+
let args, tail, rets;
|
|
72
|
+
|
|
73
|
+
if (openArgs) {
|
|
74
|
+
args = parseList();
|
|
75
|
+
|
|
76
|
+
const startTail = matcher.index;
|
|
77
|
+
const openRet = matcher.match(/\(/);
|
|
78
|
+
|
|
79
|
+
if (!openRet) {
|
|
80
|
+
tail = id.slice(startTail) || undefined;
|
|
81
|
+
} else {
|
|
82
|
+
assert(id.slice(startTail, openRet.index) === 'returns', `Malformed type id ${id}`);
|
|
83
|
+
rets = parseList();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { id, head, args, tail, rets };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
class StatefulGlobalMatcher {
|
|
91
|
+
index = 0;
|
|
92
|
+
|
|
93
|
+
constructor(private readonly text: string) {}
|
|
94
|
+
|
|
95
|
+
match(re: RegExp | string): RegExpExecArray | null {
|
|
96
|
+
const gre = new RegExp(re, 'g');
|
|
97
|
+
gre.lastIndex = this.index;
|
|
98
|
+
const match = gre.exec(this.text);
|
|
99
|
+
if (match !== null) {
|
|
100
|
+
this.index = gre.lastIndex;
|
|
101
|
+
}
|
|
102
|
+
return match;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
|
|
3
|
+
// Type Identifiers in the AST are for some reason encoded so that they don't
|
|
4
|
+
// contain parentheses or commas, which have been substituted as follows:
|
|
5
|
+
// ( -> $_
|
|
6
|
+
// ) -> _$
|
|
7
|
+
// , -> _$_
|
|
8
|
+
// This is particularly hard to decode because it is not a prefix-free code.
|
|
9
|
+
// Thus, the following regex has to perform a lookahead to make sure it gets
|
|
10
|
+
// the substitution right.
|
|
11
|
+
export function decodeTypeIdentifier(typeIdentifier: string): string {
|
|
12
|
+
return typeIdentifier.replace(/(\$_|_\$_|_\$)(?=(\$_|_\$_|_\$)*([^_$]|$))/g, m => {
|
|
13
|
+
switch (m) {
|
|
14
|
+
case '$_':
|
|
15
|
+
return '(';
|
|
16
|
+
case '_$':
|
|
17
|
+
return ')';
|
|
18
|
+
case '_$_':
|
|
19
|
+
return ',';
|
|
20
|
+
default:
|
|
21
|
+
throw new Error('Unreachable');
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Some Type Identifiers contain a _storage_ptr suffix, but the _ptr part
|
|
27
|
+
// appears in some places and not others. We remove it to get consistent type
|
|
28
|
+
// ids from the different places in the AST.
|
|
29
|
+
export function normalizeTypeIdentifier(typeIdentifier: string): string {
|
|
30
|
+
return decodeTypeIdentifier(typeIdentifier).replace(/_storage_ptr\b/g, '_storage');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Type Identifiers contain AST id numbers, which makes them sensitive to
|
|
34
|
+
// unrelated changes in the source code. This function stabilizes a type
|
|
35
|
+
// identifier by removing all AST ids.
|
|
36
|
+
export function stabilizeTypeIdentifier(typeIdentifier: string): string {
|
|
37
|
+
let decoded = decodeTypeIdentifier(typeIdentifier);
|
|
38
|
+
const re = /(t_struct|t_enum|t_contract)\(/g;
|
|
39
|
+
let match;
|
|
40
|
+
while ((match = re.exec(decoded))) {
|
|
41
|
+
let i;
|
|
42
|
+
let d = 1;
|
|
43
|
+
for (i = match.index + match[0].length; d !== 0; i++) {
|
|
44
|
+
assert(i < decoded.length, 'index out of bounds');
|
|
45
|
+
const c = decoded[i];
|
|
46
|
+
if (c === '(') {
|
|
47
|
+
d += 1;
|
|
48
|
+
} else if (c === ')') {
|
|
49
|
+
d -= 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const re2 = /\d+_?/y;
|
|
53
|
+
re2.lastIndex = i;
|
|
54
|
+
decoded = decoded.replace(re2, '');
|
|
55
|
+
}
|
|
56
|
+
return decoded;
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Legacy interface for backwards compatibility
|
|
2
|
+
|
|
3
|
+
import { ContractValidation, ValidationRunData } from './run';
|
|
4
|
+
|
|
5
|
+
export type RunValidation = ValidationRunData;
|
|
6
|
+
export type ValidationLog = RunValidation[];
|
|
7
|
+
export type Validation = RunValidation;
|
|
8
|
+
|
|
9
|
+
export type ValidationResult = ContractValidation;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import versions from 'compare-versions';
|
|
2
|
+
|
|
3
|
+
import { ValidationRunData } from './run';
|
|
4
|
+
|
|
5
|
+
type ValidationDataV1 = ValidationRunData;
|
|
6
|
+
|
|
7
|
+
type ValidationDataV2 = ValidationRunData[];
|
|
8
|
+
|
|
9
|
+
const currentMajor = '3';
|
|
10
|
+
const currentVersion = '3.2';
|
|
11
|
+
|
|
12
|
+
interface ValidationDataV3 {
|
|
13
|
+
version: '3' | '3.1' | '3.2';
|
|
14
|
+
log: ValidationRunData[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ValidationDataCurrent = ValidationDataV3;
|
|
18
|
+
|
|
19
|
+
export type ValidationData = ValidationDataV1 | ValidationDataV2 | ValidationDataV3;
|
|
20
|
+
|
|
21
|
+
export function normalizeValidationData(data: ValidationData): ValidationDataCurrent {
|
|
22
|
+
if (isCurrentValidationData(data, false)) {
|
|
23
|
+
return data;
|
|
24
|
+
} else if (Array.isArray(data)) {
|
|
25
|
+
return { version: currentVersion, log: data };
|
|
26
|
+
} else {
|
|
27
|
+
return { version: currentVersion, log: [data] };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isCurrentValidationData(data: ValidationData, exact = true): data is ValidationDataCurrent {
|
|
32
|
+
if (Array.isArray(data)) {
|
|
33
|
+
return false;
|
|
34
|
+
} else if (!('version' in data)) {
|
|
35
|
+
return false;
|
|
36
|
+
} else if (typeof data.version === 'string' && versions.validate(data.version)) {
|
|
37
|
+
if (exact) {
|
|
38
|
+
return data.version === currentVersion;
|
|
39
|
+
} else {
|
|
40
|
+
return versions.compare(data.version, `${currentMajor}.*`, '=');
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error('Unknown version or malformed validation data');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function concatRunData(
|
|
48
|
+
newRunData: ValidationRunData,
|
|
49
|
+
previousData?: ValidationDataCurrent,
|
|
50
|
+
): ValidationDataCurrent {
|
|
51
|
+
return {
|
|
52
|
+
version: currentVersion,
|
|
53
|
+
log: [newRunData].concat(previousData?.log ?? []),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
import { ValidationError } from './run';
|
|
4
|
+
import { UpgradesError, ErrorDescriptions } from '../error';
|
|
5
|
+
|
|
6
|
+
export class ValidationErrors extends UpgradesError {
|
|
7
|
+
constructor(contractName: string, readonly errors: ValidationError[]) {
|
|
8
|
+
super(`Contract \`${contractName}\` is not upgrade safe`, () => {
|
|
9
|
+
return errors.map(describeError).join('\n\n');
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const errorInfo: ErrorDescriptions<ValidationError> = {
|
|
15
|
+
constructor: {
|
|
16
|
+
msg: e => `Contract \`${e.contract}\` has a constructor`,
|
|
17
|
+
hint: () => 'Define an initializer instead',
|
|
18
|
+
link: 'https://zpl.in/upgrades/error-001',
|
|
19
|
+
},
|
|
20
|
+
delegatecall: {
|
|
21
|
+
msg: () => `Use of delegatecall is not allowed`,
|
|
22
|
+
link: 'https://zpl.in/upgrades/error-002',
|
|
23
|
+
},
|
|
24
|
+
selfdestruct: {
|
|
25
|
+
msg: () => `Use of selfdestruct is not allowed`,
|
|
26
|
+
link: 'https://zpl.in/upgrades/error-003',
|
|
27
|
+
},
|
|
28
|
+
'state-variable-assignment': {
|
|
29
|
+
msg: e => `Variable \`${e.name}\` is assigned an initial value`,
|
|
30
|
+
hint: () => 'Move the assignment to the initializer',
|
|
31
|
+
link: 'https://zpl.in/upgrades/error-004',
|
|
32
|
+
},
|
|
33
|
+
'state-variable-immutable': {
|
|
34
|
+
msg: e => `Variable \`${e.name}\` is immutable`,
|
|
35
|
+
hint: () => `Use a constant or mutable variable instead`,
|
|
36
|
+
link: 'https://zpl.in/upgrades/error-005',
|
|
37
|
+
},
|
|
38
|
+
'external-library-linking': {
|
|
39
|
+
msg: e => `Linking external libraries like \`${e.name}\` is not yet supported`,
|
|
40
|
+
hint: () =>
|
|
41
|
+
`Use libraries with internal functions only, or skip this check with the \`unsafeAllowLinkedLibraries\` flag \n` +
|
|
42
|
+
` if you have manually checked that the libraries are upgrade safe`,
|
|
43
|
+
link: 'https://zpl.in/upgrades/error-006',
|
|
44
|
+
},
|
|
45
|
+
'struct-definition': {
|
|
46
|
+
msg: e => `Structs like \`${e.name}\` are supported in the latest version of the plugin`,
|
|
47
|
+
hint: () => `Update your dependency and run again`,
|
|
48
|
+
},
|
|
49
|
+
'enum-definition': {
|
|
50
|
+
msg: e => `Enums like \`${e.name}\` are supported in the latest version of the plugin`,
|
|
51
|
+
hint: () => `Update your dependency and run again`,
|
|
52
|
+
},
|
|
53
|
+
'missing-public-upgradeto': {
|
|
54
|
+
msg: () => `Implementation is missing a public \`upgradeTo(address)\` function`,
|
|
55
|
+
hint: () =>
|
|
56
|
+
`Inherit UUPSUpgradeable to include this function in your contract\n` +
|
|
57
|
+
` @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol`,
|
|
58
|
+
link: 'https://zpl.in/upgrades/error-008',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function describeError(e: ValidationError): string {
|
|
63
|
+
const info = errorInfo[e.kind];
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
65
|
+
const log = [chalk.bold(e.src) + ': ' + info.msg(e as any)];
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
const hint = info.hint?.(e as any);
|
|
68
|
+
if (hint) {
|
|
69
|
+
log.push(hint);
|
|
70
|
+
}
|
|
71
|
+
if (info.link) {
|
|
72
|
+
log.push(chalk.dim(info.link));
|
|
73
|
+
}
|
|
74
|
+
return log.join('\n ');
|
|
75
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { validate, ValidationRunData, ContractValidation } from './run';
|
|
2
|
+
export { ValidationOptions, withValidationDefaults } from './overrides';
|
|
3
|
+
export { ValidationErrors } from './error';
|
|
4
|
+
export { RunValidation, ValidationLog, Validation, ValidationResult } from './compat';
|
|
5
|
+
export { ValidationData, ValidationDataCurrent, isCurrentValidationData, concatRunData } from './data';
|
|
6
|
+
export {
|
|
7
|
+
getContractVersion,
|
|
8
|
+
getContractNameAndRunValidation,
|
|
9
|
+
getStorageLayout,
|
|
10
|
+
assertUpgradeSafe,
|
|
11
|
+
getUnlinkedBytecode,
|
|
12
|
+
getErrors,
|
|
13
|
+
isUpgradeSafe,
|
|
14
|
+
} from './query';
|
|
15
|
+
|
|
16
|
+
// Backwards compatibility
|
|
17
|
+
export { silenceWarnings } from '../utils/log';
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { ValidationError } from './run';
|
|
2
|
+
import { ProxyDeployment } from '../manifest';
|
|
3
|
+
import { logWarning } from '../utils/log';
|
|
4
|
+
|
|
5
|
+
// Backwards compatibility
|
|
6
|
+
export { silenceWarnings } from '../utils/log';
|
|
7
|
+
|
|
8
|
+
export interface ValidationOptions {
|
|
9
|
+
unsafeAllowCustomTypes?: boolean;
|
|
10
|
+
unsafeAllowLinkedLibraries?: boolean;
|
|
11
|
+
unsafeAllowRenames?: boolean;
|
|
12
|
+
unsafeAllow?: ValidationError['kind'][];
|
|
13
|
+
kind?: ProxyDeployment['kind'];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ValidationErrorUnsafeMessages: Record<ValidationError['kind'], string[]> = {
|
|
17
|
+
'state-variable-assignment': [
|
|
18
|
+
`You are using the \`unsafeAllow.state-variable-assignment\` flag.`,
|
|
19
|
+
`The value will be stored in the implementation and not the proxy.`,
|
|
20
|
+
],
|
|
21
|
+
'state-variable-immutable': [`You are using the \`unsafeAllow.state-variable-immutable\` flag.`],
|
|
22
|
+
'external-library-linking': [
|
|
23
|
+
`You are using the \`unsafeAllow.external-library-linking\` flag to include external libraries.`,
|
|
24
|
+
`Make sure you have manually checked that the linked libraries are upgrade safe.`,
|
|
25
|
+
],
|
|
26
|
+
'struct-definition': [
|
|
27
|
+
`You are using the \`unsafeAllow.struct-definition\` flag to skip storage checks for structs.`,
|
|
28
|
+
`Make sure you have manually checked the storage layout for incompatibilities.`,
|
|
29
|
+
],
|
|
30
|
+
'enum-definition': [
|
|
31
|
+
`You are using the \`unsafeAllow.enum-definition\` flag to skip storage checks for enums.`,
|
|
32
|
+
`Make sure you have manually checked the storage layout for incompatibilities.`,
|
|
33
|
+
],
|
|
34
|
+
constructor: [`You are using the \`unsafeAllow.constructor\` flag.`],
|
|
35
|
+
delegatecall: [`You are using the \`unsafeAllow.delegatecall\` flag.`],
|
|
36
|
+
selfdestruct: [`You are using the \`unsafeAllow.selfdestruct\` flag.`],
|
|
37
|
+
'missing-public-upgradeto': [
|
|
38
|
+
`You are using the \`unsafeAllow.missing-public-upgradeto\` flag with uups proxy.`,
|
|
39
|
+
`Not having a public upgradeTo function in your implementation can break upgradeability.`,
|
|
40
|
+
`Some implementation might check that onchain, and cause the upgrade to revert.`,
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export function withValidationDefaults(opts: ValidationOptions): Required<ValidationOptions> {
|
|
45
|
+
const unsafeAllow = opts.unsafeAllow ?? [];
|
|
46
|
+
const unsafeAllowCustomTypes =
|
|
47
|
+
opts.unsafeAllowCustomTypes ??
|
|
48
|
+
(unsafeAllow.includes('struct-definition') && unsafeAllow.includes('enum-definition'));
|
|
49
|
+
const unsafeAllowLinkedLibraries =
|
|
50
|
+
opts.unsafeAllowLinkedLibraries ?? unsafeAllow.includes('external-library-linking');
|
|
51
|
+
|
|
52
|
+
if (unsafeAllowCustomTypes) {
|
|
53
|
+
unsafeAllow.push('enum-definition', 'struct-definition');
|
|
54
|
+
}
|
|
55
|
+
if (unsafeAllowLinkedLibraries) {
|
|
56
|
+
unsafeAllow.push('external-library-linking');
|
|
57
|
+
}
|
|
58
|
+
const kind = opts.kind ?? 'transparent';
|
|
59
|
+
|
|
60
|
+
const unsafeAllowRenames = opts.unsafeAllowRenames ?? false;
|
|
61
|
+
|
|
62
|
+
return { unsafeAllowCustomTypes, unsafeAllowLinkedLibraries, unsafeAllowRenames, unsafeAllow, kind };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function processExceptions(
|
|
66
|
+
contractName: string,
|
|
67
|
+
errors: ValidationError[],
|
|
68
|
+
opts: ValidationOptions,
|
|
69
|
+
): ValidationError[] {
|
|
70
|
+
const { unsafeAllow } = withValidationDefaults(opts);
|
|
71
|
+
|
|
72
|
+
if (opts.kind === 'transparent') {
|
|
73
|
+
errors = errors.filter(error => error.kind !== 'missing-public-upgradeto');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for (const [errorType, errorDescription] of Object.entries(ValidationErrorUnsafeMessages)) {
|
|
77
|
+
if (unsafeAllow.includes(errorType as ValidationError['kind'])) {
|
|
78
|
+
let exceptionsFound = false;
|
|
79
|
+
|
|
80
|
+
errors = errors.filter(error => {
|
|
81
|
+
const isException = errorType === error.kind;
|
|
82
|
+
exceptionsFound = exceptionsFound || isException;
|
|
83
|
+
return !isException;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (exceptionsFound && errorDescription) {
|
|
87
|
+
logWarning(`Potentially unsafe deployment of ${contractName}`, errorDescription);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return errors;
|
|
93
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
|
|
3
|
+
import { ContractValidation, ValidationRunData } from './run';
|
|
4
|
+
import { getUnlinkedBytecode } from './query';
|
|
5
|
+
import { getVersion } from '../version';
|
|
6
|
+
|
|
7
|
+
test('getUnlinkedBytecode', t => {
|
|
8
|
+
const unlinkedBytecode = '0x12__$5ae0c2211b657f8a7ca51e0b14f2a8333d$__78';
|
|
9
|
+
const linkedBytecode = '0x12456456456456456456456456456456456456456478';
|
|
10
|
+
|
|
11
|
+
const validation: Record<string, Partial<ContractValidation>> = {
|
|
12
|
+
B: {
|
|
13
|
+
version: getVersion(unlinkedBytecode),
|
|
14
|
+
linkReferences: [
|
|
15
|
+
{
|
|
16
|
+
src: '',
|
|
17
|
+
name: '',
|
|
18
|
+
start: 50,
|
|
19
|
+
length: 20,
|
|
20
|
+
placeholder: '__$5ae0c2211b657f8a7ca51e0b14f2a8333d$__',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
src: '',
|
|
24
|
+
name: '',
|
|
25
|
+
start: 30,
|
|
26
|
+
length: 20,
|
|
27
|
+
placeholder: '__$5ae0c2211b657f8a7ca51e0b14f2a8333d$__',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
A: {
|
|
32
|
+
version: getVersion(unlinkedBytecode),
|
|
33
|
+
linkReferences: [
|
|
34
|
+
{
|
|
35
|
+
src: '',
|
|
36
|
+
name: '',
|
|
37
|
+
start: 1,
|
|
38
|
+
length: 20,
|
|
39
|
+
placeholder: '__$5ae0c2211b657f8a7ca51e0b14f2a8333d$__',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const recovered = getUnlinkedBytecode(validation as ValidationRunData, linkedBytecode);
|
|
46
|
+
|
|
47
|
+
t.is(recovered, unlinkedBytecode);
|
|
48
|
+
});
|