@openzeppelin/wizard 0.5.4 → 0.5.6

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 (75) hide show
  1. package/README.md +13 -3
  2. package/dist/account.d.ts +20 -0
  3. package/dist/account.d.ts.map +1 -0
  4. package/dist/account.js +256 -0
  5. package/dist/account.js.map +1 -0
  6. package/dist/api.d.ts +12 -7
  7. package/dist/api.d.ts.map +1 -1
  8. package/dist/api.js +6 -1
  9. package/dist/api.js.map +1 -1
  10. package/dist/build-generic.d.ts +4 -0
  11. package/dist/build-generic.d.ts.map +1 -1
  12. package/dist/build-generic.js +3 -0
  13. package/dist/build-generic.js.map +1 -1
  14. package/dist/environments/hardhat/package-lock.json +3 -3
  15. package/dist/environments/hardhat/upgradeable/package-lock.json +7 -7
  16. package/dist/erc20.js +1 -1
  17. package/dist/erc20.js.map +1 -1
  18. package/dist/generate/account.d.ts +3 -0
  19. package/dist/generate/account.d.ts.map +1 -0
  20. package/dist/generate/account.js +21 -0
  21. package/dist/generate/account.js.map +1 -0
  22. package/dist/generate/sources.d.ts.map +1 -1
  23. package/dist/generate/sources.js +6 -0
  24. package/dist/generate/sources.js.map +1 -1
  25. package/dist/governor.d.ts +1 -1
  26. package/dist/governor.d.ts.map +1 -1
  27. package/dist/governor.js +10 -10
  28. package/dist/governor.js.map +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +2 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/kind.js +2 -1
  34. package/dist/kind.js.map +1 -1
  35. package/dist/print.d.ts.map +1 -1
  36. package/dist/print.js +2 -1
  37. package/dist/print.js.map +1 -1
  38. package/dist/set-upgradeable.d.ts +1 -0
  39. package/dist/set-upgradeable.d.ts.map +1 -1
  40. package/dist/set-upgradeable.js +13 -2
  41. package/dist/set-upgradeable.js.map +1 -1
  42. package/dist/signer.d.ts +39 -0
  43. package/dist/signer.d.ts.map +1 -0
  44. package/dist/signer.js +115 -0
  45. package/dist/signer.js.map +1 -0
  46. package/dist/solidity-version.json +1 -1
  47. package/dist/stablecoin.js +2 -2
  48. package/dist/stablecoin.js.map +1 -1
  49. package/dist/test.js +17 -6
  50. package/dist/test.js.map +1 -1
  51. package/dist/utils/sanitize.d.ts +2 -0
  52. package/dist/utils/sanitize.d.ts.map +1 -0
  53. package/dist/utils/sanitize.js +9 -0
  54. package/dist/utils/sanitize.js.map +1 -0
  55. package/dist/zip-foundry.js +4 -4
  56. package/package.json +6 -7
  57. package/src/account.ts +296 -0
  58. package/src/api.ts +16 -7
  59. package/src/build-generic.ts +6 -0
  60. package/src/environments/hardhat/package-lock.json +3 -3
  61. package/src/environments/hardhat/upgradeable/package-lock.json +7 -7
  62. package/src/erc20.ts +1 -1
  63. package/src/generate/account.ts +20 -0
  64. package/src/generate/sources.ts +7 -0
  65. package/src/governor.ts +13 -12
  66. package/src/index.ts +1 -1
  67. package/src/kind.ts +2 -1
  68. package/src/print.ts +2 -1
  69. package/src/set-upgradeable.ts +18 -2
  70. package/src/signer.ts +124 -0
  71. package/src/solidity-version.json +1 -1
  72. package/src/stablecoin.ts +2 -2
  73. package/src/test.ts +17 -5
  74. package/src/utils/sanitize.ts +6 -0
  75. package/src/zip-foundry.ts +4 -4
package/dist/test.js CHANGED
@@ -22,6 +22,9 @@ test.serial('erc1155 result compiles', async (t) => {
22
22
  test.serial('stablecoin result compiles', async (t) => {
23
23
  await testCompile(t, 'Stablecoin');
24
24
  });
25
+ test.serial('account result compiles', async (t) => {
26
+ await testCompile(t, 'Account');
27
+ });
25
28
  test.serial('governor result compiles', async (t) => {
26
29
  await testCompile(t, 'Governor');
27
30
  });
@@ -53,6 +56,8 @@ function isAccessControlRequired(opts) {
53
56
  return api_1.stablecoin.isAccessControlRequired(opts);
54
57
  case 'RealWorldAsset':
55
58
  return api_1.stablecoin.isAccessControlRequired(opts);
59
+ case 'Account':
60
+ throw new Error(`Not applicable for ${opts.kind}`);
56
61
  case 'Governor':
57
62
  return api_1.governor.isAccessControlRequired(opts);
58
63
  case 'Custom':
@@ -64,12 +69,18 @@ function isAccessControlRequired(opts) {
64
69
  test('is access control required', async (t) => {
65
70
  for (const contract of (0, sources_1.generateSources)('all')) {
66
71
  const regexOwnable = /import.*Ownable(Upgradeable)?.sol.*/gm;
67
- if (!contract.options.access) {
68
- if (isAccessControlRequired(contract.options)) {
69
- t.regex(contract.source, regexOwnable, JSON.stringify(contract.options));
70
- }
71
- else {
72
- t.notRegex(contract.source, regexOwnable, JSON.stringify(contract.options));
72
+ switch (contract.options.kind) {
73
+ case 'Account':
74
+ break;
75
+ default: {
76
+ if (!contract.options.access) {
77
+ if (isAccessControlRequired(contract.options)) {
78
+ t.regex(contract.source, regexOwnable, JSON.stringify(contract.options));
79
+ }
80
+ else {
81
+ t.notRegex(contract.source, regexOwnable, JSON.stringify(contract.options));
82
+ }
83
+ }
73
84
  }
74
85
  }
75
86
  }
package/dist/test.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function stringifyUnicodeSafe(str: string): string;
2
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKxD"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stringifyUnicodeSafe = stringifyUnicodeSafe;
4
+ function stringifyUnicodeSafe(str) {
5
+ // eslint-disable-next-line no-control-regex
6
+ const containsUnicode = /[^\x00-\x7F]/.test(str);
7
+ return containsUnicode ? `unicode"${str.replace(/"/g, '\\"')}"` : JSON.stringify(str);
8
+ }
9
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":";;AAAA,oDAKC;AALD,SAAgB,oBAAoB,CAAC,GAAW;IAC9C,4CAA4C;IAC5C,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjD,OAAO,eAAe,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACxF,CAAC"}
@@ -184,17 +184,17 @@ then
184
184
  mv README.md README-oz.md
185
185
 
186
186
  # Initialize sample Foundry project
187
- forge init --force --no-commit --quiet
187
+ forge init --force --quiet
188
188
 
189
189
  ${c.upgradeable
190
190
  ? `\
191
191
  # Install OpenZeppelin Contracts and Upgrades
192
- forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v${openzeppelin_contracts_1.default.version} --no-commit --quiet
193
- forge install OpenZeppelin/openzeppelin-foundry-upgrades --no-commit --quiet\
192
+ forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v${openzeppelin_contracts_1.default.version} --quiet
193
+ forge install OpenZeppelin/openzeppelin-foundry-upgrades --quiet\
194
194
  `
195
195
  : `\
196
196
  # Install OpenZeppelin Contracts
197
- forge install OpenZeppelin/openzeppelin-contracts@v${openzeppelin_contracts_1.default.version} --no-commit --quiet\
197
+ forge install OpenZeppelin/openzeppelin-contracts@v${openzeppelin_contracts_1.default.version} --quiet\
198
198
  `}
199
199
 
200
200
  # Remove unneeded Foundry template files
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openzeppelin/wizard",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "A boilerplate generator to get started with OpenZeppelin Contracts",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": "https://github.com/OpenZeppelin/contracts-wizard",
@@ -19,17 +19,16 @@
19
19
  "test": "ava",
20
20
  "test:update-snapshots": "ava --update-snapshots",
21
21
  "test:watch": "ava --watch",
22
- "version": "node ../../../scripts/bump-changelog.js",
23
22
  "update-env": "rm ./src/environments/hardhat/package-lock.json && npm install --package-lock-only --prefix ./src/environments/hardhat && rm ./src/environments/hardhat/upgradeable/package-lock.json && npm install --package-lock-only --prefix ./src/environments/hardhat/upgradeable"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@openzeppelin/community-contracts": "https://github.com/OpenZeppelin/openzeppelin-community-contracts",
27
- "@openzeppelin/contracts": "^5.1.0",
28
- "@openzeppelin/contracts-upgradeable": "^5.1.0",
29
- "@types/node": "^18.0.0",
26
+ "@openzeppelin/contracts": "^5.3.0",
27
+ "@openzeppelin/contracts-upgradeable": "^5.3.0",
28
+ "@types/node": "^20.0.0",
30
29
  "@types/semver": "^7.5.7",
31
30
  "ava": "^6.0.0",
32
- "hardhat": "^2.1.1",
31
+ "hardhat": "^2.22.11",
33
32
  "jszip": "^3.6.0",
34
33
  "rimraf": "^5.0.0",
35
34
  "semver": "^7.6.0",
@@ -37,4 +36,4 @@
37
36
  "ts-node": "^10.4.0",
38
37
  "typescript": "^5.0.0"
39
38
  }
40
- }
39
+ }
package/src/account.ts ADDED
@@ -0,0 +1,296 @@
1
+ import { ContractBuilder } from './contract';
2
+ import type { Contract } from './contract';
3
+ import { defineFunctions } from './utils/define-functions';
4
+ import { printContract } from './print';
5
+ import { defaults as commonDefaults, withCommonDefaults, type CommonOptions } from './common-options';
6
+ import { setInfo } from './set-info';
7
+ import { addSigner, signerFunctions, signers, type SignerOptions } from './signer';
8
+
9
+ export const defaults: Required<AccountOptions> = {
10
+ ...commonDefaults,
11
+ name: 'MyAccount',
12
+ signatureValidation: 'ERC7739',
13
+ ERC721Holder: true,
14
+ ERC1155Holder: true,
15
+ signer: 'ECDSA',
16
+ batchedExecution: false,
17
+ ERC7579Modules: false,
18
+ } as const;
19
+
20
+ export const SignatureValidationOptions = [false, 'ERC1271', 'ERC7739'] as const;
21
+ export type SignatureValidationOptions = (typeof SignatureValidationOptions)[number];
22
+
23
+ export const ERC7579ModulesOptions = [false, 'AccountERC7579', 'AccountERC7579Hooked'] as const;
24
+ export type ERC7579ModulesOptions = (typeof ERC7579ModulesOptions)[number];
25
+
26
+ export interface AccountOptions extends CommonOptions {
27
+ name: string;
28
+ signatureValidation?: SignatureValidationOptions;
29
+ ERC721Holder?: boolean;
30
+ ERC1155Holder?: boolean;
31
+ signer?: SignerOptions;
32
+ batchedExecution?: boolean;
33
+ ERC7579Modules?: ERC7579ModulesOptions;
34
+ }
35
+
36
+ function withDefaults(opts: AccountOptions): Required<AccountOptions> {
37
+ return {
38
+ ...withCommonDefaults(opts),
39
+ name: opts.name ?? defaults.name,
40
+ signatureValidation: opts.signatureValidation ?? defaults.signatureValidation,
41
+ ERC721Holder: opts.ERC721Holder ?? defaults.ERC721Holder,
42
+ ERC1155Holder: opts.ERC1155Holder ?? defaults.ERC1155Holder,
43
+ signer: opts.signer ?? defaults.signer,
44
+ batchedExecution: opts.batchedExecution ?? defaults.batchedExecution,
45
+ ERC7579Modules: opts.ERC7579Modules ?? defaults.ERC7579Modules,
46
+ };
47
+ }
48
+
49
+ export function printAccount(opts: AccountOptions = defaults): string {
50
+ return printContract(buildAccount(opts));
51
+ }
52
+
53
+ export function buildAccount(opts: AccountOptions): Contract {
54
+ const allOpts = withDefaults(opts);
55
+
56
+ allOpts.upgradeable = false; // Upgradeability is not yet available for the community contracts
57
+ allOpts.access = false; // Access control options are not used for Account
58
+
59
+ const c = new ContractBuilder(allOpts.name);
60
+
61
+ addParents(c, allOpts);
62
+ overrideRawSignatureValidation(c, allOpts);
63
+ setInfo(c, allOpts.info);
64
+
65
+ if (opts.ERC7579Modules) {
66
+ c.addImportOnly({
67
+ name: 'PackedUserOperation',
68
+ path: '@openzeppelin/contracts/interfaces/draft-IERC4337.sol',
69
+ });
70
+ }
71
+
72
+ return c;
73
+ }
74
+
75
+ function addParents(c: ContractBuilder, opts: AccountOptions): void {
76
+ // Base
77
+ c.addParent({
78
+ name: 'Account',
79
+ path: `@openzeppelin/community-contracts/account/Account.sol`,
80
+ });
81
+ c.addOverride({ name: 'Account' }, functions._validateUserOp);
82
+
83
+ if (opts.signatureValidation === 'ERC7739') addEIP712(c, opts);
84
+
85
+ // Extensions
86
+ addSignatureValidation(c, opts);
87
+ addERC7579Modules(c, opts);
88
+ addSigner(c, opts.signer ?? false);
89
+ addMultisigFunctions(c, opts);
90
+ addBatchedExecution(c, opts);
91
+ addERC721Holder(c, opts);
92
+ addERC1155Holder(c, opts);
93
+ }
94
+
95
+ function addSignatureValidation(c: ContractBuilder, opts: AccountOptions) {
96
+ switch (opts.signatureValidation) {
97
+ case 'ERC7739':
98
+ c.addParent({
99
+ name: 'ERC7739',
100
+ path: '@openzeppelin/community-contracts/utils/cryptography/ERC7739.sol',
101
+ });
102
+ break;
103
+ case 'ERC1271':
104
+ c.addParent({
105
+ name: 'IERC1271',
106
+ path: '@openzeppelin/contracts/interfaces/IERC1271.sol',
107
+ });
108
+ c.addOverride({ name: 'IERC1271' }, functions.isValidSignature);
109
+ if (!opts.ERC7579Modules) {
110
+ c.setFunctionBody(
111
+ [
112
+ 'return _rawSignatureValidation(hash, signature) ? IERC1271.isValidSignature.selector : bytes4(0xffffffff);',
113
+ ],
114
+ functions.isValidSignature,
115
+ );
116
+ }
117
+ break;
118
+ }
119
+ }
120
+
121
+ function addERC721Holder(c: ContractBuilder, opts: AccountOptions): void {
122
+ if (!opts.ERC721Holder) return;
123
+ c.addParent({
124
+ name: 'ERC721Holder',
125
+ path: '@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol',
126
+ });
127
+ }
128
+
129
+ function addERC1155Holder(c: ContractBuilder, opts: AccountOptions): void {
130
+ if (!opts.ERC1155Holder) return;
131
+ c.addParent({
132
+ name: 'ERC1155Holder',
133
+ path: '@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol',
134
+ });
135
+ }
136
+
137
+ function addBatchedExecution(c: ContractBuilder, opts: AccountOptions): void {
138
+ // ERC-7579 is a superset of ERC-7821
139
+ if (!opts.batchedExecution || !!opts.ERC7579Modules) return;
140
+ c.addParent({
141
+ name: 'ERC7821',
142
+ path: '@openzeppelin/community-contracts/account/extensions/ERC7821.sol',
143
+ });
144
+ c.addOverride({ name: 'ERC7821' }, functions._erc7821AuthorizedExecutor);
145
+ c.setFunctionBody(
146
+ ['return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);'],
147
+ functions._erc7821AuthorizedExecutor,
148
+ );
149
+ }
150
+
151
+ function addERC7579Modules(c: ContractBuilder, opts: AccountOptions): void {
152
+ if (!opts.ERC7579Modules) return;
153
+ c.addParent({
154
+ name: opts.ERC7579Modules,
155
+ path: `@openzeppelin/community-contracts/account/extensions/${opts.ERC7579Modules}.sol`,
156
+ });
157
+ if (opts.ERC7579Modules !== 'AccountERC7579') {
158
+ c.addImportOnly({
159
+ name: 'AccountERC7579',
160
+ path: `@openzeppelin/community-contracts/account/extensions/AccountERC7579.sol`,
161
+ });
162
+ }
163
+ c.addOverride({ name: 'AccountERC7579' }, functions.isValidSignature);
164
+ c.addOverride({ name: 'AccountERC7579' }, functions._validateUserOp);
165
+
166
+ if (opts.signatureValidation !== 'ERC7739') return;
167
+ c.addOverride({ name: 'ERC7739' }, functions.isValidSignature);
168
+ c.setFunctionBody(
169
+ [
170
+ '// ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).',
171
+ '// If the returned value is 0xffffffff, fallback to ERC-7579 validation.',
172
+ 'bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);',
173
+ 'return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;',
174
+ ],
175
+ functions.isValidSignature,
176
+ );
177
+ }
178
+
179
+ function addMultisigFunctions(c: ContractBuilder, opts: AccountOptions): void {
180
+ switch (opts.signer) {
181
+ case 'MultisigWeighted':
182
+ c.addFunctionCode(
183
+ `_setSignerWeights(${functions.setSignerWeights.args.map(({ name }) => name).join(', ')});`,
184
+ functions.setSignerWeights,
185
+ );
186
+ c.addModifier('onlyEntryPointOrSelf', functions.setSignerWeights);
187
+ // eslint-disable-next-line no-fallthrough
188
+ case 'Multisig':
189
+ c.addFunctionCode(`_addSigners(${functions.addSigners.args[0]!.name});`, functions.addSigners);
190
+ c.addModifier('onlyEntryPointOrSelf', functions.addSigners);
191
+ c.addFunctionCode(`_removeSigners(${functions.removeSigners.args[0]!.name});`, functions.removeSigners);
192
+ c.addModifier('onlyEntryPointOrSelf', functions.removeSigners);
193
+ c.addFunctionCode(`_setThreshold(${functions.setThreshold.args[0]!.name});`, functions.setThreshold);
194
+ c.addModifier('onlyEntryPointOrSelf', functions.setThreshold);
195
+ break;
196
+ default:
197
+ }
198
+ }
199
+
200
+ function addEIP712(c: ContractBuilder, opts: AccountOptions): void {
201
+ if (opts.signatureValidation != 'ERC7739') return;
202
+ c.addParent(
203
+ {
204
+ name: 'EIP712',
205
+ path: '@openzeppelin/contracts/utils/cryptography/EIP712.sol',
206
+ },
207
+ [opts.name, '1'],
208
+ );
209
+ }
210
+
211
+ function overrideRawSignatureValidation(c: ContractBuilder, opts: AccountOptions): void {
212
+ if (opts.signer && !opts.ERC7579Modules) return; // Signer implements _rawSignatureValidation alone
213
+ if (!opts.signer && opts.ERC7579Modules) return; // AccountERC7579 implements _rawSignatureValidation alone
214
+
215
+ // If no signer or ERC-7579 is used, we need to override the _rawSignatureValidation function
216
+ // to provide a custom validation logic
217
+ if (!opts.signer && !opts.ERC7579Modules) {
218
+ // Custom validation logic
219
+ c.addOverride({ name: 'Account' }, signerFunctions._rawSignatureValidation);
220
+ c.setFunctionBody(['// Custom validation logic', 'return false;'], signerFunctions._rawSignatureValidation);
221
+ }
222
+
223
+ // Disambiguate between Signer and AccountERC7579
224
+ if (opts.signer && opts.ERC7579Modules) {
225
+ c.addImportOnly({
226
+ name: 'AbstractSigner',
227
+ path: '@openzeppelin/community-contracts/utils/cryptography/AbstractSigner.sol',
228
+ });
229
+ c.addOverride({ name: 'AbstractSigner' }, signerFunctions._rawSignatureValidation);
230
+ c.addOverride({ name: 'AccountERC7579' }, signerFunctions._rawSignatureValidation);
231
+ c.setFunctionComments(
232
+ [
233
+ `// IMPORTANT: Make sure Signer${opts.signer} is most derived than AccountERC7579`,
234
+ `// in the inheritance chain (i.e. contract ... is AccountERC7579, ..., Signer${opts.signer})`,
235
+ '// to ensure the correct order of function resolution.',
236
+ '// AccountERC7579 returns false for `_rawSignatureValidation`',
237
+ ],
238
+ signerFunctions._rawSignatureValidation,
239
+ );
240
+ // Base override for `_rawSignatureValidation` given MultiSignerERC7913Weighted is MultiSignerERC7913
241
+ if (opts.signer === 'MultisigWeighted') {
242
+ c.addImportOnly(signers.Multisig);
243
+ }
244
+ }
245
+ }
246
+
247
+ const functions = {
248
+ ...defineFunctions({
249
+ isValidSignature: {
250
+ kind: 'public' as const,
251
+ mutability: 'view' as const,
252
+ args: [
253
+ { name: 'hash', type: 'bytes32' },
254
+ { name: 'signature', type: 'bytes calldata' },
255
+ ],
256
+ returns: ['bytes4'],
257
+ },
258
+ _validateUserOp: {
259
+ kind: 'internal' as const,
260
+ args: [
261
+ { name: 'userOp', type: 'PackedUserOperation calldata' },
262
+ { name: 'userOpHash', type: 'bytes32' },
263
+ ],
264
+ returns: ['uint256'],
265
+ },
266
+ _erc7821AuthorizedExecutor: {
267
+ kind: 'internal' as const,
268
+ args: [
269
+ { name: 'caller', type: 'address' },
270
+ { name: 'mode', type: 'bytes32' },
271
+ { name: 'executionData', type: 'bytes calldata' },
272
+ ],
273
+ returns: ['bool'],
274
+ mutability: 'view' as const,
275
+ },
276
+ addSigners: {
277
+ kind: 'public' as const,
278
+ args: [{ name: 'signers', type: 'bytes[] memory' }],
279
+ },
280
+ removeSigners: {
281
+ kind: 'public' as const,
282
+ args: [{ name: 'signers', type: 'bytes[] memory' }],
283
+ },
284
+ setThreshold: {
285
+ kind: 'public' as const,
286
+ args: [{ name: 'threshold', type: 'uint256' }],
287
+ },
288
+ setSignerWeights: {
289
+ kind: 'public' as const,
290
+ args: [
291
+ { name: 'signers', type: 'bytes[] memory' },
292
+ { name: 'weights', type: 'uint256[] memory' },
293
+ ],
294
+ },
295
+ }),
296
+ };
package/src/api.ts CHANGED
@@ -23,6 +23,8 @@ import {
23
23
  defaults as stablecoinDefaults,
24
24
  isAccessControlRequired as stablecoinIsAccessControlRequired,
25
25
  } from './stablecoin';
26
+ import type { AccountOptions } from './account';
27
+ import { printAccount, defaults as accountDefaults } from './account';
26
28
  import type { GovernorOptions } from './governor';
27
29
  import {
28
30
  printGovernor,
@@ -46,7 +48,9 @@ export interface WizardContractAPI<Options extends CommonOptions> {
46
48
  * The default options that are used for `print`.
47
49
  */
48
50
  defaults: Required<Options>;
51
+ }
49
52
 
53
+ export interface AccessControlAPI<Options extends CommonOptions> {
50
54
  /**
51
55
  * Whether any of the provided options require access control to be enabled. If this returns `true`, then calling `print` with the
52
56
  * same options would cause the `access` option to default to `'ownable'` if it was `undefined` or `false`.
@@ -54,13 +58,14 @@ export interface WizardContractAPI<Options extends CommonOptions> {
54
58
  isAccessControlRequired: (opts: Partial<Options>) => boolean;
55
59
  }
56
60
 
57
- export type ERC20 = WizardContractAPI<ERC20Options>;
58
- export type ERC721 = WizardContractAPI<ERC721Options>;
59
- export type ERC1155 = WizardContractAPI<ERC1155Options>;
60
- export type Stablecoin = WizardContractAPI<StablecoinOptions>;
61
- export type RealWorldAsset = WizardContractAPI<StablecoinOptions>;
62
- export type Governor = WizardContractAPI<GovernorOptions>;
63
- export type Custom = WizardContractAPI<CustomOptions>;
61
+ export type ERC20 = WizardContractAPI<ERC20Options> & AccessControlAPI<ERC20Options>;
62
+ export type ERC721 = WizardContractAPI<ERC721Options> & AccessControlAPI<ERC721Options>;
63
+ export type ERC1155 = WizardContractAPI<ERC1155Options> & AccessControlAPI<ERC1155Options>;
64
+ export type Stablecoin = WizardContractAPI<StablecoinOptions> & AccessControlAPI<StablecoinOptions>;
65
+ export type RealWorldAsset = WizardContractAPI<StablecoinOptions> & AccessControlAPI<StablecoinOptions>;
66
+ export type Account = WizardContractAPI<AccountOptions>;
67
+ export type Governor = WizardContractAPI<GovernorOptions> & AccessControlAPI<GovernorOptions>;
68
+ export type Custom = WizardContractAPI<CustomOptions> & AccessControlAPI<CustomOptions>;
64
69
 
65
70
  export const erc20: ERC20 = {
66
71
  print: printERC20,
@@ -82,6 +87,10 @@ export const stablecoin: Stablecoin = {
82
87
  defaults: stablecoinDefaults,
83
88
  isAccessControlRequired: stablecoinIsAccessControlRequired,
84
89
  };
90
+ export const account: Account = {
91
+ print: printAccount,
92
+ defaults: accountDefaults,
93
+ };
85
94
  export const realWorldAsset: RealWorldAsset = {
86
95
  print: printStablecoin,
87
96
  defaults: stablecoinDefaults,
@@ -11,6 +11,8 @@ import { buildStablecoin } from './stablecoin';
11
11
  import type { GovernorOptions } from './governor';
12
12
  import { buildGovernor } from './governor';
13
13
  import type { Contract } from './contract';
14
+ import { buildAccount } from './account';
15
+ import type { AccountOptions } from './account';
14
16
 
15
17
  export interface KindedOptions {
16
18
  ERC20: { kind: 'ERC20' } & ERC20Options;
@@ -18,6 +20,7 @@ export interface KindedOptions {
18
20
  ERC1155: { kind: 'ERC1155' } & ERC1155Options;
19
21
  Stablecoin: { kind: 'Stablecoin' } & StablecoinOptions;
20
22
  RealWorldAsset: { kind: 'RealWorldAsset' } & StablecoinOptions;
23
+ Account: { kind: 'Account' } & AccountOptions;
21
24
  Governor: { kind: 'Governor' } & GovernorOptions;
22
25
  Custom: { kind: 'Custom' } & CustomOptions;
23
26
  }
@@ -41,6 +44,9 @@ export function buildGeneric(opts: GenericOptions): Contract {
41
44
  case 'RealWorldAsset':
42
45
  return buildStablecoin(opts);
43
46
 
47
+ case 'Account':
48
+ return buildAccount(opts);
49
+
44
50
  case 'Governor':
45
51
  return buildGovernor(opts);
46
52
 
@@ -1510,9 +1510,9 @@
1510
1510
  }
1511
1511
  },
1512
1512
  "node_modules/@openzeppelin/contracts": {
1513
- "version": "5.2.0",
1514
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.2.0.tgz",
1515
- "integrity": "sha512-bxjNie5z89W1Ea0NZLZluFh8PrFNn9DH8DQlujEok2yjsOlraUPKID5p1Wk3qdNbf6XkQ1Os2RvfiHrrXLHWKA==",
1513
+ "version": "5.3.0",
1514
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.3.0.tgz",
1515
+ "integrity": "sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==",
1516
1516
  "dev": true,
1517
1517
  "license": "MIT"
1518
1518
  },
@@ -2195,20 +2195,20 @@
2195
2195
  }
2196
2196
  },
2197
2197
  "node_modules/@openzeppelin/contracts": {
2198
- "version": "5.2.0",
2199
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.2.0.tgz",
2200
- "integrity": "sha512-bxjNie5z89W1Ea0NZLZluFh8PrFNn9DH8DQlujEok2yjsOlraUPKID5p1Wk3qdNbf6XkQ1Os2RvfiHrrXLHWKA==",
2198
+ "version": "5.3.0",
2199
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.3.0.tgz",
2200
+ "integrity": "sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==",
2201
2201
  "dev": true,
2202
2202
  "license": "MIT"
2203
2203
  },
2204
2204
  "node_modules/@openzeppelin/contracts-upgradeable": {
2205
- "version": "5.2.0",
2206
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.2.0.tgz",
2207
- "integrity": "sha512-mZIu9oa4tQTlGiOJHk6D3LdJlqFqF6oNOSn6S6UVJtzfs9UsY9/dhMEbAVTwElxUtJnjpf6yA062+oBp+eOyPg==",
2205
+ "version": "5.3.0",
2206
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.3.0.tgz",
2207
+ "integrity": "sha512-yVzSSyTMWO6rapGI5tuqkcLpcGGXA0UA1vScyV5EhE5yw8By3Ewex9rDUw8lfVw0iTkvR/egjfcW5vpk03lqZg==",
2208
2208
  "dev": true,
2209
2209
  "license": "MIT",
2210
2210
  "peerDependencies": {
2211
- "@openzeppelin/contracts": "5.2.0"
2211
+ "@openzeppelin/contracts": "5.3.0"
2212
2212
  }
2213
2213
  },
2214
2214
  "node_modules/@openzeppelin/defender-sdk-base-client": {
package/src/erc20.ts CHANGED
@@ -313,7 +313,7 @@ function addCrossChainBridging(
313
313
  ) {
314
314
  const ERC20Bridgeable = {
315
315
  name: 'ERC20Bridgeable',
316
- path: `@openzeppelin/community-contracts/contracts/token/ERC20/extensions/ERC20Bridgeable.sol`,
316
+ path: `@openzeppelin/community-contracts/token/ERC20/extensions/ERC20Bridgeable.sol`,
317
317
  };
318
318
 
319
319
  c.addParent(ERC20Bridgeable);
@@ -0,0 +1,20 @@
1
+ import type { AccountOptions } from '../account';
2
+ import { infoOptions } from '../set-info';
3
+ import { generateAlternatives } from './alternatives';
4
+
5
+ const account = {
6
+ name: ['MyAccount'],
7
+ signatureValidation: [false, 'ERC1271', 'ERC7739'] as const,
8
+ ERC721Holder: [false, true] as const,
9
+ ERC1155Holder: [false, true] as const,
10
+ signer: ['ERC7702', 'ECDSA', 'P256', 'RSA', 'Multisig', 'MultisigWeighted'] as const,
11
+ batchedExecution: [false, true] as const,
12
+ ERC7579Modules: [false, 'AccountERC7579', 'AccountERC7579Hooked'] as const,
13
+ access: [false] as const,
14
+ upgradeable: [false] as const,
15
+ info: infoOptions,
16
+ };
17
+
18
+ export function* generateAccountOptions(): Generator<Required<AccountOptions>> {
19
+ yield* generateAlternatives(account);
20
+ }
@@ -6,6 +6,7 @@ import { generateERC20Options } from './erc20';
6
6
  import { generateERC721Options } from './erc721';
7
7
  import { generateERC1155Options } from './erc1155';
8
8
  import { generateStablecoinOptions } from './stablecoin';
9
+ import { generateAccountOptions } from './account';
9
10
  import { generateGovernorOptions } from './governor';
10
11
  import { generateCustomOptions } from './custom';
11
12
  import type { GenericOptions, KindedOptions } from '../build-generic';
@@ -50,6 +51,12 @@ export function* generateOptions(kind?: Kind): Generator<GenericOptions> {
50
51
  }
51
52
  }
52
53
 
54
+ if (!kind || kind === 'Account') {
55
+ for (const kindOpts of generateAccountOptions()) {
56
+ yield { kind: 'Account', ...kindOpts };
57
+ }
58
+ }
59
+
53
60
  if (!kind || kind === 'Governor') {
54
61
  for (const kindOpts of generateGovernorOptions()) {
55
62
  yield { kind: 'Governor', ...kindOpts };