@openzeppelin/wizard 0.5.6 → 0.7.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.
@@ -9,10 +9,10 @@
9
9
  "author": "",
10
10
  "license": "ISC",
11
11
  "devDependencies": {
12
- "@openzeppelin/contracts": "^5.0.0",
13
- "@openzeppelin/contracts-upgradeable": "^5.0.0",
12
+ "@openzeppelin/contracts": "^5.4.0",
13
+ "@openzeppelin/contracts-upgradeable": "^5.4.0",
14
14
  "@openzeppelin/hardhat-upgrades": "^3.0.0",
15
- "@nomicfoundation/hardhat-toolbox": "^5.0.0",
15
+ "@nomicfoundation/hardhat-toolbox": "^6.1.0",
16
16
  "hardhat": "^2.16.1"
17
17
  }
18
18
  }
package/src/erc20.ts CHANGED
@@ -5,7 +5,6 @@ import { addPauseFunctions } from './add-pausable';
5
5
  import { defineFunctions } from './utils/define-functions';
6
6
  import type { CommonOptions } from './common-options';
7
7
  import { withCommonDefaults, defaults as commonDefaults } from './common-options';
8
- import type { Upgradeable } from './set-upgradeable';
9
8
  import { setUpgradeable } from './set-upgradeable';
10
9
  import { setInfo } from './set-info';
11
10
  import { printContract } from './print';
@@ -90,7 +89,7 @@ export function buildERC20(opts: ERC20Options): ContractBuilder {
90
89
  addBase(c, allOpts.name, allOpts.symbol);
91
90
 
92
91
  if (allOpts.crossChainBridging) {
93
- addCrossChainBridging(c, allOpts.crossChainBridging, allOpts.upgradeable, access);
92
+ addCrossChainBridging(c, allOpts.crossChainBridging, access);
94
93
  }
95
94
 
96
95
  if (allOpts.premint) {
@@ -305,26 +304,15 @@ function addFlashMint(c: ContractBuilder) {
305
304
  });
306
305
  }
307
306
 
308
- function addCrossChainBridging(
309
- c: ContractBuilder,
310
- crossChainBridging: 'custom' | 'superchain',
311
- upgradeable: Upgradeable,
312
- access: Access,
313
- ) {
307
+ function addCrossChainBridging(c: ContractBuilder, crossChainBridging: 'custom' | 'superchain', access: Access) {
314
308
  const ERC20Bridgeable = {
315
309
  name: 'ERC20Bridgeable',
316
- path: `@openzeppelin/community-contracts/token/ERC20/extensions/ERC20Bridgeable.sol`,
310
+ path: `@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Bridgeable.sol`,
317
311
  };
318
312
 
319
313
  c.addParent(ERC20Bridgeable);
320
314
  c.addOverride(ERC20Bridgeable, supportsInterface);
321
315
 
322
- if (upgradeable) {
323
- throw new OptionsError({
324
- crossChainBridging: 'Upgradeability is not currently supported with Cross-Chain Bridging',
325
- });
326
- }
327
-
328
316
  c.addOverride(ERC20Bridgeable, functions._checkTokenBridge);
329
317
  switch (crossChainBridging) {
330
318
  case 'custom':
@@ -345,13 +333,13 @@ function addCustomBridging(c: ContractBuilder, access: Access) {
345
333
  switch (access) {
346
334
  case false:
347
335
  case 'ownable': {
348
- const addedBridgeImmutable = c.addVariable(`address public immutable TOKEN_BRIDGE;`);
336
+ const addedBridgeImmutable = c.addVariable(`address public tokenBridge;`);
349
337
  if (addedBridgeImmutable) {
350
- c.addConstructorArgument({ type: 'address', name: 'tokenBridge' });
351
- c.addConstructorCode(`require(tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");`);
352
- c.addConstructorCode(`TOKEN_BRIDGE = tokenBridge;`);
338
+ c.addConstructorArgument({ type: 'address', name: 'tokenBridge_' });
339
+ c.addConstructorCode(`require(tokenBridge_ != address(0), "Invalid tokenBridge_ address");`);
340
+ c.addConstructorCode(`tokenBridge = tokenBridge_;`);
353
341
  }
354
- c.setFunctionBody([`if (caller != TOKEN_BRIDGE) revert Unauthorized();`], functions._checkTokenBridge, 'view');
342
+ c.setFunctionBody([`if (caller != tokenBridge) revert Unauthorized();`], functions._checkTokenBridge, 'view');
355
343
  break;
356
344
  }
357
345
  case 'roles': {
package/src/governor.ts CHANGED
@@ -4,7 +4,6 @@ import { withCommonDefaults, defaults as commonDefaults } from './common-options
4
4
  import type { Contract, ImportContract } from './contract';
5
5
  import { ContractBuilder } from './contract';
6
6
  import { OptionsError } from './error';
7
- import { setAccessControl } from './set-access-control';
8
7
  import { printContract } from './print';
9
8
  import { setInfo } from './set-info';
10
9
  import { setUpgradeableGovernor } from './set-upgradeable';
@@ -13,6 +12,7 @@ import { durationToBlocks, durationToTimestamp } from './utils/duration';
13
12
  import { clockModeDefault, type ClockMode } from './set-clock-mode';
14
13
 
15
14
  export const defaults: Required<GovernorOptions> = {
15
+ ...commonDefaults,
16
16
  name: 'MyGovernor',
17
17
  delay: '1 day',
18
18
  period: '1 week',
@@ -28,10 +28,6 @@ export const defaults: Required<GovernorOptions> = {
28
28
  quorumAbsolute: '',
29
29
  storage: false,
30
30
  settings: true,
31
-
32
- access: commonDefaults.access,
33
- upgradeable: commonDefaults.upgradeable,
34
- info: commonDefaults.info,
35
31
  } as const;
36
32
 
37
33
  export const votesOptions = ['erc20votes', 'erc721votes'] as const;
@@ -98,7 +94,6 @@ export function buildGovernor(opts: GovernorOptions): Contract {
98
94
  addQuorum(c, allOpts);
99
95
  addTimelock(c, allOpts);
100
96
 
101
- setAccessControl(c, allOpts.access);
102
97
  setUpgradeableGovernor(c, allOpts.upgradeable);
103
98
  setInfo(c, allOpts.info);
104
99
 
package/src/index.ts CHANGED
@@ -22,3 +22,11 @@ export { sanitizeKind } from './kind';
22
22
  export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
23
23
 
24
24
  export { compatibleContractsSemver } from './utils/version';
25
+
26
+ export type { ERC20Options } from './erc20';
27
+ export type { ERC721Options } from './erc721';
28
+ export type { ERC1155Options } from './erc1155';
29
+ export type { StablecoinOptions } from './stablecoin';
30
+ export type { AccountOptions } from './account';
31
+ export type { GovernorOptions } from './governor';
32
+ export type { CustomOptions } from './custom';
package/src/signer.ts CHANGED
@@ -6,11 +6,10 @@ export type SignerOptions = (typeof SignerOptions)[number];
6
6
 
7
7
  export function addSigner(c: ContractBuilder, signer: SignerOptions): void {
8
8
  if (!signer) return;
9
- const parent = signers[signer];
10
- const name = parent.name;
11
- c.addParent(parent);
9
+
10
+ c.addParent(signers[signer]);
12
11
  c.addOverride(
13
- { name: name === signers.MultisigWeighted.name ? signers.Multisig.name : name },
12
+ { name: signer === 'MultisigWeighted' ? signers.Multisig.name : signers[signer].name },
14
13
  signerFunctions._rawSignatureValidation,
15
14
  );
16
15
 
@@ -21,31 +20,29 @@ export function addSigner(c: ContractBuilder, signer: SignerOptions): void {
21
20
  name: 'Initializable',
22
21
  path: '@openzeppelin/contracts/proxy/utils/Initializable.sol',
23
22
  });
23
+
24
+ // Add locking constructor
25
+ c.addNatspecTag('@custom:oz-upgrades-unsafe-allow', 'constructor');
26
+ c.addConstructorCode(`_disableInitializers();`);
27
+
28
+ // Add initializer
24
29
  const fn = signerFunctions[`initialize${signer}`];
25
30
  c.addModifier('initializer', fn);
26
31
 
27
- const args = fn.args;
28
-
29
32
  switch (signer) {
30
33
  case 'Multisig':
31
- c.addFunctionCode(`_addSigners(${args[0]!.name});`, fn);
32
- c.addFunctionCode(`_setThreshold(${args[1]!.name});`, fn);
34
+ c.addFunctionCode(`_addSigners(${fn.args[0]!.name});`, fn);
35
+ c.addFunctionCode(`_setThreshold(${fn.args[1]!.name});`, fn);
33
36
  break;
34
37
  case 'MultisigWeighted':
35
- c.addFunctionCode(`_addSigners(${args[0]!.name});`, fn);
36
- c.addFunctionCode(`_setSignerWeights(${args[0]!.name}, ${args[1]!.name});`, fn);
37
- c.addFunctionCode(`_setThreshold(${args[2]!.name});`, fn);
38
+ c.addFunctionCode(`_addSigners(${fn.args[0]!.name});`, fn);
39
+ c.addFunctionCode(`_setSignerWeights(${fn.args[0]!.name}, ${fn.args[1]!.name});`, fn);
40
+ c.addFunctionCode(`_setThreshold(${fn.args[2]!.name});`, fn);
38
41
  break;
39
42
  case 'ECDSA':
40
43
  case 'P256':
41
44
  case 'RSA':
42
- c.addFunctionCode(
43
- `_setSigner(${fn.args
44
- .map(({ name }) => name)
45
- .join(', ')
46
- .trimEnd()});`,
47
- fn,
48
- );
45
+ c.addFunctionCode(`_setSigner(${fn.args.map(({ name }) => name).join(', ')});`, fn);
49
46
  }
50
47
  }
51
48
 
@@ -76,49 +73,47 @@ export const signers = {
76
73
  },
77
74
  };
78
75
 
79
- export const signerFunctions = {
80
- ...defineFunctions({
81
- initializeECDSA: {
82
- kind: 'public' as const,
83
- args: [{ name: 'signer', type: 'address' }],
84
- },
85
- initializeP256: {
86
- kind: 'public' as const,
87
- args: [
88
- { name: 'qx', type: 'bytes32' },
89
- { name: 'qy', type: 'bytes32' },
90
- ],
91
- },
92
- initializeRSA: {
93
- kind: 'public' as const,
94
- args: [
95
- { name: 'e', type: 'bytes memory' },
96
- { name: 'n', type: 'bytes memory' },
97
- ],
98
- },
99
- initializeMultisig: {
100
- kind: 'public' as const,
101
- args: [
102
- { name: 'signers', type: 'bytes[] memory' },
103
- { name: 'threshold', type: 'uint256' },
104
- ],
105
- },
106
- initializeMultisigWeighted: {
107
- kind: 'public' as const,
108
- args: [
109
- { name: 'signers', type: 'bytes[] memory' },
110
- { name: 'weights', type: 'uint256[] memory' },
111
- { name: 'threshold', type: 'uint256' },
112
- ],
113
- },
114
- _rawSignatureValidation: {
115
- kind: 'internal' as const,
116
- args: [
117
- { name: 'hash', type: 'bytes32' },
118
- { name: 'signature', type: 'bytes calldata' },
119
- ],
120
- returns: ['bool'],
121
- mutability: 'view' as const,
122
- },
123
- }),
124
- };
76
+ export const signerFunctions = defineFunctions({
77
+ initializeECDSA: {
78
+ kind: 'public' as const,
79
+ args: [{ name: 'signer', type: 'address' }],
80
+ },
81
+ initializeP256: {
82
+ kind: 'public' as const,
83
+ args: [
84
+ { name: 'qx', type: 'bytes32' },
85
+ { name: 'qy', type: 'bytes32' },
86
+ ],
87
+ },
88
+ initializeRSA: {
89
+ kind: 'public' as const,
90
+ args: [
91
+ { name: 'e', type: 'bytes memory' },
92
+ { name: 'n', type: 'bytes memory' },
93
+ ],
94
+ },
95
+ initializeMultisig: {
96
+ kind: 'public' as const,
97
+ args: [
98
+ { name: 'signers', type: 'bytes[] memory' },
99
+ { name: 'threshold', type: 'uint256' },
100
+ ],
101
+ },
102
+ initializeMultisigWeighted: {
103
+ kind: 'public' as const,
104
+ args: [
105
+ { name: 'signers', type: 'bytes[] memory' },
106
+ { name: 'weights', type: 'uint256[] memory' },
107
+ { name: 'threshold', type: 'uint256' },
108
+ ],
109
+ },
110
+ _rawSignatureValidation: {
111
+ kind: 'internal' as const,
112
+ args: [
113
+ { name: 'hash', type: 'bytes32' },
114
+ { name: 'signature', type: 'bytes calldata' },
115
+ ],
116
+ returns: ['bool'],
117
+ mutability: 'view' as const,
118
+ },
119
+ });
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Semantic version string representing of the minimum compatible version of Contracts to display in output.
3
3
  */
4
- export const compatibleContractsSemver = '^5.0.0';
4
+ export const compatibleContractsSemver = '^5.4.0';
@@ -147,10 +147,28 @@ main().catch((error) => {
147
147
  `;
148
148
  };
149
149
 
150
- const readme = `\
150
+ const lowerFirstCharacter = (str: string) => str.charAt(0).toLowerCase() + str.slice(1);
151
+
152
+ const ignitionModule = (c: Contract) => {
153
+ const deployArguments = getAddressArgs(c);
154
+ const contractVariableName = lowerFirstCharacter(c.name);
155
+
156
+ return `import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
157
+
158
+ export default buildModule("${c.name}Module", (m) => {
159
+
160
+ ${deployArguments.length > 0 ? '// TODO: Set addresses for the contract arguments below' : ''}
161
+ const ${contractVariableName} = m.contract("${c.name}", [${deployArguments.join(', ')}]);
162
+
163
+ return { ${contractVariableName} };
164
+ });
165
+ `;
166
+ };
167
+
168
+ const readme = (c: Contract) => `\
151
169
  # Sample Hardhat Project
152
170
 
153
- This project demonstrates a basic Hardhat use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, and a script that deploys that contract.
171
+ This project demonstrates a basic Hardhat use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, ${c.upgradeable ? 'and a script that deploys that contract' : 'and a Hardhat Ignition module that deploys that contract'}.
154
172
 
155
173
  ## Installing dependencies
156
174
 
@@ -169,7 +187,7 @@ npm test
169
187
  You can target any network from your Hardhat config using:
170
188
 
171
189
  \`\`\`
172
- npx hardhat run --network <network-name> scripts/deploy.ts
190
+ ${c.upgradeable ? 'npx hardhat run --network <network-name> scripts/deploy.ts' : `npx hardhat ignition deploy ignition/modules/${c.name}.ts --network <network-name>`}
173
191
  \`\`\`
174
192
  `;
175
193
 
@@ -196,12 +214,18 @@ export async function zipHardhat(c: Contract, opts?: GenericOptions) {
196
214
 
197
215
  zip.file(`contracts/${c.name}.sol`, printContract(c));
198
216
  zip.file('test/test.ts', test(c, opts));
199
- zip.file('scripts/deploy.ts', script(c));
217
+
218
+ if (c.upgradeable) {
219
+ zip.file('scripts/deploy.ts', script(c));
220
+ } else {
221
+ zip.file(`ignition/modules/${c.name}.ts`, ignitionModule(c));
222
+ }
223
+
200
224
  zip.file('.gitignore', gitIgnore);
201
225
  zip.file('hardhat.config.ts', hardhatConfig(c.upgradeable));
202
226
  zip.file('package.json', JSON.stringify(packageJson, null, 2));
203
227
  zip.file(`package-lock.json`, JSON.stringify(packageLock, null, 2));
204
- zip.file('README.md', readme);
228
+ zip.file('README.md', readme(c));
205
229
  zip.file('tsconfig.json', tsConfig);
206
230
 
207
231
  return zip;