@openzeppelin/upgrades-core 1.31.2 → 1.32.0-alpha.0

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 (38) hide show
  1. package/artifacts/@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json +76 -0
  2. package/artifacts/@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol/BeaconProxy.json +87 -0
  3. package/artifacts/@openzeppelin/contracts-v5/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json +151 -0
  4. package/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json +132 -0
  5. package/artifacts/@openzeppelin/contracts-v5/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json +74 -0
  6. package/artifacts/@openzeppelin/contracts-v5/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json +116 -0
  7. package/artifacts/build-info-v5.json +13993 -0
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +2 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/scripts/migratable-manifest.test.json +175 -0
  13. package/dist/scripts/project-file.test.json +25 -0
  14. package/dist/solidity-version.json +1 -0
  15. package/dist/standalone.test.js +9 -8
  16. package/dist/standalone.test.js.map +1 -1
  17. package/dist/usage-error.d.ts +3 -0
  18. package/dist/usage-error.d.ts.map +1 -1
  19. package/dist/usage-error.js +7 -1
  20. package/dist/usage-error.js.map +1 -1
  21. package/dist/utils/make-namespaced.d.ts +3 -4
  22. package/dist/utils/make-namespaced.d.ts.map +1 -1
  23. package/dist/utils/make-namespaced.js +85 -42
  24. package/dist/utils/make-namespaced.js.map +1 -1
  25. package/dist/utils/make-namespaced.test.js +9 -8
  26. package/dist/utils/make-namespaced.test.js.map +1 -1
  27. package/package.json +20 -13
  28. package/src/index.ts +1 -0
  29. package/src/solidity-version.json +1 -0
  30. package/src/standalone.test.ts +41 -7
  31. package/src/usage-error.ts +9 -0
  32. package/src/utils/make-namespaced.test.ts +11 -9
  33. package/src/utils/make-namespaced.test.ts.md +97 -32
  34. package/src/utils/make-namespaced.test.ts.snap +0 -0
  35. package/src/utils/make-namespaced.ts +91 -44
  36. package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.dbg.json +0 -4
  37. package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.dbg.json +0 -4
  38. package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.dbg.json +0 -4
@@ -8,7 +8,7 @@ const hardhat_1 = require("hardhat");
8
8
  const task_names_1 = require("hardhat/builtin-tasks/task-names");
9
9
  const make_namespaced_1 = require("./make-namespaced");
10
10
  (0, ava_1.default)('make namespaced input', async (t) => {
11
- const origBuildInfo = await hardhat_1.artifacts.getBuildInfo('contracts/test/NamespacedToModify.sol:Example');
11
+ const origBuildInfo = await hardhat_1.artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
12
12
  await testMakeNamespaced(origBuildInfo, t, '0.8.20');
13
13
  });
14
14
  (0, ava_1.default)('make namespaced input - solc 0.7', async (t) => {
@@ -23,20 +23,21 @@ async function testMakeNamespaced(origBuildInfo, t, solcVersion) {
23
23
  // Inefficient, but we want to test that we don't actually modify the original input object
24
24
  const origInput = JSON.parse(JSON.stringify(origBuildInfo.input));
25
25
  const modifiedInput = (0, make_namespaced_1.makeNamespacedInput)(origBuildInfo.input, origBuildInfo.output);
26
- normalizeStateVariableNames(modifiedInput);
27
- t.snapshot(modifiedInput);
28
- t.deepEqual(origBuildInfo.input, origInput);
29
- t.notDeepEqual(modifiedInput, origInput);
30
26
  // Run hardhat compile on the modified input and make sure it has no errors
31
27
  const modifiedOutput = await hardhatCompile(modifiedInput, solcVersion);
32
28
  t.is(modifiedOutput.errors, undefined);
29
+ normalizeIdentifiers(modifiedInput);
30
+ t.snapshot(modifiedInput);
31
+ t.deepEqual(origBuildInfo.input, origInput);
32
+ t.notDeepEqual(modifiedInput, origInput);
33
33
  }
34
- function normalizeStateVariableNames(input) {
34
+ function normalizeIdentifiers(input) {
35
35
  for (const source of Object.values(input.sources)) {
36
36
  if (source.content !== undefined) {
37
37
  source.content = source.content
38
- .replace(/\$MainStorage_\d{1,6};/g, '$MainStorage_random;')
39
- .replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random');
38
+ .replace(/\$MainStorage_\d{1,6}/g, '$MainStorage_random')
39
+ .replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random')
40
+ .replace(/\$astId_\d+_\d{1,6}/g, '$astId_id_random');
40
41
  }
41
42
  }
42
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"make-namespaced.test.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAA6C;AAC7C,qCAAyC;AACzC,iEAI0C;AAE1C,uDAAwD;AAKxD,IAAA,aAAI,EAAC,uBAAuB,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACtC,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,+CAA+C,CAAC,CAAC;IACpG,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,kCAAkC,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACjD,6JAA6J;IAC7J,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,qDAAqD,CAAC,CAAC;IAC1G,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,kBAAkB,CAC/B,aAAoC,EACpC,CAA4B,EAC5B,WAAmB;IAEnB,IAAI,aAAa,KAAK,SAAS,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;KACzC;IAED,2FAA2F;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAElE,MAAM,aAAa,GAAG,IAAA,qCAAmB,EAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrF,2BAA2B,CAAC,aAAa,CAAC,CAAC;IAC3C,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAE1B,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAEzC,2EAA2E;IAC3E,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,2BAA2B,CAAC,KAAgB;IACnD,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;QACjD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;YAChC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;iBAC5B,OAAO,CAAC,yBAAyB,EAAE,sBAAsB,CAAC;iBAC1D,OAAO,CAAC,6BAA6B,EAAE,0BAA0B,CAAC,CAAC;SACvE;KACF;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,KAAgB,EAAE,WAAmB;IACjE,MAAM,SAAS,GAAc,MAAM,IAAA,aAAG,EAAC,iDAAoC,EAAE;QAC3E,KAAK,EAAE,IAAI;QACX,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,SAAS,CAAC,QAAQ,EAAE;QACtB,OAAO,MAAM,IAAA,aAAG,EAAC,6CAAgC,EAAE;YACjD,KAAK;YACL,UAAU,EAAE,SAAS,CAAC,YAAY;SACnC,CAAC,CAAC;KACJ;SAAM;QACL,OAAO,MAAM,IAAA,aAAG,EAAC,2CAA8B,EAAE;YAC/C,KAAK;YACL,QAAQ,EAAE,SAAS,CAAC,YAAY;SACjC,CAAC,CAAC;KACJ;AACH,CAAC"}
1
+ {"version":3,"file":"make-namespaced.test.js","sourceRoot":"","sources":["../../src/utils/make-namespaced.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAA6C;AAC7C,qCAAyC;AACzC,iEAI0C;AAE1C,uDAAwD;AAKxD,IAAA,aAAI,EAAC,uBAAuB,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACtC,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,uDAAuD,CAAC,CAAC;IAC5G,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,kCAAkC,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;IACjD,6JAA6J;IAC7J,MAAM,aAAa,GAAG,MAAM,mBAAS,CAAC,YAAY,CAAC,qDAAqD,CAAC,CAAC;IAC1G,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,kBAAkB,CAC/B,aAAoC,EACpC,CAA4B,EAC5B,WAAmB;IAEnB,IAAI,aAAa,KAAK,SAAS,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;KACzC;IAED,2FAA2F;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAElE,MAAM,aAAa,GAAG,IAAA,qCAAmB,EAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAErF,2EAA2E;IAC3E,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEvC,oBAAoB,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAE1B,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAgB;IAC5C,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;QACjD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE;YAChC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO;iBAC5B,OAAO,CAAC,wBAAwB,EAAE,qBAAqB,CAAC;iBACxD,OAAO,CAAC,6BAA6B,EAAE,0BAA0B,CAAC;iBAClE,OAAO,CAAC,sBAAsB,EAAE,kBAAkB,CAAC,CAAC;SACxD;KACF;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,KAAgB,EAAE,WAAmB;IACjE,MAAM,SAAS,GAAc,MAAM,IAAA,aAAG,EAAC,iDAAoC,EAAE;QAC3E,KAAK,EAAE,IAAI;QACX,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,SAAS,CAAC,QAAQ,EAAE;QACtB,OAAO,MAAM,IAAA,aAAG,EAAC,6CAAgC,EAAE;YACjD,KAAK;YACL,UAAU,EAAE,SAAS,CAAC,YAAY;SACnC,CAAC,CAAC;KACJ;SAAM;QACL,OAAO,MAAM,IAAA,aAAG,EAAC,2CAA8B,EAAE;YAC/C,KAAK;YACL,QAAQ,EAAE,SAAS,CAAC,YAAY;SACjC,CAAC,CAAC;KACJ;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/upgrades-core",
3
- "version": "1.31.2",
3
+ "version": "1.32.0-alpha.0",
4
4
  "description": "",
5
5
  "repository": "https://github.com/OpenZeppelin/openzeppelin-upgrades/tree/master/packages/core",
6
6
  "license": "MIT",
@@ -13,22 +13,29 @@
13
13
  "/artifacts/contracts/proxy/AdminUpgradeabilityProxy.sol/AdminUpgradeabilityProxy.json",
14
14
  "/artifacts/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json",
15
15
  "/contracts/Initializable.sol",
16
- "/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol",
17
- "/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol",
18
- "/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol",
16
+ "/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json",
17
+ "/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json",
18
+ "/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json",
19
19
  "/artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json",
20
20
  "/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json",
21
21
  "/artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json",
22
- "/artifacts/build-info.json"
22
+ "/artifacts/build-info.json",
23
+ "/artifacts/@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol/BeaconProxy.json",
24
+ "/artifacts/@openzeppelin/contracts-v5/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json",
25
+ "/artifacts/@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.json",
26
+ "/artifacts/@openzeppelin/contracts-v5/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json",
27
+ "/artifacts/@openzeppelin/contracts-v5/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json",
28
+ "/artifacts/@openzeppelin/contracts-v5/proxy/transparent/TransparentUpgradeableProxy.sol/ITransparentUpgradeableProxy.json",
29
+ "/artifacts/build-info-v5.json"
23
30
  ],
24
31
  "scripts": {
25
32
  "clean": "hardhat clean && rimraf dist *.tsbuildinfo",
26
33
  "compile": "tsc -b && yarn compile:contracts",
27
- "compile:contracts": "hardhat compile && node scripts/copy-build-info.js",
28
- "prepare": "yarn clean && yarn compile",
29
- "prepublishOnly": "bash scripts/copy-artifacts.sh",
30
- "test": "tsc -b && hardhat compile --force && node scripts/copy-build-info.js && ava",
31
- "test:watch": "hardhat compile --force && fgbg 'ava --watch' 'tsc -b --watch' --",
34
+ "compile:contracts": "hardhat compile",
35
+ "copyfiles": "node scripts/copy-build-info-v5.js && bash scripts/copy-legacy-artifacts.sh",
36
+ "prepare": "yarn clean && yarn compile && yarn copyfiles",
37
+ "test": "tsc -b && hardhat compile --force && yarn copyfiles && ava",
38
+ "test:watch": "hardhat compile --force && yarn copyfiles && fgbg 'ava --watch' 'tsc -b --watch' --",
32
39
  "version": "node ../../scripts/bump-changelog.js",
33
40
  "cli": "node ./dist/cli/cli.js"
34
41
  },
@@ -38,8 +45,8 @@
38
45
  "devDependencies": {
39
46
  "@ava/typescript": "^4.0.0",
40
47
  "@nomicfoundation/hardhat-ethers": "^3.0.5",
41
- "@openzeppelin/contracts": "4.8.3",
42
- "@openzeppelin/contracts-upgradeable": "4.8.3",
48
+ "@openzeppelin/contracts": "5.0.0",
49
+ "@openzeppelin/upgrades-core-legacy": "npm:@openzeppelin/upgrades-core@1.31.3",
43
50
  "@types/cbor": "^5.0.0",
44
51
  "@types/debug": "^4.1.5",
45
52
  "@types/mocha": "^7.0.2",
@@ -64,5 +71,5 @@
64
71
  "proper-lockfile": "^4.1.1",
65
72
  "solidity-ast": "^0.4.51"
66
73
  },
67
- "gitHead": "6614824fca753f8fb853b48cfc722685e832a1b9"
74
+ "gitHead": "7fd74e339fe760d23aea5cc0bbf6bac525323ab4"
68
75
  }
package/src/index.ts CHANGED
@@ -53,6 +53,7 @@ export {
53
53
  NoContractImportError,
54
54
  ValidateUpdateRequiresKindError,
55
55
  PrepareUpgradeRequiresKindError,
56
+ InitialOwnerUnsupportedKindError,
56
57
  assertNotProxy,
57
58
  } from './usage-error';
58
59
 
@@ -0,0 +1 @@
1
+ "0.8.20"
@@ -1,6 +1,8 @@
1
1
  import _test, { TestFn } from 'ava';
2
2
  import { artifacts } from 'hardhat';
3
3
 
4
+ import SOLIDITY_VERSION from './solidity-version.json';
5
+
4
6
  import { SolcInput, SolcOutput } from './solc-api';
5
7
  import { UpgradeableContract } from './standalone';
6
8
 
@@ -21,7 +23,7 @@ test.before(async t => {
21
23
  });
22
24
 
23
25
  test('reports unsafe operation', t => {
24
- const impl = new UpgradeableContract('StandaloneV1', t.context.solcInput, t.context.solcOutput);
26
+ const impl = new UpgradeableContract('StandaloneV1', t.context.solcInput, t.context.solcOutput, {}, SOLIDITY_VERSION);
25
27
  const report = impl.getErrorReport();
26
28
  t.false(report.ok);
27
29
  t.true(report.errors[0].kind === 'delegatecall');
@@ -32,6 +34,8 @@ test('reports unsafe operation - fully qualified name', t => {
32
34
  'contracts/test/Standalone.sol:StandaloneV1',
33
35
  t.context.solcInput,
34
36
  t.context.solcOutput,
37
+ {},
38
+ SOLIDITY_VERSION,
35
39
  );
36
40
  const report = impl.getErrorReport();
37
41
  t.false(report.ok);
@@ -39,25 +43,55 @@ test('reports unsafe operation - fully qualified name', t => {
39
43
  });
40
44
 
41
45
  test('reports storage upgrade errors', t => {
42
- const v1 = new UpgradeableContract('StandaloneV1', t.context.solcInput, t.context.solcOutput);
46
+ const v1 = new UpgradeableContract('StandaloneV1', t.context.solcInput, t.context.solcOutput, {}, SOLIDITY_VERSION);
43
47
 
44
- const v2Good = new UpgradeableContract('StandaloneV2Good', t.context.solcInput, t.context.solcOutput);
48
+ const v2Good = new UpgradeableContract(
49
+ 'StandaloneV2Good',
50
+ t.context.solcInput,
51
+ t.context.solcOutput,
52
+ {},
53
+ SOLIDITY_VERSION,
54
+ );
45
55
  const goodReport = v1.getStorageUpgradeReport(v2Good);
46
56
  t.true(goodReport.ok);
47
57
 
48
- const v2Bad = new UpgradeableContract('StandaloneV2Bad', t.context.solcInput, t.context.solcOutput);
58
+ const v2Bad = new UpgradeableContract(
59
+ 'StandaloneV2Bad',
60
+ t.context.solcInput,
61
+ t.context.solcOutput,
62
+ {},
63
+ SOLIDITY_VERSION,
64
+ );
49
65
  const badReport = v1.getStorageUpgradeReport(v2Bad);
50
66
  t.false(badReport.ok);
51
67
  });
52
68
 
53
69
  test('dont report renamed version update', t => {
54
- const v1 = new UpgradeableContract('StandaloneRenameV1', t.context.solcInput, t.context.solcOutput);
70
+ const v1 = new UpgradeableContract(
71
+ 'StandaloneRenameV1',
72
+ t.context.solcInput,
73
+ t.context.solcOutput,
74
+ {},
75
+ SOLIDITY_VERSION,
76
+ );
55
77
 
56
- const v2 = new UpgradeableContract('StandaloneRenameV2', t.context.solcInput, t.context.solcOutput);
78
+ const v2 = new UpgradeableContract(
79
+ 'StandaloneRenameV2',
80
+ t.context.solcInput,
81
+ t.context.solcOutput,
82
+ {},
83
+ SOLIDITY_VERSION,
84
+ );
57
85
  const goodReport = v1.getStorageUpgradeReport(v2);
58
86
  t.true(goodReport.ok);
59
87
 
60
- const v3 = new UpgradeableContract('StandaloneRenameV3', t.context.solcInput, t.context.solcOutput);
88
+ const v3 = new UpgradeableContract(
89
+ 'StandaloneRenameV3',
90
+ t.context.solcInput,
91
+ t.context.solcOutput,
92
+ {},
93
+ SOLIDITY_VERSION,
94
+ );
61
95
  const goodReport2 = v2.getStorageUpgradeReport(v3);
62
96
  t.true(goodReport2.ok);
63
97
  });
@@ -95,6 +95,15 @@ export class PrepareUpgradeRequiresKindError extends UpgradesError {
95
95
  }
96
96
  }
97
97
 
98
+ export class InitialOwnerUnsupportedKindError extends UpgradesError {
99
+ constructor(kind: string) {
100
+ super(
101
+ `The \`initialOwner\` option is not supported for this kind of proxy ('${kind}')`,
102
+ () => `Set the initial owner as part of your contract's initializer arguments instead.`,
103
+ );
104
+ }
105
+ }
106
+
98
107
  export async function assertNotProxy(provider: EthereumProvider, address: string) {
99
108
  if (await isTransparentOrUUPSProxy(provider, address)) {
100
109
  throw new UpgradesError(
@@ -12,7 +12,7 @@ import { SolcInput, SolcOutput } from '../solc-api';
12
12
  import { BuildInfo } from 'hardhat/types';
13
13
 
14
14
  test('make namespaced input', async t => {
15
- const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModify.sol:Example');
15
+ const origBuildInfo = await artifacts.getBuildInfo('contracts/test/NamespacedToModifyImported.sol:Example');
16
16
  await testMakeNamespaced(origBuildInfo, t, '0.8.20');
17
17
  });
18
18
 
@@ -35,23 +35,25 @@ async function testMakeNamespaced(
35
35
  const origInput = JSON.parse(JSON.stringify(origBuildInfo.input));
36
36
 
37
37
  const modifiedInput = makeNamespacedInput(origBuildInfo.input, origBuildInfo.output);
38
- normalizeStateVariableNames(modifiedInput);
39
- t.snapshot(modifiedInput);
40
-
41
- t.deepEqual(origBuildInfo.input, origInput);
42
- t.notDeepEqual(modifiedInput, origInput);
43
38
 
44
39
  // Run hardhat compile on the modified input and make sure it has no errors
45
40
  const modifiedOutput = await hardhatCompile(modifiedInput, solcVersion);
46
41
  t.is(modifiedOutput.errors, undefined);
42
+
43
+ normalizeIdentifiers(modifiedInput);
44
+ t.snapshot(modifiedInput);
45
+
46
+ t.deepEqual(origBuildInfo.input, origInput);
47
+ t.notDeepEqual(modifiedInput, origInput);
47
48
  }
48
49
 
49
- function normalizeStateVariableNames(input: SolcInput): void {
50
+ function normalizeIdentifiers(input: SolcInput): void {
50
51
  for (const source of Object.values(input.sources)) {
51
52
  if (source.content !== undefined) {
52
53
  source.content = source.content
53
- .replace(/\$MainStorage_\d{1,6};/g, '$MainStorage_random;')
54
- .replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random');
54
+ .replace(/\$MainStorage_\d{1,6}/g, '$MainStorage_random')
55
+ .replace(/\$SecondaryStorage_\d{1,6}/g, '$SecondaryStorage_random')
56
+ .replace(/\$astId_\d+_\d{1,6}/g, '$astId_id_random');
55
57
  }
56
58
  }
57
59
  }
@@ -45,27 +45,27 @@ Generated by [AVA](https://avajs.dev).
45
45
  uint256 b;␊
46
46
  } SecondaryStorage $SecondaryStorage_random;␊
47
47
  ␊
48
- ␊
49
- ␊
48
+ /// @notice some natspec␊
49
+ enum $astId_id_random { dummy }␊
50
50
  ␊
51
- ␊
52
- ␊
51
+ /// @param a docs␊
52
+ enum $astId_id_random { dummy }␊
53
53
  ␊
54
- ␊
55
- ␊
54
+ /// @param a docs␊
55
+ enum $astId_id_random { dummy }␊
56
56
  struct MyStruct { uint b; }␊
57
57
  ␊
58
58
  // keccak256(abi.encode(uint256(keccak256("example.main")) - 1)) & ~bytes32(uint256(0xff));␊
59
- ␊
59
+ enum $astId_id_random { dummy }␊
60
60
  ␊
61
- ␊
61
+ enum $astId_id_random { dummy }␊
62
62
  ␊
63
- ␊
63
+ enum $astId_id_random { dummy }␊
64
64
  ␊
65
65
  /// @notice standlone natspec␊
66
66
  ␊
67
- ␊
68
- ␊
67
+ /// @notice natspec for var␊
68
+ enum $astId_id_random { dummy }␊
69
69
  ␊
70
70
  // standalone doc␊
71
71
  ␊
@@ -73,49 +73,114 @@ Generated by [AVA](https://avajs.dev).
73
73
  * standlone doc block␊
74
74
  */␊
75
75
  ␊
76
- ␊
77
- ␊
76
+ /**␊
77
+ * doc block without natspec␊
78
+ */␊
79
+ enum $astId_id_random { dummy }␊
80
+ ␊
81
+ /**␊
82
+ * doc block with natspec␊
83
+ *␊
84
+ * @notice some natspec␊
85
+ */␊
86
+ enum $astId_id_random { dummy }␊
78
87
  ␊
79
- ␊
80
- ␊
88
+ /**␊
89
+ * @dev a custom error inside a contract␊
90
+ */␊
91
+ enum $astId_id_random { dummy }␊
81
92
  }␊
82
93
  ␊
83
94
  contract HasFunction {␊
84
- ␊
85
- ␊
95
+ enum $astId_id_random { dummy }␊
96
+ enum $astId_id_random { dummy }␊
86
97
  }␊
87
98
  ␊
88
99
  contract UsingFunction is HasFunction {␊
89
- ␊
100
+ enum $astId_id_random { dummy }␊
90
101
  }␊
91
102
  ␊
92
- uint256 constant FreeFunctionUsingSelector = 0;␊
103
+ enum FreeFunctionUsingSelector { dummy }␊
93
104
  ␊
94
- uint256 constant CONSTANT_USING_SELECTOR = 0;␊
105
+ enum CONSTANT_USING_SELECTOR { dummy }␊
95
106
  ␊
96
107
  library Lib {␊
97
- ␊
108
+ enum $astId_id_random { dummy }␊
98
109
  ␊
99
- ␊
110
+ enum $astId_id_random { dummy }␊
100
111
  }␊
101
112
  ␊
102
113
  contract Consumer {␊
103
- ␊
114
+ enum $astId_id_random { dummy }␊
115
+ ␊
116
+ enum $astId_id_random { dummy }␊
104
117
  ␊
105
- ␊
118
+ enum $astId_id_random { dummy }␊
106
119
  ␊
107
- ␊
120
+ enum $astId_id_random { dummy }␊
108
121
  }␊
109
122
  ␊
110
- uint256 constant plusTwo = 0;␊
123
+ enum plusTwo { dummy }␊
124
+ ␊
125
+ /**␊
126
+ * @notice originally orphaned natspec␊
127
+ */␊
128
+ ␊
129
+ /**␊
130
+ * @dev plusThree␊
131
+ * @param x x␊
132
+ */␊
133
+ enum plusThree { dummy }␊
134
+ ␊
135
+ /// @notice originally orphaned natspec 2␊
111
136
  ␊
137
+ /**␊
138
+ * @dev plusThree overloaded␊
139
+ * @param x x␊
140
+ * @param y y␊
141
+ */␊
142
+ enum $astId_id_random { dummy }␊
112
143
  ␊
144
+ enum originallyNoDocumentation { dummy }␊
145
+ ␊
146
+ /**␊
147
+ * @param foo foo␊
148
+ */␊
149
+ enum $astId_id_random { dummy }␊
113
150
  ␊
114
151
  contract UsingForDirectives {␊
115
- ␊
152
+ enum $astId_id_random { dummy }␊
153
+ ␊
154
+ enum $astId_id_random { dummy }␊
155
+ }␊
156
+ ␊
157
+ /**␊
158
+ * @title a␊
159
+ * @author a␊
160
+ * @inheritdoc Example␊
161
+ * @dev a␊
162
+ * @custom:a a␊
163
+ * @notice a␊
164
+ * @param a a␊
165
+ * @return a a␊
166
+ */␊
167
+ enum FreeEnum { MyEnum }␊
168
+ ␊
169
+ /**␊
170
+ * @dev a custom error outside a contract␊
171
+ * @param example example parameter␊
172
+ */␊
173
+ enum CustomErrorOutsideContract { dummy }␊
174
+ `,
175
+ },
176
+ 'contracts/test/NamespacedToModifyImported.sol': {
177
+ content: `// SPDX-License-Identifier: MIT␊
178
+ pragma solidity ^0.8.20;␊
116
179
  ␊
117
- ␊
118
- }`,
180
+ import {CONSTANT_USING_SELECTOR, plusTwo, plusThree, CustomErrorOutsideContract} from "./NamespacedToModify.sol";␊
181
+ ␊
182
+ contract Example {}␊
183
+ `,
119
184
  },
120
185
  },
121
186
  }
@@ -148,12 +213,12 @@ Generated by [AVA](https://avajs.dev).
148
213
  pragma solidity 0.7.6;␊
149
214
  ␊
150
215
  contract HasFunction {␊
151
- ␊
152
- ␊
216
+ enum $astId_id_random { dummy }␊
217
+ enum $astId_id_random { dummy }␊
153
218
  }␊
154
219
  ␊
155
220
  contract UsingFunction is HasFunction {␊
156
- ␊
221
+ enum $astId_id_random { dummy }␊
157
222
  }␊
158
223
  `,
159
224
  },
@@ -17,10 +17,9 @@ const OUTPUT_SELECTION = {
17
17
  *
18
18
  * This makes the following modifications to the input:
19
19
  * - Adds a state variable for each namespaced struct definition
20
- * - Deletes all contracts' functions since they are not needed for storage layout
21
- * - Deletes all contracts' modifiers, variables, and parent constructor invocations to avoid compilation errors due to deleted functions and constructors
22
- * - Deletes all using for directives (at file level and in contracts) since they may reference deleted functions
23
- * - Converts all free functions and constants (at file level) to dummy variables (do not delete them since they might be imported by other files)
20
+ * - For each contract, for all node types that are not needed for storage layout or may reference deleted functions and constructors, converts them to dummy enums with random id
21
+ * - Converts all using for directives (at file level and in contracts) to dummy enums with random id (do not delete them to avoid orphaning possible NatSpec documentation)
22
+ * - Converts all custom errors, free functions and constants (at file level) to dummy enums with the same name (do not delete them since they might be imported by other files)
24
23
  *
25
24
  * Also sets the outputSelection to only include storageLayout and ast, since the other outputs are not needed.
26
25
  *
@@ -41,55 +40,95 @@ export function makeNamespacedInput(input: SolcInput, output: SolcOutput): SolcI
41
40
 
42
41
  const orig = Buffer.from(source.content, 'utf8');
43
42
 
43
+ const replacedIdentifiers = new Set<string>();
44
44
  const modifications: Modification[] = [];
45
45
 
46
46
  for (const node of output.sources[sourcePath].ast.nodes) {
47
- if (isNodeType('ContractDefinition', node)) {
48
- const contractDef = node;
49
-
50
- // Remove any calls to parent constructors from the inheritance list
51
- const inherits = contractDef.baseContracts;
52
- for (const inherit of inherits) {
53
- if (Array.isArray(inherit.arguments)) {
54
- assert(inherit.baseName.name !== undefined);
55
- modifications.push(makeReplace(inherit, orig, inherit.baseName.name));
47
+ switch (node.nodeType) {
48
+ case 'ContractDefinition': {
49
+ const contractDef = node;
50
+
51
+ // Remove any calls to parent constructors from the inheritance list
52
+ const inherits = contractDef.baseContracts;
53
+ for (const inherit of inherits) {
54
+ if (Array.isArray(inherit.arguments)) {
55
+ assert(inherit.baseName.name !== undefined);
56
+ modifications.push(makeReplace(inherit, orig, inherit.baseName.name));
57
+ }
56
58
  }
57
- }
58
59
 
59
- const contractNodes = contractDef.nodes;
60
- for (const contractNode of contractNodes) {
61
- if (
62
- isNodeType('FunctionDefinition', contractNode) ||
63
- isNodeType('ModifierDefinition', contractNode) ||
64
- isNodeType('VariableDeclaration', contractNode)
65
- ) {
66
- if (contractNode.documentation) {
67
- modifications.push(makeDelete(contractNode.documentation, orig));
68
- }
69
- modifications.push(makeDelete(contractNode, orig));
70
- } else if (isNodeType('UsingForDirective', contractNode)) {
71
- modifications.push(makeDelete(contractNode, orig));
72
- } else if (isNodeType('StructDefinition', contractNode)) {
73
- const storageLocation = getStorageLocationAnnotation(contractNode);
74
- if (storageLocation !== undefined) {
75
- const structName = contractNode.name;
76
- const variableName = `$${structName}_${(Math.random() * 1e6).toFixed(0)}`;
77
- const insertText = ` ${structName} ${variableName};`;
78
-
79
- modifications.push(makeInsertAfter(contractNode, insertText));
60
+ const contractNodes = contractDef.nodes;
61
+ for (const contractNode of contractNodes) {
62
+ switch (contractNode.nodeType) {
63
+ case 'ErrorDefinition':
64
+ case 'EventDefinition':
65
+ case 'FunctionDefinition':
66
+ case 'ModifierDefinition':
67
+ case 'UsingForDirective':
68
+ case 'VariableDeclaration': {
69
+ // Replace with an enum based on astId (the original name is not needed, since nothing should reference it)
70
+ modifications.push(makeReplace(contractNode, orig, toDummyEnumWithAstId(contractNode.id)));
71
+ break;
72
+ }
73
+ case 'StructDefinition': {
74
+ const storageLocation = getStorageLocationAnnotation(contractNode);
75
+ if (storageLocation !== undefined) {
76
+ const structName = contractNode.name;
77
+ const variableName = `$${structName}_${(Math.random() * 1e6).toFixed(0)}`;
78
+ const insertText = ` ${structName} ${variableName};`;
79
+
80
+ modifications.push(makeInsertAfter(contractNode, insertText));
81
+ }
82
+ break;
83
+ }
84
+ case 'EnumDefinition':
85
+ case 'UserDefinedValueTypeDefinition':
86
+ default: {
87
+ // - EnumDefinition may be used in structures with storage locations
88
+ // - UserDefinedValueTypeDefinition may be used in structures with storage locations
89
+ // - default: in case unexpected ast nodes show up
90
+ break;
91
+ }
80
92
  }
81
93
  }
94
+ break;
95
+ }
96
+
97
+ // - UsingForDirective isn't needed, but it might have NatSpec documentation which is not included in the AST.
98
+ // We convert it to a dummy enum to avoid orphaning any possible documentation.
99
+ // - ErrorDefinition, FunctionDefinition, and VariableDeclaration might be imported by other files, so they cannot be deleted.
100
+ // However, we need to remove their values to avoid referencing other deleted nodes.
101
+ // We do this by converting them to dummy enums, but avoiding duplicate names.
102
+ case 'UsingForDirective':
103
+ case 'ErrorDefinition':
104
+ case 'FunctionDefinition':
105
+ case 'VariableDeclaration': {
106
+ // If an identifier with the same name was not previously written, replace with a dummy enum using its name.
107
+ // Otherwise replace with an enum based on astId to avoid duplicate names, which can happen if there was overloading.
108
+ // This does not need to check all identifiers from the original contract, since the original compilation
109
+ // should have failed if there were conflicts in the first place.
110
+ if ('name' in node && !replacedIdentifiers.has(node.name)) {
111
+ modifications.push(makeReplace(node, orig, toDummyEnumWithName(node.name)));
112
+ replacedIdentifiers.add(node.name);
113
+ } else {
114
+ modifications.push(makeReplace(node, orig, toDummyEnumWithAstId(node.id)));
115
+ }
116
+ break;
82
117
  }
83
- } else if (isNodeType('FunctionDefinition', node) || isNodeType('VariableDeclaration', node)) {
84
- if (node.documentation) {
85
- modifications.push(makeDelete(node.documentation, orig));
118
+ case 'EnumDefinition':
119
+ case 'ImportDirective':
120
+ case 'PragmaDirective':
121
+ case 'StructDefinition':
122
+ case 'UserDefinedValueTypeDefinition':
123
+ default: {
124
+ // - EnumDefinition may be used in structures with storage locations
125
+ // - ImportDirective may import types used in structures with storage locations
126
+ // - PragmaDirective is necessary for compilation
127
+ // - StructDefinition may be used in structures with storage locations
128
+ // - UserDefinedValueTypeDefinition may be used in structures with storage locations
129
+ // - default: in case unexpected ast nodes show up (file-level events since 0.8.22)
130
+ break;
86
131
  }
87
- // Replace with a dummy variable of arbitrary type
88
- const name = node.name;
89
- const insertText = `uint256 constant ${name} = 0;`;
90
- modifications.push(makeReplace(node, orig, insertText));
91
- } else if (isNodeType('UsingForDirective', node)) {
92
- modifications.push(makeDelete(node, orig));
93
132
  }
94
133
  }
95
134
 
@@ -105,6 +144,14 @@ interface Modification {
105
144
  text?: string;
106
145
  }
107
146
 
147
+ function toDummyEnumWithName(name: string) {
148
+ return `enum ${name} { dummy }`;
149
+ }
150
+
151
+ function toDummyEnumWithAstId(astId: number) {
152
+ return `enum $astId_${astId}_${(Math.random() * 1e6).toFixed(0)} { dummy }`;
153
+ }
154
+
108
155
  function getPositions(node: Node) {
109
156
  const [start, length] = node.src.split(':').map(Number);
110
157
  const end = start + length;
@@ -1,4 +0,0 @@
1
- {
2
- "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../../../build-info/966b1f437e942115ba46359eb293018c.json"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../../../build-info/966b1f437e942115ba46359eb293018c.json"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../../../build-info/966b1f437e942115ba46359eb293018c.json"
4
- }