@openzeppelin/upgrades-core 1.29.0 → 1.30.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.
Files changed (161) hide show
  1. package/dist/call-optional-signature.d.ts +3 -0
  2. package/dist/call-optional-signature.d.ts.map +1 -0
  3. package/dist/call-optional-signature.js +24 -0
  4. package/dist/call-optional-signature.js.map +1 -0
  5. package/dist/cli/validate/build-info-file.d.ts +4 -0
  6. package/dist/cli/validate/build-info-file.d.ts.map +1 -1
  7. package/dist/cli/validate/build-info-file.js +5 -2
  8. package/dist/cli/validate/build-info-file.js.map +1 -1
  9. package/dist/cli/validate/build-info-file.test.js +4 -1
  10. package/dist/cli/validate/build-info-file.test.js.map +1 -1
  11. package/dist/cli/validate/upgradeability-assessment.js +2 -6
  12. package/dist/cli/validate/upgradeability-assessment.js.map +1 -1
  13. package/dist/cli/validate/validations.d.ts.map +1 -1
  14. package/dist/cli/validate/validations.js +5 -4
  15. package/dist/cli/validate/validations.js.map +1 -1
  16. package/dist/impl-address.d.ts.map +1 -1
  17. package/dist/impl-address.js +9 -16
  18. package/dist/impl-address.js.map +1 -1
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +7 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/levenshtein.d.ts +6 -0
  24. package/dist/levenshtein.d.ts.map +1 -1
  25. package/dist/levenshtein.js.map +1 -1
  26. package/dist/solc-api.d.ts +14 -0
  27. package/dist/solc-api.d.ts.map +1 -1
  28. package/dist/standalone.d.ts +4 -1
  29. package/dist/standalone.d.ts.map +1 -1
  30. package/dist/standalone.js +6 -3
  31. package/dist/standalone.js.map +1 -1
  32. package/dist/standalone.test.js +17 -0
  33. package/dist/standalone.test.js.map +1 -1
  34. package/dist/storage/compare.d.ts +2 -1
  35. package/dist/storage/compare.d.ts.map +1 -1
  36. package/dist/storage/compare.js +25 -2
  37. package/dist/storage/compare.js.map +1 -1
  38. package/dist/storage/extract.d.ts +15 -3
  39. package/dist/storage/extract.d.ts.map +1 -1
  40. package/dist/storage/extract.js +48 -21
  41. package/dist/storage/extract.js.map +1 -1
  42. package/dist/storage/index.d.ts.map +1 -1
  43. package/dist/storage/index.js +15 -1
  44. package/dist/storage/index.js.map +1 -1
  45. package/dist/storage/layout.d.ts +1 -0
  46. package/dist/storage/layout.d.ts.map +1 -1
  47. package/dist/storage/layout.js.map +1 -1
  48. package/dist/storage/namespace.d.ts +35 -0
  49. package/dist/storage/namespace.d.ts.map +1 -0
  50. package/dist/storage/namespace.js +219 -0
  51. package/dist/storage/namespace.js.map +1 -0
  52. package/dist/storage/report.js +6 -0
  53. package/dist/storage/report.js.map +1 -1
  54. package/dist/storage-namespaced-conflicts-layout.test.d.ts +2 -0
  55. package/dist/storage-namespaced-conflicts-layout.test.d.ts.map +1 -0
  56. package/dist/storage-namespaced-conflicts-layout.test.js +69 -0
  57. package/dist/storage-namespaced-conflicts-layout.test.js.map +1 -0
  58. package/dist/storage-namespaced-conflicts.test.d.ts +2 -0
  59. package/dist/storage-namespaced-conflicts.test.d.ts.map +1 -0
  60. package/dist/storage-namespaced-conflicts.test.js +45 -0
  61. package/dist/storage-namespaced-conflicts.test.js.map +1 -0
  62. package/dist/storage-namespaced-layout.test.d.ts +2 -0
  63. package/dist/storage-namespaced-layout.test.d.ts.map +1 -0
  64. package/dist/storage-namespaced-layout.test.js +59 -0
  65. package/dist/storage-namespaced-layout.test.js.map +1 -0
  66. package/dist/storage-namespaced-outside-contract.test.d.ts +2 -0
  67. package/dist/storage-namespaced-outside-contract.test.d.ts.map +1 -0
  68. package/dist/storage-namespaced-outside-contract.test.js +22 -0
  69. package/dist/storage-namespaced-outside-contract.test.js.map +1 -0
  70. package/dist/storage-namespaced-solc-versions.test.d.ts +2 -0
  71. package/dist/storage-namespaced-solc-versions.test.d.ts.map +1 -0
  72. package/dist/storage-namespaced-solc-versions.test.js +42 -0
  73. package/dist/storage-namespaced-solc-versions.test.js.map +1 -0
  74. package/dist/storage-namespaced-udvt.test.d.ts +2 -0
  75. package/dist/storage-namespaced-udvt.test.d.ts.map +1 -0
  76. package/dist/storage-namespaced-udvt.test.js +130 -0
  77. package/dist/storage-namespaced-udvt.test.js.map +1 -0
  78. package/dist/storage-namespaced.test.d.ts +2 -0
  79. package/dist/storage-namespaced.test.d.ts.map +1 -0
  80. package/dist/storage-namespaced.test.js +132 -0
  81. package/dist/storage-namespaced.test.js.map +1 -0
  82. package/dist/upgrade-interface-version.d.ts +3 -0
  83. package/dist/upgrade-interface-version.d.ts.map +1 -0
  84. package/dist/upgrade-interface-version.js +25 -0
  85. package/dist/upgrade-interface-version.js.map +1 -0
  86. package/dist/upgrade-interface-version.test.d.ts +2 -0
  87. package/dist/upgrade-interface-version.test.d.ts.map +1 -0
  88. package/dist/upgrade-interface-version.test.js +32 -0
  89. package/dist/upgrade-interface-version.test.js.map +1 -0
  90. package/dist/utils/annotations.d.ts +4 -0
  91. package/dist/utils/annotations.d.ts.map +1 -1
  92. package/dist/utils/annotations.js +9 -1
  93. package/dist/utils/annotations.js.map +1 -1
  94. package/dist/utils/make-namespaced.d.ts +20 -0
  95. package/dist/utils/make-namespaced.d.ts.map +1 -0
  96. package/dist/utils/make-namespaced.js +131 -0
  97. package/dist/utils/make-namespaced.js.map +1 -0
  98. package/dist/utils/make-namespaced.test.d.ts +2 -0
  99. package/dist/utils/make-namespaced.test.d.ts.map +1 -0
  100. package/dist/utils/make-namespaced.test.js +59 -0
  101. package/dist/utils/make-namespaced.test.js.map +1 -0
  102. package/dist/utils/stabilize-layout.d.ts +11 -0
  103. package/dist/utils/stabilize-layout.d.ts.map +1 -1
  104. package/dist/utils/stabilize-layout.js +5 -0
  105. package/dist/utils/stabilize-layout.js.map +1 -1
  106. package/dist/validate/query.d.ts.map +1 -1
  107. package/dist/validate/query.js +4 -2
  108. package/dist/validate/query.js.map +1 -1
  109. package/dist/validate/run.d.ts +18 -2
  110. package/dist/validate/run.d.ts.map +1 -1
  111. package/dist/validate/run.js +80 -2
  112. package/dist/validate/run.js.map +1 -1
  113. package/package.json +3 -3
  114. package/src/call-optional-signature.ts +20 -0
  115. package/src/cli/validate/build-info-file.test.ts +4 -1
  116. package/src/cli/validate/build-info-file.ts +12 -2
  117. package/src/cli/validate/upgradeability-assessment.ts +1 -6
  118. package/src/cli/validate/validations.ts +6 -5
  119. package/src/impl-address.ts +9 -20
  120. package/src/index.ts +4 -0
  121. package/src/levenshtein.ts +7 -0
  122. package/src/solc-api.ts +14 -0
  123. package/src/standalone.test.ts +26 -0
  124. package/src/standalone.ts +6 -2
  125. package/src/storage/compare.ts +34 -2
  126. package/src/storage/extract.ts +68 -20
  127. package/src/storage/index.ts +22 -1
  128. package/src/storage/layout.ts +1 -0
  129. package/src/storage/namespace.ts +267 -0
  130. package/src/storage/report.ts +8 -0
  131. package/src/storage-0.8.test.ts.md +4 -0
  132. package/src/storage-0.8.test.ts.snap +0 -0
  133. package/src/storage-memory-0.5.test.ts.md +2 -0
  134. package/src/storage-memory-0.5.test.ts.snap +0 -0
  135. package/src/storage-namespaced-conflicts-layout.test.ts +96 -0
  136. package/src/storage-namespaced-conflicts-layout.test.ts.md +53 -0
  137. package/src/storage-namespaced-conflicts-layout.test.ts.snap +0 -0
  138. package/src/storage-namespaced-conflicts.test.ts +54 -0
  139. package/src/storage-namespaced-conflicts.test.ts.md +53 -0
  140. package/src/storage-namespaced-conflicts.test.ts.snap +0 -0
  141. package/src/storage-namespaced-layout.test.ts +77 -0
  142. package/src/storage-namespaced-layout.test.ts.md +67 -0
  143. package/src/storage-namespaced-layout.test.ts.snap +0 -0
  144. package/src/storage-namespaced-outside-contract.test.ts +24 -0
  145. package/src/storage-namespaced-solc-versions.test.ts +59 -0
  146. package/src/storage-namespaced-udvt.test.ts +160 -0
  147. package/src/storage-namespaced.test.ts +146 -0
  148. package/src/storage-namespaced.test.ts.md +89 -0
  149. package/src/storage-namespaced.test.ts.snap +0 -0
  150. package/src/storage.test.ts.md +2 -0
  151. package/src/storage.test.ts.snap +0 -0
  152. package/src/upgrade-interface-version.test.ts +37 -0
  153. package/src/upgrade-interface-version.ts +27 -0
  154. package/src/utils/annotations.ts +8 -0
  155. package/src/utils/make-namespaced.test.ts +74 -0
  156. package/src/utils/make-namespaced.test.ts.md +154 -0
  157. package/src/utils/make-namespaced.test.ts.snap +0 -0
  158. package/src/utils/make-namespaced.ts +154 -0
  159. package/src/utils/stabilize-layout.ts +5 -0
  160. package/src/validate/query.ts +4 -2
  161. package/src/validate/run.ts +108 -2
@@ -0,0 +1,53 @@
1
+ # Snapshot report for `src/storage-namespaced-conflicts-layout.test.ts`
2
+
3
+ The actual snapshot is saved in `storage-namespaced-conflicts-layout.test.ts.snap`.
4
+
5
+ Generated by [AVA](https://avajs.dev).
6
+
7
+ ## duplicate namespace
8
+
9
+ > Snapshot 1
10
+
11
+ `Namespace erc7201:conflicting is defined multiple times for contract DuplicateNamespace␊
12
+ ␊
13
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
14
+ - contracts/test/NamespacedConflicts.sol:10␊
15
+ - contracts/test/NamespacedConflicts.sol:15␊
16
+ ␊
17
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
18
+
19
+ ## inherits duplicate
20
+
21
+ > Snapshot 1
22
+
23
+ `Namespace erc7201:conflicting is defined multiple times for contract InheritsDuplicate␊
24
+ ␊
25
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
26
+ - contracts/test/NamespacedConflicts.sol:10␊
27
+ - contracts/test/NamespacedConflicts.sol:15␊
28
+ ␊
29
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
30
+
31
+ ## conflicts with parent
32
+
33
+ > Snapshot 1
34
+
35
+ `Namespace erc7201:conflicting is defined multiple times for contract ConflictsWithParent␊
36
+ ␊
37
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
38
+ - contracts/test/NamespacedConflicts.sol:45␊
39
+ - contracts/test/NamespacedConflicts.sol:30␊
40
+ ␊
41
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
42
+
43
+ ## conflicts in both parents
44
+
45
+ > Snapshot 1
46
+
47
+ `Namespace erc7201:conflicting is defined multiple times for contract ConflictsInBothParents␊
48
+ ␊
49
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
50
+ - contracts/test/NamespacedConflicts.sol:45␊
51
+ - contracts/test/NamespacedConflicts.sol:30␊
52
+ ␊
53
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
@@ -0,0 +1,54 @@
1
+ import _test, { TestFn } from 'ava';
2
+ import { ContractDefinition } from 'solidity-ast';
3
+ import { findAll, astDereferencer } from 'solidity-ast/utils';
4
+ import { artifacts } from 'hardhat';
5
+
6
+ import { SolcOutput } from './solc-api';
7
+ import { StorageLayout } from './storage/layout';
8
+ import { extractStorageLayout } from './storage/extract';
9
+ import { solcInputOutputDecoder } from './src-decoder';
10
+
11
+ interface Context {
12
+ extractStorageLayout: (contract: string) => ReturnType<typeof extractStorageLayout>;
13
+ }
14
+
15
+ const test = _test as TestFn<Context>;
16
+
17
+ test.before(async t => {
18
+ const buildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedConflicts.sol:DuplicateNamespace');
19
+ if (buildInfo === undefined) {
20
+ throw new Error('Build info not found');
21
+ }
22
+ const solcOutput: SolcOutput = buildInfo.output;
23
+ const contracts: Record<string, ContractDefinition> = {};
24
+ const storageLayouts: Record<string, StorageLayout> = {};
25
+ for (const def of findAll('ContractDefinition', solcOutput.sources['contracts/test/NamespacedConflicts.sol'].ast)) {
26
+ contracts[def.name] = def;
27
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
28
+ storageLayouts[def.name] = solcOutput.contracts['contracts/test/NamespacedConflicts.sol'][def.name].storageLayout!;
29
+ }
30
+ const deref = astDereferencer(solcOutput);
31
+ const decodeSrc = solcInputOutputDecoder(buildInfo.input, solcOutput);
32
+ t.context.extractStorageLayout = name =>
33
+ extractStorageLayout(contracts[name], decodeSrc, deref, storageLayouts[name]);
34
+ });
35
+
36
+ test('duplicate namespace', t => {
37
+ const error = t.throws(() => t.context.extractStorageLayout('DuplicateNamespace'));
38
+ t.snapshot(error?.message);
39
+ });
40
+
41
+ test('inherits duplicate', t => {
42
+ const error = t.throws(() => t.context.extractStorageLayout('InheritsDuplicate'));
43
+ t.snapshot(error?.message);
44
+ });
45
+
46
+ test('conflicts with parent', t => {
47
+ const error = t.throws(() => t.context.extractStorageLayout('ConflictsWithParent'));
48
+ t.snapshot(error?.message);
49
+ });
50
+
51
+ test('conflicts in both parents', t => {
52
+ const error = t.throws(() => t.context.extractStorageLayout('ConflictsInBothParents'));
53
+ t.snapshot(error?.message);
54
+ });
@@ -0,0 +1,53 @@
1
+ # Snapshot report for `src/storage-namespaced-conflicts.test.ts`
2
+
3
+ The actual snapshot is saved in `storage-namespaced-conflicts.test.ts.snap`.
4
+
5
+ Generated by [AVA](https://avajs.dev).
6
+
7
+ ## duplicate namespace
8
+
9
+ > Snapshot 1
10
+
11
+ `Namespace erc7201:conflicting is defined multiple times for contract DuplicateNamespace␊
12
+ ␊
13
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
14
+ - contracts/test/NamespacedConflicts.sol:10␊
15
+ - contracts/test/NamespacedConflicts.sol:15␊
16
+ ␊
17
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
18
+
19
+ ## inherits duplicate
20
+
21
+ > Snapshot 1
22
+
23
+ `Namespace erc7201:conflicting is defined multiple times for contract InheritsDuplicate␊
24
+ ␊
25
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
26
+ - contracts/test/NamespacedConflicts.sol:10␊
27
+ - contracts/test/NamespacedConflicts.sol:15␊
28
+ ␊
29
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
30
+
31
+ ## conflicts with parent
32
+
33
+ > Snapshot 1
34
+
35
+ `Namespace erc7201:conflicting is defined multiple times for contract ConflictsWithParent␊
36
+ ␊
37
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
38
+ - contracts/test/NamespacedConflicts.sol:45␊
39
+ - contracts/test/NamespacedConflicts.sol:30␊
40
+ ␊
41
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
42
+
43
+ ## conflicts in both parents
44
+
45
+ > Snapshot 1
46
+
47
+ `Namespace erc7201:conflicting is defined multiple times for contract ConflictsInBothParents␊
48
+ ␊
49
+ The namespace erc7201:conflicting was found in structs at the following locations:␊
50
+ - contracts/test/NamespacedConflicts.sol:45␊
51
+ - contracts/test/NamespacedConflicts.sol:30␊
52
+ ␊
53
+ Use a unique namespace id for each struct annotated with '@custom:storage-location erc7201:<NAMESPACE_ID>' in your contract and its inherited contracts.`
@@ -0,0 +1,77 @@
1
+ import _test, { TestFn } from 'ava';
2
+ import { ContractDefinition } from 'solidity-ast';
3
+ import { findAll, astDereferencer } from 'solidity-ast/utils';
4
+ import { artifacts } from 'hardhat';
5
+
6
+ import { SolcOutput } from './solc-api';
7
+ import { StorageLayout } from './storage/layout';
8
+ import { extractStorageLayout } from './storage/extract';
9
+ import { stabilizeStorageLayout } from './utils/stabilize-layout';
10
+ import { solcInputOutputDecoder } from './src-decoder';
11
+
12
+ interface Context {
13
+ extractStorageLayout: (contract: string) => ReturnType<typeof extractStorageLayout>;
14
+ }
15
+
16
+ const test = _test as TestFn<Context>;
17
+
18
+ test.before(async t => {
19
+ // Tests extracting the storage layout (to include slot and offset) using Namespaced.sol's Example as the original contract,
20
+ // and NamespacedLayout.sol's Example as the modified contract with the storage layout.
21
+ const origBuildInfo = await artifacts.getBuildInfo('contracts/test/Namespaced.sol:Example');
22
+ const namespacedBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedLayout.sol:Example');
23
+
24
+ if (origBuildInfo === undefined || namespacedBuildInfo === undefined) {
25
+ throw new Error('Build info not found');
26
+ }
27
+
28
+ const origSolcOutput: SolcOutput = origBuildInfo.output;
29
+ const origContracts: Record<string, ContractDefinition> = {};
30
+ const origStorageLayouts: Record<string, StorageLayout> = {};
31
+
32
+ const namespacedSolcOutput: SolcOutput = namespacedBuildInfo.output;
33
+ const namespacedContracts: Record<string, ContractDefinition> = {};
34
+ const namespacedStorageLayouts: Record<string, StorageLayout> = {};
35
+
36
+ const origContractDefs = [];
37
+ for (const def of findAll('ContractDefinition', origSolcOutput.sources['contracts/test/Namespaced.sol'].ast)) {
38
+ origContractDefs.push(def);
39
+ }
40
+ const namespacedContractDefs = [];
41
+ for (const def of findAll(
42
+ 'ContractDefinition',
43
+ namespacedSolcOutput.sources['contracts/test/NamespacedLayout.sol'].ast,
44
+ )) {
45
+ namespacedContractDefs.push(def);
46
+ }
47
+
48
+ // Expects the first contract in Namespaced.sol and NamespacedLayout.sol to be 'Example'
49
+ const origContractDef = origContractDefs[0];
50
+ const namespacedContractDef = namespacedContractDefs[0];
51
+
52
+ origContracts[origContractDef.name] = origContractDef;
53
+ namespacedContracts[namespacedContractDef.name] = namespacedContractDef;
54
+
55
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
56
+ origStorageLayouts[origContractDef.name] =
57
+ origSolcOutput.contracts['contracts/test/Namespaced.sol'][origContractDef.name].storageLayout!;
58
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
59
+ namespacedStorageLayouts[namespacedContractDef.name] =
60
+ namespacedSolcOutput.contracts['contracts/test/NamespacedLayout.sol'][namespacedContractDef.name].storageLayout!;
61
+
62
+ const origDeref = astDereferencer(origSolcOutput);
63
+ const namespacedDeref = astDereferencer(namespacedSolcOutput);
64
+
65
+ const decodeSrc = solcInputOutputDecoder(origBuildInfo.input, origSolcOutput);
66
+ t.context.extractStorageLayout = name =>
67
+ extractStorageLayout(origContracts[name], decodeSrc, origDeref, origStorageLayouts[name], {
68
+ deref: namespacedDeref,
69
+ contractDef: namespacedContracts[name],
70
+ storageLayout: namespacedStorageLayouts[name],
71
+ });
72
+ });
73
+
74
+ test('layout', t => {
75
+ const layout = t.context.extractStorageLayout('Example');
76
+ t.snapshot(stabilizeStorageLayout(layout));
77
+ });
@@ -0,0 +1,67 @@
1
+ # Snapshot report for `src/storage-namespaced-layout.test.ts`
2
+
3
+ The actual snapshot is saved in `storage-namespaced-layout.test.ts.snap`.
4
+
5
+ Generated by [AVA](https://avajs.dev).
6
+
7
+ ## layout
8
+
9
+ > Snapshot 1
10
+
11
+ {
12
+ namespaces: [
13
+ [
14
+ 'erc7201:example.main',
15
+ [
16
+ {
17
+ contract: 'Example',
18
+ label: 'x',
19
+ offset: 0,
20
+ slot: '0',
21
+ src: 'contracts/test/Namespaced.sol:7',
22
+ type: 't_uint256',
23
+ },
24
+ {
25
+ contract: 'Example',
26
+ label: 'y',
27
+ offset: 0,
28
+ slot: '1',
29
+ src: 'contracts/test/Namespaced.sol:8',
30
+ type: 't_uint256',
31
+ },
32
+ ],
33
+ ],
34
+ ],
35
+ storage: [],
36
+ types: [
37
+ [
38
+ 't_struct(MainStorage)storage',
39
+ {
40
+ label: 'struct Example.MainStorage',
41
+ members: [
42
+ {
43
+ label: 'x',
44
+ offset: 0,
45
+ slot: '0',
46
+ type: 't_uint256',
47
+ },
48
+ {
49
+ label: 'y',
50
+ offset: 0,
51
+ slot: '1',
52
+ type: 't_uint256',
53
+ },
54
+ ],
55
+ numberOfBytes: '64',
56
+ },
57
+ ],
58
+ [
59
+ 't_uint256',
60
+ {
61
+ label: 'uint256',
62
+ members: undefined,
63
+ numberOfBytes: '32',
64
+ },
65
+ ],
66
+ ],
67
+ }
@@ -0,0 +1,24 @@
1
+ import test from 'ava';
2
+ import { artifacts } from 'hardhat';
3
+
4
+ import { validate } from './validate';
5
+ import { solcInputOutputDecoder } from './src-decoder';
6
+
7
+ test('namespace outside contract', async t => {
8
+ const contract = 'contracts/test/NamespacedOutsideContract.sol:Example';
9
+
10
+ const buildInfo = await artifacts.getBuildInfo(contract);
11
+ if (buildInfo === undefined) {
12
+ throw new Error(`Build info not found for contract ${contract}`);
13
+ }
14
+ const solcOutput = buildInfo.output;
15
+ const solcInput = buildInfo.input;
16
+ const decodeSrc = solcInputOutputDecoder(solcInput, solcOutput);
17
+ const error = t.throws(() => validate(solcOutput, decodeSrc));
18
+ t.assert(
19
+ error?.message.includes(
20
+ 'contracts/test/NamespacedOutsideContract.sol:7: Namespace struct MainStorage is defined outside of a contract',
21
+ ),
22
+ error?.message,
23
+ );
24
+ });
@@ -0,0 +1,59 @@
1
+ import _test, { TestFn } from 'ava';
2
+ import { artifacts } from 'hardhat';
3
+
4
+ import { validate } from './validate';
5
+ import { solcInputOutputDecoder } from './src-decoder';
6
+
7
+ interface Context {
8
+ validate: (solcVersion?: string) => ReturnType<typeof validate>;
9
+ }
10
+
11
+ const test = _test as TestFn<Context>;
12
+
13
+ test.before(async t => {
14
+ const contract = 'contracts/test/Namespaced.sol:Example';
15
+
16
+ const buildInfo = await artifacts.getBuildInfo(contract);
17
+ if (buildInfo === undefined) {
18
+ throw new Error(`Build info not found for contract ${contract}`);
19
+ }
20
+ const solcOutput = buildInfo.output;
21
+ const solcInput = buildInfo.input;
22
+ const decodeSrc = solcInputOutputDecoder(solcInput, solcOutput);
23
+
24
+ t.context.validate = solcVersion => validate(solcOutput, decodeSrc, solcVersion, solcInput);
25
+ });
26
+
27
+ test('namespace with older solc version', async t => {
28
+ const { validate } = t.context;
29
+ const error = t.throws(() => validate('0.8.19'));
30
+ t.assert(
31
+ error?.message.includes(
32
+ `contracts/test/Namespaced.sol: Namespace annotations require Solidity version >= 0.8.20, but 0.8.19 was used`,
33
+ ),
34
+ error?.message,
35
+ );
36
+ });
37
+
38
+ test('namespace with correct solc version', async t => {
39
+ const { validate } = t.context;
40
+ validate('0.8.20');
41
+ t.pass();
42
+ });
43
+
44
+ test('namespace with newer solc version', async t => {
45
+ const { validate } = t.context;
46
+ validate('0.8.21');
47
+ t.pass();
48
+ });
49
+
50
+ test('namespace with no solc version', async t => {
51
+ const { validate } = t.context;
52
+ const error = t.throws(() => validate(undefined));
53
+ t.assert(
54
+ error?.message.includes(
55
+ `contracts/test/Namespaced.sol: Namespace annotations require Solidity version >= 0.8.20, but no solcVersion parameter was provided`,
56
+ ),
57
+ error?.message,
58
+ );
59
+ });
@@ -0,0 +1,160 @@
1
+ import _test, { TestFn } from 'ava';
2
+ import { ContractDefinition } from 'solidity-ast';
3
+ import { findAll, astDereferencer } from 'solidity-ast/utils';
4
+ import { artifacts } from 'hardhat';
5
+
6
+ import { SolcOutput } from './solc-api';
7
+ import { getStorageUpgradeErrors } from './storage';
8
+ import { StorageLayout } from './storage/layout';
9
+ import { extractStorageLayout } from './storage/extract';
10
+ import { solcInputOutputDecoder } from './src-decoder';
11
+
12
+ interface Context {
13
+ extractStorageLayout: (contract: string, layoutInfo: boolean) => ReturnType<typeof extractStorageLayout>;
14
+ }
15
+
16
+ const test = _test as TestFn<Context>;
17
+
18
+ test.before(async t => {
19
+ const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedUDVT.sol:NamespacedUDVT');
20
+ const namespacedBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedUDVTLayout.sol:NamespacedUDVT');
21
+
22
+ if (origBuildInfo === undefined || namespacedBuildInfo === undefined) {
23
+ throw new Error('Build info not found');
24
+ }
25
+
26
+ const origSolcOutput: SolcOutput = origBuildInfo.output;
27
+ const origContracts: Record<string, ContractDefinition> = {};
28
+ const origStorageLayouts: Record<string, StorageLayout> = {};
29
+
30
+ const namespacedSolcOutput: SolcOutput = namespacedBuildInfo.output;
31
+ const namespacedContracts: Record<string, ContractDefinition> = {};
32
+ const namespacedStorageLayouts: Record<string, StorageLayout> = {};
33
+
34
+ const origContractDefs = [];
35
+ for (const def of findAll('ContractDefinition', origSolcOutput.sources['contracts/test/NamespacedUDVT.sol'].ast)) {
36
+ origContractDefs.push(def);
37
+ }
38
+ const namespacedContractDefs = [];
39
+ for (const def of findAll(
40
+ 'ContractDefinition',
41
+ namespacedSolcOutput.sources['contracts/test/NamespacedUDVTLayout.sol'].ast,
42
+ )) {
43
+ namespacedContractDefs.push(def);
44
+ }
45
+
46
+ for (let i = 0; i < origContractDefs.length; i++) {
47
+ const origContractDef = origContractDefs[i];
48
+ const namespacedContractDef = namespacedContractDefs[i];
49
+
50
+ origContracts[origContractDef.name] = origContractDef;
51
+ namespacedContracts[namespacedContractDef.name] = namespacedContractDef;
52
+
53
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
54
+ origStorageLayouts[origContractDef.name] =
55
+ origSolcOutput.contracts['contracts/test/NamespacedUDVT.sol'][origContractDef.name].storageLayout!;
56
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
57
+ namespacedStorageLayouts[namespacedContractDef.name] =
58
+ namespacedSolcOutput.contracts['contracts/test/NamespacedUDVTLayout.sol'][
59
+ namespacedContractDef.name
60
+ ].storageLayout!;
61
+ }
62
+ const origDeref = astDereferencer(origSolcOutput);
63
+ const namespacedDeref = astDereferencer(namespacedSolcOutput);
64
+
65
+ const decodeSrc = solcInputOutputDecoder(origBuildInfo.input, origSolcOutput);
66
+ t.context.extractStorageLayout = (name, layoutInfo) =>
67
+ extractStorageLayout(
68
+ origContracts[name],
69
+ decodeSrc,
70
+ origDeref,
71
+ origStorageLayouts[name],
72
+ layoutInfo
73
+ ? {
74
+ deref: namespacedDeref,
75
+ contractDef: namespacedContracts[name],
76
+ storageLayout: namespacedStorageLayouts[name],
77
+ }
78
+ : undefined,
79
+ );
80
+ });
81
+
82
+ test('user defined value types - layout info', async t => {
83
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT', true);
84
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_V2_Ok', true);
85
+ const comparison = getStorageUpgradeErrors(v1, v2);
86
+ t.deepEqual(comparison, []);
87
+ });
88
+
89
+ test('user defined value types - no layout info', async t => {
90
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT', false);
91
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_V2_Ok', false);
92
+ const comparison = getStorageUpgradeErrors(v1, v2);
93
+ t.deepEqual(comparison, []);
94
+ });
95
+
96
+ test('user defined value types - layout info - bad underlying type', async t => {
97
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT', true);
98
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_V2_Resize', true);
99
+ const comparison = getStorageUpgradeErrors(v1, v2);
100
+ t.like(comparison, {
101
+ length: 1,
102
+ 0: {
103
+ kind: 'typechange',
104
+ change: {
105
+ kind: 'type resize',
106
+ },
107
+ original: { label: 'my_user_value' },
108
+ updated: { label: 'my_user_value' },
109
+ },
110
+ });
111
+ });
112
+
113
+ test('user defined value types - no layout info - bad underlying type', async t => {
114
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT', false);
115
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_V2_Resize', false);
116
+ const comparison = getStorageUpgradeErrors(v1, v2);
117
+ t.like(comparison, {
118
+ length: 1,
119
+ 0: {
120
+ kind: 'typechange',
121
+ change: {
122
+ kind: 'unknown',
123
+ },
124
+ original: { label: 'my_user_value' },
125
+ updated: { label: 'my_user_value' },
126
+ },
127
+ });
128
+ });
129
+
130
+ test('mapping with user defined value type key - ok', t => {
131
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT_MappingKey_V1', true);
132
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_MappingKey_V2_Ok', true);
133
+ const comparison = getStorageUpgradeErrors(v1, v2);
134
+ t.deepEqual(comparison, []);
135
+ });
136
+
137
+ test('mapping with user defined value type key - bad', t => {
138
+ const v1 = t.context.extractStorageLayout('NamespacedUDVT_MappingKey_V1', true);
139
+ const v2 = t.context.extractStorageLayout('NamespacedUDVT_MappingKey_V2_Bad', true);
140
+ const comparison = getStorageUpgradeErrors(v1, v2);
141
+ t.like(comparison, {
142
+ length: 2,
143
+ 0: {
144
+ kind: 'typechange',
145
+ change: {
146
+ kind: 'mapping key',
147
+ },
148
+ original: { label: 'm1' },
149
+ updated: { label: 'm1' },
150
+ },
151
+ 1: {
152
+ kind: 'typechange',
153
+ change: {
154
+ kind: 'mapping key',
155
+ },
156
+ original: { label: 'm2' },
157
+ updated: { label: 'm2' },
158
+ },
159
+ });
160
+ });