@openzeppelin/upgrades-core 1.9.1 → 1.11.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 (191) hide show
  1. package/LICENSE +22 -0
  2. package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol/ERC1967Proxy.dbg.json +1 -1
  3. package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.dbg.json +4 -0
  4. package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json +80 -0
  5. package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.dbg.json +4 -0
  6. package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json +113 -0
  7. package/artifacts/AdminUpgradeabilityProxy.json +2 -2
  8. package/artifacts/contracts/proxy/AdminUpgradeabilityProxy.sol/AdminUpgradeabilityProxy.json +2 -2
  9. package/dist/ast-dereferencer.js +2 -2
  10. package/dist/ast-dereferencer.js.map +1 -1
  11. package/dist/beacon.d.ts +8 -0
  12. package/dist/beacon.d.ts.map +1 -0
  13. package/dist/beacon.js +25 -0
  14. package/dist/beacon.js.map +1 -0
  15. package/dist/deployment.js +18 -18
  16. package/dist/deployment.js.map +1 -1
  17. package/dist/deployment.test.js +39 -39
  18. package/dist/deployment.test.js.map +1 -1
  19. package/dist/eip-1967-type.d.ts +4 -0
  20. package/dist/eip-1967-type.d.ts.map +1 -0
  21. package/dist/eip-1967-type.js +37 -0
  22. package/dist/eip-1967-type.js.map +1 -0
  23. package/dist/eip-1967.d.ts +5 -0
  24. package/dist/eip-1967.d.ts.map +1 -1
  25. package/dist/eip-1967.js +22 -15
  26. package/dist/eip-1967.js.map +1 -1
  27. package/dist/impl-address.d.ts +19 -0
  28. package/dist/impl-address.d.ts.map +1 -0
  29. package/dist/impl-address.js +67 -0
  30. package/dist/impl-address.js.map +1 -0
  31. package/dist/impl-store.d.ts.map +1 -1
  32. package/dist/impl-store.js +8 -6
  33. package/dist/impl-store.js.map +1 -1
  34. package/dist/impl-store.test.js +18 -18
  35. package/dist/impl-store.test.js.map +1 -1
  36. package/dist/index.d.ts +7 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +23 -3
  39. package/dist/index.js.map +1 -1
  40. package/dist/levenshtein.test.js +14 -14
  41. package/dist/levenshtein.test.js.map +1 -1
  42. package/dist/link-refs.test.js +4 -4
  43. package/dist/link-refs.test.js.map +1 -1
  44. package/dist/manifest-storage-layout.js +8 -8
  45. package/dist/manifest-storage-layout.js.map +1 -1
  46. package/dist/manifest-storage-layout.test.js +16 -16
  47. package/dist/manifest-storage-layout.test.js.map +1 -1
  48. package/dist/manifest.d.ts +1 -1
  49. package/dist/manifest.d.ts.map +1 -1
  50. package/dist/manifest.js +6 -6
  51. package/dist/manifest.js.map +1 -1
  52. package/dist/manifest.test.js +2 -2
  53. package/dist/manifest.test.js.map +1 -1
  54. package/dist/provider.d.ts +2 -0
  55. package/dist/provider.d.ts.map +1 -1
  56. package/dist/provider.js +11 -1
  57. package/dist/provider.js.map +1 -1
  58. package/dist/provider.test.js +12 -12
  59. package/dist/provider.test.js.map +1 -1
  60. package/dist/proxy-kind.d.ts +12 -0
  61. package/dist/proxy-kind.d.ts.map +1 -0
  62. package/dist/proxy-kind.js +50 -0
  63. package/dist/proxy-kind.js.map +1 -0
  64. package/dist/scripts/migrate-oz-cli-project.js +1 -1
  65. package/dist/scripts/migrate-oz-cli-project.js.map +1 -1
  66. package/dist/scripts/migrate-oz-cli-project.test.js +9 -9
  67. package/dist/scripts/migrate-oz-cli-project.test.js.map +1 -1
  68. package/dist/src-decoder.test.js +2 -3
  69. package/dist/src-decoder.test.js.map +1 -1
  70. package/dist/standalone.d.ts +19 -0
  71. package/dist/standalone.d.ts.map +1 -0
  72. package/dist/standalone.js +24 -0
  73. package/dist/standalone.js.map +1 -0
  74. package/dist/standalone.test.d.ts +2 -0
  75. package/dist/standalone.test.d.ts.map +1 -0
  76. package/dist/standalone.test.js +33 -0
  77. package/dist/standalone.test.js.map +1 -0
  78. package/dist/storage/compare.js +7 -7
  79. package/dist/storage/compare.js.map +1 -1
  80. package/dist/storage/extract.js +9 -9
  81. package/dist/storage/extract.js.map +1 -1
  82. package/dist/storage/index.d.ts +7 -0
  83. package/dist/storage/index.d.ts.map +1 -1
  84. package/dist/storage/index.js +17 -11
  85. package/dist/storage/index.js.map +1 -1
  86. package/dist/storage/layout.js +1 -1
  87. package/dist/storage/layout.js.map +1 -1
  88. package/dist/storage/report.d.ts +3 -2
  89. package/dist/storage/report.d.ts.map +1 -1
  90. package/dist/storage/report.js +17 -11
  91. package/dist/storage/report.js.map +1 -1
  92. package/dist/storage/report.test.js +5 -5
  93. package/dist/storage/report.test.js.map +1 -1
  94. package/dist/storage.test.js +32 -32
  95. package/dist/storage.test.js.map +1 -1
  96. package/dist/stub-provider.d.ts.map +1 -1
  97. package/dist/stub-provider.js +0 -1
  98. package/dist/stub-provider.js.map +1 -1
  99. package/dist/usage-error.d.ts +21 -0
  100. package/dist/usage-error.d.ts.map +1 -0
  101. package/dist/usage-error.js +51 -0
  102. package/dist/usage-error.js.map +1 -0
  103. package/dist/utils/address.d.ts +8 -0
  104. package/dist/utils/address.d.ts.map +1 -0
  105. package/dist/utils/address.js +20 -0
  106. package/dist/utils/address.js.map +1 -0
  107. package/dist/utils/debug.js +1 -1
  108. package/dist/utils/debug.js.map +1 -1
  109. package/dist/utils/deep-array.test.js +12 -12
  110. package/dist/utils/deep-array.test.js.map +1 -1
  111. package/dist/utils/function.js +5 -5
  112. package/dist/utils/function.js.map +1 -1
  113. package/dist/utils/function.test.js +4 -4
  114. package/dist/utils/function.test.js.map +1 -1
  115. package/dist/utils/is-nullish.test.js +6 -6
  116. package/dist/utils/is-nullish.test.js.map +1 -1
  117. package/dist/utils/itemize.js +1 -1
  118. package/dist/utils/itemize.js.map +1 -1
  119. package/dist/utils/log.js +1 -1
  120. package/dist/utils/log.js.map +1 -1
  121. package/dist/utils/make-non-enumerable.d.ts +1 -1
  122. package/dist/utils/make-non-enumerable.d.ts.map +1 -1
  123. package/dist/utils/make-non-enumerable.js +0 -1
  124. package/dist/utils/make-non-enumerable.js.map +1 -1
  125. package/dist/utils/parse-type-id.js +1 -1
  126. package/dist/utils/parse-type-id.js.map +1 -1
  127. package/dist/utils/parse-type-id.test.js +2 -2
  128. package/dist/utils/parse-type-id.test.js.map +1 -1
  129. package/dist/utils/type-id.js +1 -1
  130. package/dist/utils/type-id.js.map +1 -1
  131. package/dist/validate/error.d.ts.map +1 -1
  132. package/dist/validate/error.js +2 -67
  133. package/dist/validate/error.js.map +1 -1
  134. package/dist/validate/index.d.ts +2 -1
  135. package/dist/validate/index.d.ts.map +1 -1
  136. package/dist/validate/index.js +4 -1
  137. package/dist/validate/index.js.map +1 -1
  138. package/dist/validate/overrides.js +2 -2
  139. package/dist/validate/overrides.js.map +1 -1
  140. package/dist/validate/query.d.ts +3 -1
  141. package/dist/validate/query.d.ts.map +1 -1
  142. package/dist/validate/query.js +45 -19
  143. package/dist/validate/query.js.map +1 -1
  144. package/dist/validate/query.test.js +4 -4
  145. package/dist/validate/query.test.js.map +1 -1
  146. package/dist/validate/report.d.ts +8 -0
  147. package/dist/validate/report.d.ts.map +1 -0
  148. package/dist/validate/report.js +79 -0
  149. package/dist/validate/report.js.map +1 -0
  150. package/dist/validate/run.js +15 -15
  151. package/dist/validate/run.js.map +1 -1
  152. package/dist/validate.test.js +7 -6
  153. package/dist/validate.test.js.map +1 -1
  154. package/dist/version.d.ts +3 -3
  155. package/dist/version.d.ts.map +1 -1
  156. package/dist/version.js +14 -8
  157. package/dist/version.js.map +1 -1
  158. package/dist/version.test.js +11 -11
  159. package/dist/version.test.js.map +1 -1
  160. package/package.json +13 -8
  161. package/src/beacon.ts +20 -0
  162. package/src/eip-1967-type.ts +35 -0
  163. package/src/eip-1967.ts +16 -12
  164. package/src/impl-address.ts +76 -0
  165. package/src/impl-store.ts +2 -0
  166. package/src/index.ts +18 -1
  167. package/src/manifest.ts +2 -2
  168. package/src/provider.ts +16 -0
  169. package/src/proxy-kind.ts +59 -0
  170. package/src/src-decoder.test.ts +0 -2
  171. package/src/standalone.test.ts +40 -0
  172. package/src/standalone.ts +41 -0
  173. package/src/storage/index.ts +14 -4
  174. package/src/storage/report.ts +10 -5
  175. package/src/stub-provider.ts +0 -1
  176. package/src/usage-error.ts +68 -0
  177. package/src/utils/address.ts +16 -0
  178. package/src/utils/make-non-enumerable.ts +1 -2
  179. package/src/validate/error.ts +5 -69
  180. package/src/validate/index.ts +2 -0
  181. package/src/validate/overrides.ts +1 -1
  182. package/src/validate/query.ts +38 -9
  183. package/src/validate/report.ts +78 -0
  184. package/src/validate.test.ts +1 -0
  185. package/src/version.ts +14 -6
  186. package/CHANGELOG.md +0 -110
  187. package/dist/set-proxy-kind.d.ts +0 -5
  188. package/dist/set-proxy-kind.d.ts.map +0 -1
  189. package/dist/set-proxy-kind.js +0 -25
  190. package/dist/set-proxy-kind.js.map +0 -1
  191. package/src/set-proxy-kind.ts +0 -27
@@ -0,0 +1,68 @@
1
+ import { EthereumProvider, getBeaconAddress, isBeaconProxy, isTransparentOrUUPSProxy, UpgradesError } from '.';
2
+
3
+ export class BeaconProxyUnsupportedError extends UpgradesError {
4
+ constructor() {
5
+ super(
6
+ 'Beacon proxies are not supported with the current function.',
7
+ () => 'Use deployBeacon(), deployBeaconProxy(), or upgradeBeacon() instead.',
8
+ );
9
+ }
10
+ }
11
+
12
+ export class DeployBeaconProxyKindError extends UpgradesError {
13
+ constructor(kind: string) {
14
+ super(
15
+ `Unsupported proxy kind '${kind}'`,
16
+ () => `deployBeaconProxy() is only supported with proxy kind undefined or 'beacon'`,
17
+ );
18
+ }
19
+ }
20
+
21
+ export class DeployBeaconProxyUnsupportedError extends UpgradesError {
22
+ constructor(beaconAddress: string) {
23
+ super(`Contract at ${beaconAddress} doesn't look like a beacon`, () => 'Deploy a beacon using deployBeacon().');
24
+ }
25
+ }
26
+
27
+ export class DeployBeaconProxyImplUnknownError extends UpgradesError {
28
+ constructor(implAddress: string) {
29
+ super(
30
+ `Beacon's current implementation at ${implAddress} is unknown`,
31
+ () => `Call deployBeaconProxy() with the implementation option providing the beacon's current implementation.`,
32
+ );
33
+ }
34
+ }
35
+
36
+ export class LoadProxyUnsupportedError extends UpgradesError {
37
+ constructor(proxyAddress: string) {
38
+ super(
39
+ `Contract at ${proxyAddress} doesn't look like a supported proxy`,
40
+ () => 'Only transparent, UUPS, or beacon proxies can be loaded with the loadProxy() function.',
41
+ );
42
+ }
43
+ }
44
+
45
+ export class PrepareUpgradeUnsupportedError extends UpgradesError {
46
+ constructor(proxyOrBeaconAddress: string) {
47
+ super(
48
+ `Contract at address ${proxyOrBeaconAddress} doesn't look like a supported proxy or beacon`,
49
+ () => `Only transparent, UUPS, or beacon proxies or beacons can be used with the prepareUpgrade() function.`,
50
+ );
51
+ }
52
+ }
53
+
54
+ export async function assertNotProxy(provider: EthereumProvider, address: string) {
55
+ if (await isTransparentOrUUPSProxy(provider, address)) {
56
+ throw new UpgradesError(
57
+ 'Address is a transparent or UUPS proxy which cannot be upgraded using upgradeBeacon().',
58
+ () => 'Use upgradeProxy() instead.',
59
+ );
60
+ } else if (await isBeaconProxy(provider, address)) {
61
+ const beaconAddress = await getBeaconAddress(provider, address);
62
+ throw new UpgradesError(
63
+ 'Address is a beacon proxy which cannot be upgraded directly.',
64
+ () =>
65
+ `upgradeBeacon() must be called with a beacon address, not a beacon proxy address. Call upgradeBeacon() on the beacon address ${beaconAddress} instead.`,
66
+ );
67
+ }
68
+ }
@@ -0,0 +1,16 @@
1
+ import { toChecksumAddress } from 'ethereumjs-util';
2
+
3
+ /**
4
+ * Parses an address from a hex string which may come from storage or a returned address via eth_call.
5
+ *
6
+ * @param addressString The address hex string.
7
+ * @returns The parsed checksum address, or undefined if the input string is not an address.
8
+ */
9
+ export function parseAddress(addressString: string): string | undefined {
10
+ const buf = Buffer.from(addressString.replace(/^0x/, ''), 'hex');
11
+ if (!buf.slice(0, 12).equals(Buffer.alloc(12, 0))) {
12
+ return undefined;
13
+ }
14
+ const address = '0x' + buf.toString('hex', 12, 32); // grab the last 20 bytes
15
+ return toChecksumAddress(address);
16
+ }
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
- export function makeNonEnumerable<O extends any>(obj: O, key: keyof O): void {
1
+ export function makeNonEnumerable<O>(obj: O, key: keyof O): void {
3
2
  Object.defineProperty(obj, key, { enumerable: false });
4
3
  }
@@ -1,75 +1,11 @@
1
- import chalk from 'chalk';
2
-
3
1
  import { ValidationError } from './run';
4
- import { UpgradesError, ErrorDescriptions } from '../error';
2
+ import { UpgradesError } from '../error';
3
+ import { UpgradeableContractErrorReport } from './report';
5
4
 
6
5
  export class ValidationErrors extends UpgradesError {
7
6
  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));
7
+ super(`Contract \`${contractName}\` is not upgrade safe`, () =>
8
+ new UpgradeableContractErrorReport(errors).explain(),
9
+ );
73
10
  }
74
- return log.join('\n ');
75
11
  }
@@ -11,7 +11,9 @@ export {
11
11
  getUnlinkedBytecode,
12
12
  getErrors,
13
13
  isUpgradeSafe,
14
+ inferProxyKind,
14
15
  } from './query';
16
+ export { UpgradeableContractErrorReport } from './report';
15
17
 
16
18
  // Backwards compatibility
17
19
  export { silenceWarnings } from '../utils/log';
@@ -69,7 +69,7 @@ export function processExceptions(
69
69
  ): ValidationError[] {
70
70
  const { unsafeAllow } = withValidationDefaults(opts);
71
71
 
72
- if (opts.kind === 'transparent') {
72
+ if (opts.kind === 'transparent' || opts.kind === 'beacon') {
73
73
  errors = errors.filter(error => error.kind !== 'missing-public-upgradeto');
74
74
  }
75
75
 
@@ -5,13 +5,15 @@ import { unlinkBytecode } from '../link-refs';
5
5
  import { ValidationOptions, processExceptions } from './overrides';
6
6
  import { ValidationErrors } from './error';
7
7
  import { ValidationData, normalizeValidationData } from './data';
8
+ import { ProxyDeployment } from '../manifest';
9
+
10
+ const upgradeToSignature = 'upgradeTo(address)';
8
11
 
9
12
  export function assertUpgradeSafe(data: ValidationData, version: Version, opts: ValidationOptions): void {
10
13
  const dataV3 = normalizeValidationData(data);
11
14
  const [contractName] = getContractNameAndRunValidation(dataV3, version);
12
15
 
13
- let errors = getErrors(dataV3, version);
14
- errors = processExceptions(contractName, errors, opts);
16
+ const errors = getErrors(dataV3, version, opts);
15
17
 
16
18
  if (errors.length > 0) {
17
19
  throw new ValidationErrors(contractName, errors);
@@ -100,28 +102,55 @@ export function getUnlinkedBytecode(data: ValidationData, bytecode: string): str
100
102
  return bytecode;
101
103
  }
102
104
 
103
- export function getErrors(data: ValidationData, version: Version): ValidationError[] {
105
+ export function getErrors(data: ValidationData, version: Version, opts: ValidationOptions = {}): ValidationError[] {
104
106
  const dataV3 = normalizeValidationData(data);
105
107
  const [contractName, runValidation] = getContractNameAndRunValidation(dataV3, version);
106
108
  const c = runValidation[contractName];
107
109
 
108
- const errors = c.errors
109
- .concat(...c.inherit.map(name => runValidation[name].errors))
110
- .concat(...c.libraries.map(name => runValidation[name].errors));
110
+ const errors = getUsedContractsAndLibraries(contractName, runValidation).flatMap(name => runValidation[name].errors);
111
111
 
112
- const selfAndInheritedMethods = c.methods.concat(...c.inherit.map(name => runValidation[name].methods));
112
+ const selfAndInheritedMethods = getAllMethods(runValidation, contractName);
113
113
 
114
- if (!selfAndInheritedMethods.includes('upgradeTo(address)')) {
114
+ if (!selfAndInheritedMethods.includes(upgradeToSignature)) {
115
115
  errors.push({
116
116
  src: c.src,
117
117
  kind: 'missing-public-upgradeto',
118
118
  });
119
119
  }
120
120
 
121
- return errors;
121
+ return processExceptions(contractName, errors, opts);
122
+ }
123
+
124
+ function getAllMethods(runValidation: ValidationRunData, contractName: string): string[] {
125
+ const c = runValidation[contractName];
126
+ return c.methods.concat(...c.inherit.map(name => runValidation[name].methods));
127
+ }
128
+
129
+ function getUsedContractsAndLibraries(contractName: string, runValidation: ValidationRunData) {
130
+ const c = runValidation[contractName];
131
+ // Add current contract and all of its parents
132
+ const res = new Set([contractName, ...c.inherit]);
133
+ // Add used libraries transitively until no more are found
134
+ for (const c1 of res) {
135
+ for (const c2 of runValidation[c1].libraries) {
136
+ res.add(c2);
137
+ }
138
+ }
139
+ return Array.from(res);
122
140
  }
123
141
 
124
142
  export function isUpgradeSafe(data: ValidationData, version: Version): boolean {
125
143
  const dataV3 = normalizeValidationData(data);
126
144
  return getErrors(dataV3, version).length == 0;
127
145
  }
146
+
147
+ export function inferProxyKind(data: ValidationData, version: Version): ProxyDeployment['kind'] {
148
+ const dataV3 = normalizeValidationData(data);
149
+ const [contractName, runValidation] = getContractNameAndRunValidation(dataV3, version);
150
+ const methods = getAllMethods(runValidation, contractName);
151
+ if (methods.includes(upgradeToSignature)) {
152
+ return 'uups';
153
+ } else {
154
+ return 'transparent';
155
+ }
156
+ }
@@ -0,0 +1,78 @@
1
+ import _chalk from 'chalk';
2
+
3
+ import { ErrorDescriptions } from '../error';
4
+ import { ValidationError } from './run';
5
+
6
+ export class UpgradeableContractErrorReport {
7
+ constructor(readonly errors: ValidationError[]) {}
8
+
9
+ get ok(): boolean {
10
+ return this.errors.length === 0;
11
+ }
12
+
13
+ explain(color = true): string {
14
+ return this.errors.map(e => describeError(e, color)).join('\n\n');
15
+ }
16
+ }
17
+
18
+ const errorInfo: ErrorDescriptions<ValidationError> = {
19
+ constructor: {
20
+ msg: e => `Contract \`${e.contract}\` has a constructor`,
21
+ hint: () => 'Define an initializer instead',
22
+ link: 'https://zpl.in/upgrades/error-001',
23
+ },
24
+ delegatecall: {
25
+ msg: () => `Use of delegatecall is not allowed`,
26
+ link: 'https://zpl.in/upgrades/error-002',
27
+ },
28
+ selfdestruct: {
29
+ msg: () => `Use of selfdestruct is not allowed`,
30
+ link: 'https://zpl.in/upgrades/error-003',
31
+ },
32
+ 'state-variable-assignment': {
33
+ msg: e => `Variable \`${e.name}\` is assigned an initial value`,
34
+ hint: () => 'Move the assignment to the initializer',
35
+ link: 'https://zpl.in/upgrades/error-004',
36
+ },
37
+ 'state-variable-immutable': {
38
+ msg: e => `Variable \`${e.name}\` is immutable`,
39
+ hint: () => `Use a constant or mutable variable instead`,
40
+ link: 'https://zpl.in/upgrades/error-005',
41
+ },
42
+ 'external-library-linking': {
43
+ msg: e => `Linking external libraries like \`${e.name}\` is not yet supported`,
44
+ hint: () =>
45
+ `Use libraries with internal functions only, or skip this check with the \`unsafeAllowLinkedLibraries\` flag \n` +
46
+ ` if you have manually checked that the libraries are upgrade safe`,
47
+ link: 'https://zpl.in/upgrades/error-006',
48
+ },
49
+ 'struct-definition': {
50
+ msg: e => `Structs like \`${e.name}\` are supported in the latest version of the plugin`,
51
+ hint: () => `Update your dependency and run again`,
52
+ },
53
+ 'enum-definition': {
54
+ msg: e => `Enums like \`${e.name}\` are supported in the latest version of the plugin`,
55
+ hint: () => `Update your dependency and run again`,
56
+ },
57
+ 'missing-public-upgradeto': {
58
+ msg: () => `Implementation is missing a public \`upgradeTo(address)\` function`,
59
+ hint: () =>
60
+ `Inherit UUPSUpgradeable to include this function in your contract\n` +
61
+ ` @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol`,
62
+ link: 'https://zpl.in/upgrades/error-008',
63
+ },
64
+ };
65
+
66
+ function describeError(e: ValidationError, color = true): string {
67
+ const chalk = new _chalk.Instance({ level: color && _chalk.supportsColor ? _chalk.supportsColor.level : 0 });
68
+ const info = errorInfo[e.kind];
69
+ const log = [chalk.bold(e.src) + ': ' + info.msg(e as any)];
70
+ const hint = info.hint?.(e as any);
71
+ if (hint) {
72
+ log.push(hint);
73
+ }
74
+ if (info.link) {
75
+ log.push(chalk.dim(info.link));
76
+ }
77
+ return log.join('\n ');
78
+ }
@@ -131,3 +131,4 @@ testValid('UsesExplicitSafeInternalLibraryNatspec', 'transparent', true);
131
131
  testValid('UsesExplicitSafeExternalLibraryNatspec', 'transparent', true);
132
132
  testValid('UsesExplicitUnsafeInternalLibraryNatspec', 'transparent', true);
133
133
  testValid('UsesExplicitUnsafeExternalLibraryNatspec', 'transparent', true);
134
+ testValid('TransitiveLibraryIsUnsafe', 'transparent', false);
package/src/version.ts CHANGED
@@ -7,19 +7,19 @@ export interface Version {
7
7
  linkedWithoutMetadata: string;
8
8
  }
9
9
 
10
- export function getVersion(bytecode: string, linkedBytecode?: string): Version {
10
+ export function getVersion(bytecode: string, linkedBytecode?: string, constructorArgs = ''): Version {
11
11
  if (bytecode !== '') {
12
12
  return {
13
13
  withMetadata: hashBytecode(bytecode),
14
14
  withoutMetadata: hashBytecodeWithoutMetadata(bytecode),
15
- linkedWithoutMetadata: hashBytecodeWithoutMetadata(linkedBytecode ?? bytecode),
15
+ linkedWithoutMetadata: hashBytecodeWithoutMetadata(linkedBytecode ?? bytecode, constructorArgs),
16
16
  };
17
17
  } else {
18
18
  throw new Error('Abstract contract not allowed here');
19
19
  }
20
20
  }
21
21
 
22
- export function hashBytecode(bytecode: string): string {
22
+ export function hashBytecode(bytecode: string, constructorArgs = ''): string {
23
23
  bytecode = bytecode
24
24
  .replace(/__\$([0-9a-fA-F]{34})\$__/g, (_, placeholder) => `000${placeholder}000`)
25
25
  .replace(/__\w{36}__/g, placeholder => keccak256(Buffer.from(placeholder)).toString('hex', 0, 20));
@@ -31,12 +31,20 @@ export function hashBytecode(bytecode: string): string {
31
31
  throw new Error('Bytecode is not a valid hex string');
32
32
  }
33
33
 
34
- const buf = Buffer.from(bytecode.replace(/^0x/, ''), 'hex');
34
+ if (!/^(0x)?[0-9a-fA-F]*$/.test(constructorArgs)) {
35
+ throw new Error('Constructor arguments are not a valid hex string');
36
+ }
37
+
38
+ const buf = Buffer.concat([
39
+ Buffer.from(bytecode.replace(/^0x/, ''), 'hex'),
40
+ Buffer.from(constructorArgs.replace(/^0x/, ''), 'hex'),
41
+ ]);
42
+
35
43
  return keccak256(buf).toString('hex');
36
44
  }
37
45
 
38
- export function hashBytecodeWithoutMetadata(bytecode: string): string {
39
- return hashBytecode(trimBytecodeMetadata(bytecode));
46
+ export function hashBytecodeWithoutMetadata(bytecode: string, constructorArgs = ''): string {
47
+ return hashBytecode(trimBytecodeMetadata(bytecode), constructorArgs);
40
48
  }
41
49
 
42
50
  function trimBytecodeMetadata(bytecode: string): string {
package/CHANGELOG.md DELETED
@@ -1,110 +0,0 @@
1
- # Changelog
2
-
3
- ## 1.9.1 (2021-09-15)
4
-
5
- - Silence all warnings when using `silenceWarnings`.
6
-
7
- ## 1.9.0 (2021-08-25)
8
-
9
- - Add `getBeaconAddress`. ([#413](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/413))
10
-
11
- ## 1.8.1 (2021-08-06)
12
-
13
- - Add support for function types.
14
-
15
- ## 1.8.0 (2021-06-29)
16
-
17
- - Add option `unsafeAllowRenames` to configure storage layout check to allow variable renaming.
18
-
19
- ## 1.7.6 (2021-05-25)
20
-
21
- - Fix recognition of value types in storage layouts.
22
-
23
- ## 1.7.5 (2021-05-22)
24
-
25
- - Fix exception when upgrading mapping key to enum.
26
-
27
- ## 1.7.4 (2021-05-22)
28
-
29
- - Fix handling of functions with struct or mapping storage pointer arguments.
30
-
31
- ## 1.7.3 (2021-05-13)
32
-
33
- - Simplify clean up of manifest data before storing to disk.
34
-
35
- ## 1.7.2 (2021-05-13)
36
-
37
- - Fix bug when the project uses external libraries.
38
-
39
- ## 1.7.1 (2021-05-03)
40
-
41
- - Use `web3_clientVersion` to better detect development networks.
42
-
43
- ## 1.7.0 (2021-04-29)
44
-
45
- - Add support for UUPS proxies. ([#315](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/315))
46
- - Fix parsing of NatSpec `@custom:oz-upgrades-unsafe-allow` when included in a `/**`-style comment.
47
-
48
- ## 1.6.0 (2021-04-14)
49
- - Add `unsafeAllow` as a new field in `ValidationOptions`, which can be used as a manual override to silence any type of validation error. For example, `opts = { unsafeAllow: ['external-library-linking', 'delegatecall'] }` will silence the corresponding checks. ([#320](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/320))
50
- - Custom NatSpec comments can disable error checks directly from the Solidity code. See `core/contracts/test/ValidationNatspec.sol` for example usage of these NatSpec comments. Note: this requires Solidity >=0.8.2. ([#320](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/320))
51
- - Fix a bug with library placeholders when hashing contract source code. ([#320](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/320))
52
-
53
- ## 1.5.1 (2021-02-24)
54
-
55
- - Add support for enum keys in mappings. ([#301](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/301))
56
-
57
- ## 1.5.0 (2021-01-27)
58
-
59
- - Add support for structs and enums. ([#261](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/261))
60
- - Enable optimizations when compiling proxies.
61
-
62
- ## 1.4.4 (2021-01-14)
63
-
64
- - Fix `InvalidDeployment` error on some networks. ([#282](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/282))
65
-
66
- ## 1.4.3 (2020-12-21)
67
-
68
- - Fix a type error caused by duplicate contract names in Truffle.
69
-
70
- ## 1.4.2 (2020-12-16)
71
-
72
- - Fix an error in the `unsafeAllowCustomTypes` flag that would cause other storage layout incompatibilities to be ignored. ([#259](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/259))
73
-
74
- Users of this flag are advised to update to this version.
75
-
76
- ## 1.4.1 (2020-11-30)
77
-
78
- - Fix a problem in deployment logic when used with Hyperledger Besu. ([#244](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/244))
79
-
80
- ## 1.4.0 (2020-11-24)
81
-
82
- - Add `silenceWarnings` to emit a single warning and silence all subsequent ones. ([#228](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/228))
83
-
84
- ## 1.3.1 (2020-11-13)
85
-
86
- - Add missing artifact files in the package.
87
-
88
- ## 1.3.0 (2020-11-13)
89
-
90
- - Support Hardhat. ([#214](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/214))
91
-
92
- ## 1.2.0 (2020-10-16)
93
-
94
- - Support new flag `unsafeAllowLinkedLibraries` to allow deployment of contracts with linked libraries. ([#182](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/182))
95
-
96
- ## 1.1.1 (2020-10-08)
97
-
98
- - Fix OpenZeppelin CLI migration for projects that were initialized with ZeppelinOS. ([#193](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/193))
99
-
100
- ## 1.1.0 (2020-09-18)
101
-
102
- - Add ability to migrate from OpenZeppelin CLI. ([#143](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/143))
103
-
104
- ## 1.0.2 (2020-09-16)
105
-
106
- - Fix false positive variable initialization check in Solidity 0.7.1. ([#171](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/171))
107
-
108
- ## 1.0.1 (2020-09-01)
109
-
110
- - Include `src` directory in npm packages. ([#150](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/150))
@@ -1,5 +0,0 @@
1
- import { EthereumProvider } from './provider';
2
- import { ValidationOptions } from './validate';
3
- import { ProxyDeployment } from './manifest';
4
- export declare function setProxyKind(provider: EthereumProvider, proxyAddress: string, opts: ValidationOptions): Promise<ProxyDeployment['kind']>;
5
- //# sourceMappingURL=set-proxy-kind.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"set-proxy-kind.d.ts","sourceRoot":"","sources":["../src/set-proxy-kind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAgC,eAAe,EAAE,MAAM,YAAY,CAAC;AAE3E,wBAAsB,YAAY,CAChC,QAAQ,EAAE,gBAAgB,EAC1B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAkBlC"}
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setProxyKind = void 0;
4
- const manifest_1 = require("./manifest");
5
- async function setProxyKind(provider, proxyAddress, opts) {
6
- var _a;
7
- const manifest = await manifest_1.Manifest.forNetwork(provider);
8
- const manifestDeployment = await manifest.getProxyFromAddress(proxyAddress).catch(e => {
9
- if (e instanceof manifest_1.DeploymentNotFound) {
10
- return undefined;
11
- }
12
- else {
13
- throw e;
14
- }
15
- });
16
- if (opts.kind === undefined) {
17
- opts.kind = (_a = manifestDeployment === null || manifestDeployment === void 0 ? void 0 : manifestDeployment.kind) !== null && _a !== void 0 ? _a : 'transparent';
18
- }
19
- else if (manifestDeployment && opts.kind !== manifestDeployment.kind) {
20
- throw new Error(`Requested an upgrade of kind ${opts.kind} but proxy is ${manifestDeployment.kind}`);
21
- }
22
- return opts.kind;
23
- }
24
- exports.setProxyKind = setProxyKind;
25
- //# sourceMappingURL=set-proxy-kind.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"set-proxy-kind.js","sourceRoot":"","sources":["../src/set-proxy-kind.ts"],"names":[],"mappings":";;;AAEA,yCAA2E;AAEpE,KAAK,UAAU,YAAY,CAChC,QAA0B,EAC1B,YAAoB,EACpB,IAAuB;;IAEvB,MAAM,QAAQ,GAAG,MAAM,mBAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAErD,MAAM,kBAAkB,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACpF,IAAI,CAAC,YAAY,6BAAkB,EAAE;YACnC,OAAO,SAAS,CAAC;SAClB;aAAM;YACL,MAAM,CAAC,CAAC;SACT;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE;QAC3B,IAAI,CAAC,IAAI,GAAG,MAAA,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,IAAI,mCAAI,aAAa,CAAC;KACvD;SAAM,IAAI,kBAAkB,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,CAAC,IAAI,EAAE;QACtE,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,IAAI,iBAAiB,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;KACtG;IAED,OAAO,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC;AAtBD,oCAsBC"}
@@ -1,27 +0,0 @@
1
- import { EthereumProvider } from './provider';
2
- import { ValidationOptions } from './validate';
3
- import { Manifest, DeploymentNotFound, ProxyDeployment } from './manifest';
4
-
5
- export async function setProxyKind(
6
- provider: EthereumProvider,
7
- proxyAddress: string,
8
- opts: ValidationOptions,
9
- ): Promise<ProxyDeployment['kind']> {
10
- const manifest = await Manifest.forNetwork(provider);
11
-
12
- const manifestDeployment = await manifest.getProxyFromAddress(proxyAddress).catch(e => {
13
- if (e instanceof DeploymentNotFound) {
14
- return undefined;
15
- } else {
16
- throw e;
17
- }
18
- });
19
-
20
- if (opts.kind === undefined) {
21
- opts.kind = manifestDeployment?.kind ?? 'transparent';
22
- } else if (manifestDeployment && opts.kind !== manifestDeployment.kind) {
23
- throw new Error(`Requested an upgrade of kind ${opts.kind} but proxy is ${manifestDeployment.kind}`);
24
- }
25
-
26
- return opts.kind;
27
- }