@openzeppelin/wizard 0.10.5 → 0.10.7

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 (56) hide show
  1. package/dist/common-options.js +1 -1
  2. package/dist/common-options.js.map +1 -1
  3. package/dist/contract.d.ts +1 -1
  4. package/dist/contract.d.ts.map +1 -1
  5. package/dist/contract.js +1 -1
  6. package/dist/contract.js.map +1 -1
  7. package/dist/environments/hardhat/package-lock.json +4 -4
  8. package/dist/environments/hardhat/package.json +1 -1
  9. package/dist/environments/hardhat/upgradeable/package-lock.json +9 -9
  10. package/dist/environments/hardhat/upgradeable/package.json +2 -2
  11. package/dist/erc20.d.ts +10 -2
  12. package/dist/erc20.d.ts.map +1 -1
  13. package/dist/erc20.js +125 -50
  14. package/dist/erc20.js.map +1 -1
  15. package/dist/generate/erc20.d.ts.map +1 -1
  16. package/dist/generate/erc20.js +25 -6
  17. package/dist/generate/erc20.js.map +1 -1
  18. package/dist/generate/stablecoin.d.ts.map +1 -1
  19. package/dist/generate/stablecoin.js +2 -0
  20. package/dist/generate/stablecoin.js.map +1 -1
  21. package/dist/index.d.ts +23 -15
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +34 -21
  24. package/dist/index.js.map +1 -1
  25. package/dist/options.d.ts +3 -0
  26. package/dist/options.d.ts.map +1 -1
  27. package/dist/options.js.map +1 -1
  28. package/dist/print.d.ts.map +1 -1
  29. package/dist/print.js +38 -26
  30. package/dist/print.js.map +1 -1
  31. package/dist/stablecoin.d.ts.map +1 -1
  32. package/dist/stablecoin.js +1 -1
  33. package/dist/stablecoin.js.map +1 -1
  34. package/dist/utils/convert-strings.d.ts +21 -2
  35. package/dist/utils/convert-strings.d.ts.map +1 -1
  36. package/dist/utils/convert-strings.js +28 -4
  37. package/dist/utils/convert-strings.js.map +1 -1
  38. package/dist/utils/version.d.ts +1 -1
  39. package/dist/utils/version.js +1 -1
  40. package/openzeppelin-contracts-version.json +1 -1
  41. package/package.json +5 -5
  42. package/src/common-options.ts +1 -1
  43. package/src/contract.ts +2 -2
  44. package/src/environments/hardhat/package-lock.json +4 -4
  45. package/src/environments/hardhat/package.json +1 -1
  46. package/src/environments/hardhat/upgradeable/package-lock.json +9 -9
  47. package/src/environments/hardhat/upgradeable/package.json +2 -2
  48. package/src/erc20.ts +163 -51
  49. package/src/generate/erc20.ts +27 -6
  50. package/src/generate/stablecoin.ts +2 -0
  51. package/src/index.ts +30 -18
  52. package/src/options.ts +3 -1
  53. package/src/print.ts +47 -26
  54. package/src/stablecoin.ts +2 -1
  55. package/src/utils/convert-strings.ts +28 -4
  56. package/src/utils/version.ts +1 -1
@@ -19,6 +19,6 @@ export function withCommonDefaults(opts: CommonOptions): Required<CommonOptions>
19
19
  return {
20
20
  access: opts.access ?? false,
21
21
  upgradeable: opts.upgradeable ?? false,
22
- info: opts.info ?? {},
22
+ info: { ...defaults.info, ...(opts.info ?? {}) },
23
23
  };
24
24
  }
package/src/contract.ts CHANGED
@@ -100,9 +100,9 @@ export class ContractBuilder implements Contract {
100
100
 
101
101
  readonly variableOrErrorMap: Map<string, VariableOrErrorDefinition> = new Map<string, VariableOrErrorDefinition>();
102
102
  private parentMap: Map<string, Parent> = new Map<string, Parent>();
103
+ private functionMap: Map<string, ContractFunction> = new Map<string, ContractFunction>();
103
104
  private libraryMap: Map<string, Library> = new Map<string, Library>();
104
- private functionMap: Map<string, ContractFunction> = new Map();
105
- private structMap: Map<string, ContractStruct> = new Map();
105
+ private structMap: Map<string, ContractStruct> = new Map<string, ContractStruct>();
106
106
 
107
107
  constructor(name: string) {
108
108
  this.name = toIdentifier(name, true);
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "devDependencies": {
12
12
  "@nomicfoundation/hardhat-toolbox": "^6.1.0",
13
- "@openzeppelin/contracts": "^5.5.0",
13
+ "@openzeppelin/contracts": "^5.6.0",
14
14
  "hardhat": "^2.22.0"
15
15
  }
16
16
  },
@@ -1219,9 +1219,9 @@
1219
1219
  }
1220
1220
  },
1221
1221
  "node_modules/@openzeppelin/contracts": {
1222
- "version": "5.5.0",
1223
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.5.0.tgz",
1224
- "integrity": "sha512-R8hq4zmKKWP2c7OxeRgAcjZwvF5W0Qq2OIX7degrtdM52Q9xYr4MLJdUAVPKGUewNJ1qo+M6YiZLLnNUnjP/gg==",
1222
+ "version": "5.6.0",
1223
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.6.0.tgz",
1224
+ "integrity": "sha512-eZJSS8+RbWzX/7oDJPi+lYzfeuWwHXSsw336Yff35pTkmLEwRWKde2PQMW2objjMi1C1hNn9QiHjGktEJPSSWQ==",
1225
1225
  "dev": true,
1226
1226
  "license": "MIT"
1227
1227
  },
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "devDependencies": {
12
12
  "@nomicfoundation/hardhat-toolbox": "^6.1.0",
13
- "@openzeppelin/contracts": "^5.5.0",
13
+ "@openzeppelin/contracts": "^5.6.0",
14
14
  "hardhat": "^2.22.0"
15
15
  }
16
16
  }
@@ -10,8 +10,8 @@
10
10
  "license": "ISC",
11
11
  "devDependencies": {
12
12
  "@nomicfoundation/hardhat-toolbox": "^6.1.0",
13
- "@openzeppelin/contracts": "^5.5.0",
14
- "@openzeppelin/contracts-upgradeable": "^5.5.0",
13
+ "@openzeppelin/contracts": "^5.6.0",
14
+ "@openzeppelin/contracts-upgradeable": "^5.6.0",
15
15
  "@openzeppelin/hardhat-upgrades": "^3.0.0",
16
16
  "hardhat": "^2.22.0"
17
17
  }
@@ -1924,20 +1924,20 @@
1924
1924
  }
1925
1925
  },
1926
1926
  "node_modules/@openzeppelin/contracts": {
1927
- "version": "5.5.0",
1928
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.5.0.tgz",
1929
- "integrity": "sha512-R8hq4zmKKWP2c7OxeRgAcjZwvF5W0Qq2OIX7degrtdM52Q9xYr4MLJdUAVPKGUewNJ1qo+M6YiZLLnNUnjP/gg==",
1927
+ "version": "5.6.0",
1928
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.6.0.tgz",
1929
+ "integrity": "sha512-eZJSS8+RbWzX/7oDJPi+lYzfeuWwHXSsw336Yff35pTkmLEwRWKde2PQMW2objjMi1C1hNn9QiHjGktEJPSSWQ==",
1930
1930
  "dev": true,
1931
1931
  "license": "MIT"
1932
1932
  },
1933
1933
  "node_modules/@openzeppelin/contracts-upgradeable": {
1934
- "version": "5.5.0",
1935
- "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.5.0.tgz",
1936
- "integrity": "sha512-Va5hKG5oaK0EE5bXTVWugcGimMHazxL+SL523dH6WVbGiuLXwuWr9oxtLyPHQSVGtgmlIgtKNR5V+OUpCIUwFQ==",
1934
+ "version": "5.6.0",
1935
+ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.6.0.tgz",
1936
+ "integrity": "sha512-pJ4Qb4EGjemdvP/pbBZ+etXDB5PQJJf1tbIBDQqfQZMK3Lk8UuNCK+cWDluHZ28UfwH2WAwJLftyhJid4w63QA==",
1937
1937
  "dev": true,
1938
1938
  "license": "MIT",
1939
1939
  "peerDependencies": {
1940
- "@openzeppelin/contracts": "5.5.0"
1940
+ "@openzeppelin/contracts": "5.6.0"
1941
1941
  }
1942
1942
  },
1943
1943
  "node_modules/@openzeppelin/defender-sdk-base-client": {
@@ -10,8 +10,8 @@
10
10
  "license": "ISC",
11
11
  "devDependencies": {
12
12
  "@nomicfoundation/hardhat-toolbox": "^6.1.0",
13
- "@openzeppelin/contracts": "^5.5.0",
14
- "@openzeppelin/contracts-upgradeable": "^5.5.0",
13
+ "@openzeppelin/contracts": "^5.6.0",
14
+ "@openzeppelin/contracts-upgradeable": "^5.6.0",
15
15
  "@openzeppelin/hardhat-upgrades": "^3.0.0",
16
16
  "hardhat": "^2.22.0"
17
17
  }
package/src/erc20.ts CHANGED
@@ -16,7 +16,7 @@ import { OptionsError } from './error';
16
16
  import { toUint256, UINT256_MAX } from './utils/convert-strings';
17
17
  import { setNamespacedStorage, toStorageStructInstantiation } from './set-namespaced-storage';
18
18
 
19
- export const crossChainBridgingOptions = [false, 'custom', 'superchain'] as const;
19
+ export const crossChainBridgingOptions = [false, 'custom', 'erc7786native', 'superchain'] as const;
20
20
  export type CrossChainBridging = (typeof crossChainBridgingOptions)[number];
21
21
 
22
22
  export interface ERC20Options extends CommonOptions {
@@ -36,6 +36,7 @@ export interface ERC20Options extends CommonOptions {
36
36
  votes?: boolean | ClockMode;
37
37
  flashmint?: boolean;
38
38
  crossChainBridging?: CrossChainBridging;
39
+ crossChainLinkAllowOverride?: boolean;
39
40
  namespacePrefix?: string;
40
41
  }
41
42
 
@@ -53,6 +54,7 @@ export const defaults: Required<ERC20Options> = {
53
54
  votes: false,
54
55
  flashmint: false,
55
56
  crossChainBridging: false,
57
+ crossChainLinkAllowOverride: false,
56
58
  namespacePrefix: 'myProject',
57
59
  } as const;
58
60
 
@@ -70,6 +72,7 @@ export function withDefaults(opts: ERC20Options): Required<ERC20Options> {
70
72
  votes: opts.votes ?? defaults.votes,
71
73
  flashmint: opts.flashmint ?? defaults.flashmint,
72
74
  crossChainBridging: opts.crossChainBridging ?? defaults.crossChainBridging,
75
+ crossChainLinkAllowOverride: opts.crossChainLinkAllowOverride ?? defaults.crossChainLinkAllowOverride,
73
76
  namespacePrefix: opts.namespacePrefix ?? defaults.namespacePrefix,
74
77
  };
75
78
  }
@@ -79,7 +82,13 @@ export function printERC20(opts: ERC20Options = defaults): string {
79
82
  }
80
83
 
81
84
  export function isAccessControlRequired(opts: Partial<ERC20Options>): boolean {
82
- return opts.mintable || opts.pausable || opts.upgradeable === 'uups';
85
+ return (
86
+ opts.mintable ||
87
+ opts.pausable ||
88
+ opts.upgradeable === 'uups' ||
89
+ opts.crossChainBridging === 'custom' ||
90
+ opts.crossChainBridging === 'erc7786native'
91
+ );
83
92
  }
84
93
 
85
94
  export function buildERC20(opts: ERC20Options): ContractBuilder {
@@ -92,7 +101,14 @@ export function buildERC20(opts: ERC20Options): ContractBuilder {
92
101
  addBase(c, allOpts.name, allOpts.symbol);
93
102
 
94
103
  if (allOpts.crossChainBridging) {
95
- addCrossChainBridging(c, allOpts.crossChainBridging, access, upgradeable, allOpts.namespacePrefix);
104
+ addCrossChainBridging(
105
+ c,
106
+ allOpts.crossChainBridging,
107
+ allOpts.crossChainLinkAllowOverride,
108
+ access,
109
+ upgradeable,
110
+ allOpts.namespacePrefix,
111
+ );
96
112
  }
97
113
 
98
114
  if (allOpts.premint) {
@@ -115,14 +131,13 @@ export function buildERC20(opts: ERC20Options): ContractBuilder {
115
131
  addCallback(c);
116
132
  }
117
133
 
118
- // Note: Votes requires Permit
119
- if (allOpts.permit || allOpts.votes) {
134
+ if (allOpts.permit) {
120
135
  addPermit(c, allOpts.name);
121
136
  }
122
137
 
123
138
  if (allOpts.votes) {
124
139
  const clockMode = allOpts.votes === true ? clockModeDefault : allOpts.votes;
125
- addVotes(c, clockMode);
140
+ addVotes(c, allOpts.name, clockMode);
126
141
  }
127
142
 
128
143
  if (allOpts.flashmint) {
@@ -173,7 +188,7 @@ export function isValidChainId(str: string): boolean {
173
188
  return chainIdPattern.test(str);
174
189
  }
175
190
 
176
- function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
191
+ export function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
177
192
  if (exponent < 0) {
178
193
  return base / BigInt(10) ** BigInt(-exponent);
179
194
  } else {
@@ -181,55 +196,74 @@ function scaleByPowerOfTen(base: bigint, exponent: number): bigint {
181
196
  }
182
197
  }
183
198
 
199
+ export interface PremintCalculation {
200
+ units: string;
201
+ exp: string;
202
+ decimalPlace: number;
203
+ }
204
+
205
+ export function calculatePremint(amount: string): PremintCalculation | undefined {
206
+ const m = amount.match(premintPattern);
207
+ if (!m) {
208
+ throw new OptionsError({
209
+ premint: 'Not a valid number',
210
+ });
211
+ }
212
+
213
+ const integer = m[1]?.replace(/^0+/, '') ?? '';
214
+ const decimals = m[2]?.replace(/0+$/, '') ?? '';
215
+ const exponent = Number(m[3] ?? 0);
216
+
217
+ if (Number(integer + decimals) > 0) {
218
+ const decimalPlace = decimals.length - exponent;
219
+ const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join('');
220
+ const units = integer + decimals + zeroes;
221
+ const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`;
222
+
223
+ return { units, exp, decimalPlace };
224
+ } else {
225
+ return undefined;
226
+ }
227
+ }
228
+
184
229
  function addPremint(
185
230
  c: ContractBuilder,
186
231
  amount: string,
187
232
  premintChainId: string,
188
233
  crossChainBridging: CrossChainBridging,
189
234
  ) {
190
- const m = amount.match(premintPattern);
191
- if (m) {
192
- const integer = m[1]?.replace(/^0+/, '') ?? '';
193
- const decimals = m[2]?.replace(/0+$/, '') ?? '';
194
- const exponent = Number(m[3] ?? 0);
195
-
196
- if (Number(integer + decimals) > 0) {
197
- const decimalPlace = decimals.length - exponent;
198
- const zeroes = new Array(Math.max(0, -decimalPlace)).fill('0').join('');
199
- const units = integer + decimals + zeroes;
200
- const exp = decimalPlace <= 0 ? 'decimals()' : `(decimals() - ${decimalPlace})`;
235
+ const premintCalculation = calculatePremint(amount);
236
+ if (premintCalculation === undefined) {
237
+ return;
238
+ }
201
239
 
202
- const validatedBaseUnits = toUint256(units, 'premint');
203
- checkPotentialPremintOverflow(validatedBaseUnits, decimalPlace);
240
+ const { units, exp, decimalPlace } = premintCalculation;
204
241
 
205
- c.addConstructorArgument({ type: 'address', name: 'recipient' });
242
+ const validatedBaseUnits = toUint256(units, 'premint');
243
+ checkPotentialPremintOverflow(validatedBaseUnits, decimalPlace);
206
244
 
207
- const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
245
+ c.addConstructorArgument({ type: 'address', name: 'recipient' });
208
246
 
209
- if (crossChainBridging) {
210
- if (premintChainId === '') {
211
- throw new OptionsError({
212
- premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging',
213
- });
214
- }
247
+ const mintLine = `_mint(recipient, ${units} * 10 ** ${exp});`;
215
248
 
216
- if (!isValidChainId(premintChainId)) {
217
- throw new OptionsError({
218
- premintChainId: 'Not a valid chain ID',
219
- });
220
- }
249
+ if (crossChainBridging) {
250
+ if (premintChainId === '') {
251
+ throw new OptionsError({
252
+ premintChainId: 'Chain ID is required when using Premint with Cross-Chain Bridging',
253
+ });
254
+ }
221
255
 
222
- c.addConstructorCode(`if (block.chainid == ${premintChainId}) {`);
223
- c.addConstructorCode(` ${mintLine}`);
224
- c.addConstructorCode(`}`);
225
- } else {
226
- c.addConstructorCode(mintLine);
227
- }
256
+ if (!isValidChainId(premintChainId)) {
257
+ throw new OptionsError({
258
+ premintChainId: 'Not a valid chain ID',
259
+ });
228
260
  }
261
+
262
+ c.addConstructorCode(`if (block.chainid == ${premintChainId}) {`);
263
+ c.addConstructorCode(` ${mintLine}`);
264
+ c.addConstructorCode(`}`);
229
265
  } else {
230
- throw new OptionsError({
231
- premint: 'Not a valid number',
232
- });
266
+ c.addConstructorCode(mintLine);
233
267
  }
234
268
  }
235
269
 
@@ -274,9 +308,14 @@ function addPermit(c: ContractBuilder, name: string) {
274
308
  c.addOverride(ERC20Permit, functions.nonces);
275
309
  }
276
310
 
277
- function addVotes(c: ContractBuilder, clockMode: ClockMode) {
311
+ function addVotes(c: ContractBuilder, name: string, clockMode: ClockMode) {
278
312
  if (!c.parents.some(p => p.contract.name === 'ERC20Permit')) {
279
- throw new Error('Missing ERC20Permit requirement for ERC20Votes');
313
+ // ERC20Permit initializes the EIP712 domain separator. If ERC20Permit is not a parent, we need to do it here.
314
+ const EIP712 = {
315
+ name: 'EIP712',
316
+ path: '@openzeppelin/contracts/utils/cryptography/EIP712.sol',
317
+ };
318
+ c.addParent(EIP712, [name, '1']);
280
319
  }
281
320
 
282
321
  const ERC20Votes = {
@@ -308,6 +347,40 @@ function addFlashMint(c: ContractBuilder) {
308
347
  }
309
348
 
310
349
  function addCrossChainBridging(
350
+ c: ContractBuilder,
351
+ crossChainBridging: 'custom' | 'erc7786native' | 'superchain',
352
+ crossChainLinkAllowOverride: boolean,
353
+ access: Access,
354
+ upgradeable: Upgradeable,
355
+ namespacePrefix: string,
356
+ ) {
357
+ if (crossChainBridging === 'erc7786native') {
358
+ addERC20Crosschain(c, crossChainLinkAllowOverride, access);
359
+ } else {
360
+ addERC20Bridgeable(c, crossChainBridging, access, upgradeable, namespacePrefix);
361
+ }
362
+ }
363
+
364
+ function addERC20Crosschain(c: ContractBuilder, crossChainLinkAllowOverride: boolean, access: Access) {
365
+ c.addParent({
366
+ name: 'ERC20Crosschain',
367
+ path: '@openzeppelin/contracts/token/ERC20/extensions/ERC20Crosschain.sol',
368
+ });
369
+
370
+ c.addConstructionOnly(
371
+ {
372
+ name: 'CrosschainLinked',
373
+ path: '@openzeppelin/contracts/crosschain/CrosschainLinked.sol',
374
+ },
375
+ [{ lit: 'links' }],
376
+ );
377
+ c.addConstructorArgument({ type: 'CrosschainLinked.Link[] memory', name: 'links' });
378
+
379
+ requireAccessControl(c, functions.setLink, access, 'CROSSCHAIN_LINKER', 'crosschainLinker');
380
+ c.addFunctionCode(`_setLink(gateway, counterpart, ${crossChainLinkAllowOverride});`, functions.setLink);
381
+ }
382
+
383
+ function addERC20Bridgeable(
311
384
  c: ContractBuilder,
312
385
  crossChainBridging: 'custom' | 'superchain',
313
386
  access: Access,
@@ -339,31 +412,57 @@ function addCrossChainBridging(
339
412
  }
340
413
 
341
414
  function addCustomBridging(c: ContractBuilder, access: Access, upgradeable: Upgradeable, namespacePrefix: string) {
415
+ if (access === false) {
416
+ access = 'ownable';
417
+ }
418
+
342
419
  switch (access) {
343
- case false:
344
420
  case 'ownable': {
345
421
  if (!upgradeable) {
422
+ const LINES_CHECK_AND_SET_TOKEN_BRIDGE = [
423
+ `require(tokenBridge_ != address(0), "Invalid tokenBridge_ address");`,
424
+ `tokenBridge = tokenBridge_;`,
425
+ ];
426
+
427
+ // Add variable and constructor logic using state variable
346
428
  const addedBridge = c.addStateVariable(`address public tokenBridge;`, false);
347
429
  if (addedBridge) {
348
430
  c.addConstructorArgument({ type: 'address', name: 'tokenBridge_' });
349
- c.addConstructorCode(`require(tokenBridge_ != address(0), "Invalid tokenBridge_ address");`);
350
- c.addConstructorCode(`tokenBridge = tokenBridge_;`);
431
+ LINES_CHECK_AND_SET_TOKEN_BRIDGE.forEach(line => {
432
+ c.addConstructorCode(line);
433
+ });
351
434
  }
352
435
  c.setFunctionBody([`if (caller != tokenBridge) revert Unauthorized();`], functions._checkTokenBridge, 'view');
436
+
437
+ // Add bridge setter
438
+ requireAccessControl(c, functions.setTokenBridge, access, 'TOKEN_BRIDGE_SETTER', 'tokenBridgeSetter');
439
+ LINES_CHECK_AND_SET_TOKEN_BRIDGE.forEach(line => {
440
+ c.addFunctionCode(line, functions.setTokenBridge);
441
+ });
353
442
  } else {
443
+ const LINES_CHECK_AND_SET_TOKEN_BRIDGE = [
444
+ `require(tokenBridge_ != address(0), "Invalid tokenBridge_ address");`,
445
+ toStorageStructInstantiation(c.name),
446
+ '$.tokenBridge = tokenBridge_;',
447
+ ];
448
+
449
+ // Add variable and constructor logic using namespaced storage
354
450
  setNamespacedStorage(c, ['address tokenBridge;'], namespacePrefix);
355
451
 
356
452
  c.addConstructorArgument({ type: 'address', name: 'tokenBridge_' });
357
- c.addConstructorCode(`require(tokenBridge_ != address(0), "Invalid tokenBridge_ address");`);
358
-
359
- c.addConstructorCode(toStorageStructInstantiation(c.name));
360
- c.addConstructorCode(`$.tokenBridge = tokenBridge_;`);
453
+ LINES_CHECK_AND_SET_TOKEN_BRIDGE.forEach(line => {
454
+ c.addConstructorCode(line);
455
+ });
361
456
 
362
457
  c.setFunctionBody(
363
458
  [toStorageStructInstantiation(c.name), `if (caller != $.tokenBridge) revert Unauthorized();`],
364
459
  functions._checkTokenBridge,
365
460
  'view',
366
461
  );
462
+
463
+ // Add bridge setter
464
+ requireAccessControl(c, functions.setTokenBridge, access, 'TOKEN_BRIDGE_SETTER', 'tokenBridgeSetter');
465
+ c.setFunctionBody(LINES_CHECK_AND_SET_TOKEN_BRIDGE, functions.setTokenBridge);
367
466
  }
368
467
  break;
369
468
  }
@@ -483,4 +582,17 @@ export const functions = defineFunctions({
483
582
  kind: 'internal' as const,
484
583
  args: [{ name: 'caller', type: 'address' }],
485
584
  },
585
+
586
+ setTokenBridge: {
587
+ kind: 'public' as const,
588
+ args: [{ name: 'tokenBridge_', type: 'address' }],
589
+ },
590
+
591
+ setLink: {
592
+ kind: 'public' as const,
593
+ args: [
594
+ { name: 'gateway', type: 'address' },
595
+ { name: 'counterpart', type: 'bytes memory' },
596
+ ],
597
+ },
486
598
  });
@@ -7,27 +7,48 @@ import { generateAlternatives } from './alternatives';
7
7
 
8
8
  const booleans = [true, false];
9
9
 
10
- const blueprint = {
10
+ const blueprintWithoutBasicFeatures = {
11
11
  name: ['MyToken'],
12
12
  symbol: ['MTK'],
13
- burnable: booleans,
14
13
  pausable: booleans,
15
14
  mintable: booleans,
16
- callback: booleans,
17
- permit: booleans,
18
15
  votes: [...booleans, ...clockModeOptions] as const,
19
- flashmint: booleans,
20
16
  premint: ['1'],
21
17
  premintChainId: ['10'],
22
18
  crossChainBridging: crossChainBridgingOptions,
19
+ crossChainLinkAllowOverride: [false],
23
20
  access: accessOptions,
24
21
  upgradeable: upgradeableOptions,
25
22
  namespacePrefix: ['myProject'],
26
23
  info: infoOptions,
27
24
  };
28
25
 
26
+ // Basic features that do not depend on other features like access control
27
+ const basicFeatures = {
28
+ OFF: {
29
+ burnable: [false],
30
+ callback: [false],
31
+ permit: [false],
32
+ flashmint: [false],
33
+ },
34
+ ON: {
35
+ burnable: [true],
36
+ callback: [true],
37
+ permit: [true],
38
+ flashmint: [true],
39
+ },
40
+ };
41
+
29
42
  export function* generateERC20Options(): Generator<Required<ERC20Options>> {
30
- for (const opts of generateAlternatives(blueprint)) {
43
+ // Separate generation steps with basic features OFF and ON to avoid having too many combinations
44
+ for (const opts of generateAlternatives({ ...blueprintWithoutBasicFeatures, ...basicFeatures.OFF })) {
45
+ // crossChainBridging does not currently support upgradeable
46
+ if (!(opts.crossChainBridging && opts.upgradeable)) {
47
+ yield opts;
48
+ }
49
+ }
50
+
51
+ for (const opts of generateAlternatives({ ...blueprintWithoutBasicFeatures, ...basicFeatures.ON })) {
31
52
  // crossChainBridging does not currently support upgradeable
32
53
  if (!(opts.crossChainBridging && opts.upgradeable)) {
33
54
  yield opts;
@@ -19,6 +19,7 @@ const erc20Basic = {
19
19
  premint: ['1'],
20
20
  premintChainId: [''],
21
21
  crossChainBridging: [false] as const,
22
+ crossChainLinkAllowOverride: [false] as const,
22
23
  access: [false] as const,
23
24
  info: [{}] as const,
24
25
  namespacePrefix: ['myProject'],
@@ -37,6 +38,7 @@ const erc20Full = {
37
38
  premint: ['1'],
38
39
  premintChainId: ['10'],
39
40
  crossChainBridging: crossChainBridgingOptions,
41
+ crossChainLinkAllowOverride: [true] as const,
40
42
  access: accessOptions,
41
43
  info: infoOptions,
42
44
  namespacePrefix: ['myProject'],
package/src/index.ts CHANGED
@@ -1,21 +1,37 @@
1
+ // ===== Public API =====
2
+
3
+ export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
4
+ export type { WizardContractAPI, AccessControlAPI } from './api';
5
+
6
+ export type { ERC20Options } from './erc20';
7
+ export type { ERC721Options } from './erc721';
8
+ export type { ERC1155Options } from './erc1155';
9
+ export type { StablecoinOptions } from './stablecoin';
10
+ export type { AccountOptions } from './account';
11
+ export type { GovernorOptions } from './governor';
12
+ export type { CustomOptions } from './custom';
13
+
14
+ // ===== Internal API - Intended for use by other Wizard packages only =====
15
+
1
16
  export type { GenericOptions, KindedOptions } from './build-generic';
2
17
  export { buildGeneric } from './build-generic';
3
18
 
4
19
  export { generateAlternatives } from './generate/alternatives';
5
20
 
6
- export type { Contract, BaseFunction, Value, ReferencedContract } from './contract';
21
+ export type { Contract, BaseFunction, Value, ReferencedContract, FunctionArgument } from './contract';
7
22
  export { ContractBuilder } from './contract';
8
23
 
9
24
  export { printContract } from './print';
10
25
 
11
26
  export type { Access } from './set-access-control';
27
+ export { accessOptions, setAccessControl, requireAccessControl } from './set-access-control';
28
+ export { addPausable } from './add-pausable';
12
29
  export type { Upgradeable } from './set-upgradeable';
13
30
  export type { Info } from './set-info';
14
31
 
15
32
  export { premintPattern, chainIdPattern } from './erc20';
16
- export { defaults as infoDefaults, infoOptions, setInfo } from './set-info';
17
- export { accessOptions, setAccessControl, requireAccessControl } from './set-access-control';
18
- export { addPausable } from './add-pausable';
33
+ export { defaults as infoDefaults, setInfo, infoOptions } from './set-info';
34
+ export { supportsInterface } from './common-functions';
19
35
 
20
36
  export type { OptionsErrorMessages } from './error';
21
37
  export { OptionsError } from './error';
@@ -23,21 +39,17 @@ export { OptionsError } from './error';
23
39
  export type { Kind } from './kind';
24
40
  export { sanitizeKind } from './kind';
25
41
 
26
- export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
27
- export type { WizardContractAPI, AccessControlAPI } from './api';
28
-
29
42
  export { compatibleContractsSemver } from './utils/version';
30
- export { findCover } from './utils/find-cover';
31
- export { defineFunctions } from './utils/define-functions';
32
43
 
44
+ export { defineFunctions } from './utils/define-functions';
33
45
  export type { CommonOptions } from './common-options';
34
46
  export { withCommonDefaults, defaults as commonDefaults } from './common-options';
35
- export { supportsInterface } from './common-functions';
36
-
37
- export type { ERC20Options } from './erc20';
38
- export type { ERC721Options } from './erc721';
39
- export type { ERC1155Options } from './erc1155';
40
- export type { StablecoinOptions } from './stablecoin';
41
- export type { AccountOptions } from './account';
42
- export type { GovernorOptions } from './governor';
43
- export type { CustomOptions } from './custom';
47
+ export type { ClockMode } from './set-clock-mode';
48
+ export { clockModeDefault, setClockMode, clockModeOptions } from './set-clock-mode';
49
+ export { toBigInt } from './utils/convert-strings';
50
+ export type { Options } from './options';
51
+ export type { Lines } from './utils/format-lines';
52
+ export { formatLinesWithSpaces, spaceBetween } from './utils/format-lines';
53
+ export { findCover } from './utils/find-cover';
54
+ export type { PremintCalculation } from './erc20';
55
+ export { calculatePremint as calculateERC20Premint, scaleByPowerOfTen } from './erc20';
package/src/options.ts CHANGED
@@ -29,8 +29,10 @@ export interface Options {
29
29
  transformImport?: (parent: ImportContract) => ImportContract;
30
30
  /**
31
31
  * Add additional libraries to the compatibility banner printed at the top of the contract.
32
+ *
33
+ * If `alwaysKeepOzPrefix` is true, the library name will always keep the "OpenZeppelin " prefix, even if there are multiple libraries from OpenZeppelin being imported.
32
34
  */
33
- additionalCompatibleLibraries?: { name: string; path: string; version: string }[];
35
+ additionalCompatibleLibraries?: { name: string; path: string; version: string; alwaysKeepOzPrefix?: boolean }[];
34
36
  }
35
37
 
36
38
  export interface Helpers extends Required<Options> {