@openzeppelin/wizard 0.7.1 → 0.8.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.
- package/README.md +1 -1
- package/dist/account.d.ts.map +1 -1
- package/dist/account.js +48 -28
- package/dist/account.js.map +1 -1
- package/dist/environments/hardhat/package-lock.json +463 -521
- package/dist/environments/hardhat/upgradeable/package-lock.json +1282 -1055
- package/dist/generate/account.d.ts.map +1 -1
- package/dist/generate/account.js +2 -1
- package/dist/generate/account.js.map +1 -1
- package/dist/options.d.ts +3 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +8 -7
- package/dist/options.js.map +1 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +11 -11
- package/dist/print.js.map +1 -1
- package/dist/set-upgradeable.d.ts +1 -0
- package/dist/set-upgradeable.d.ts.map +1 -1
- package/dist/set-upgradeable.js +6 -0
- package/dist/set-upgradeable.js.map +1 -1
- package/dist/signer.d.ts +7 -2
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +45 -65
- package/dist/signer.js.map +1 -1
- package/dist/zip-foundry.d.ts.map +1 -1
- package/dist/zip-foundry.js +60 -65
- package/dist/zip-foundry.js.map +1 -1
- package/dist/zip-hardhat.d.ts.map +1 -1
- package/dist/zip-hardhat.js +8 -3
- package/dist/zip-hardhat.js.map +1 -1
- package/package.json +2 -2
- package/src/account.ts +55 -29
- package/src/environments/hardhat/package-lock.json +463 -521
- package/src/environments/hardhat/upgradeable/package-lock.json +1282 -1055
- package/src/generate/account.ts +2 -1
- package/src/options.ts +8 -8
- package/src/print.ts +31 -13
- package/src/set-upgradeable.ts +6 -0
- package/src/signer.ts +49 -70
- package/src/zip-foundry.ts +84 -64
- package/src/zip-hardhat.ts +9 -3
package/src/generate/account.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AccountOptions } from '../account';
|
|
2
2
|
import { infoOptions } from '../set-info';
|
|
3
|
+
import { upgradeableOptions } from '../set-upgradeable';
|
|
3
4
|
import { generateAlternatives } from './alternatives';
|
|
4
5
|
|
|
5
6
|
const account = {
|
|
@@ -11,7 +12,7 @@ const account = {
|
|
|
11
12
|
batchedExecution: [false, true] as const,
|
|
12
13
|
ERC7579Modules: [false, 'AccountERC7579', 'AccountERC7579Hooked'] as const,
|
|
13
14
|
access: [false] as const,
|
|
14
|
-
upgradeable:
|
|
15
|
+
upgradeable: upgradeableOptions,
|
|
15
16
|
info: infoOptions,
|
|
16
17
|
};
|
|
17
18
|
|
package/src/options.ts
CHANGED
|
@@ -3,15 +3,15 @@ import path from 'path';
|
|
|
3
3
|
import type { Contract, ReferencedContract, ImportContract } from './contract';
|
|
4
4
|
import { inferTranspiled } from './infer-transpiled';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export function upgradeableName(n: string) {
|
|
7
7
|
if (n === 'Initializable') {
|
|
8
8
|
return n;
|
|
9
9
|
} else {
|
|
10
10
|
return n.replace(/(Upgradeable)?(?=\.|$)/, 'Upgradeable');
|
|
11
11
|
}
|
|
12
|
-
}
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
export function upgradeableImport(p: ImportContract): ImportContract {
|
|
15
15
|
const { dir, ext, name } = path.parse(p.path);
|
|
16
16
|
// Use path.posix to get forward slashes
|
|
17
17
|
return {
|
|
@@ -23,7 +23,7 @@ const upgradeableImport = (p: ImportContract): ImportContract => {
|
|
|
23
23
|
name: upgradeableName(name), // Solidity file name
|
|
24
24
|
}),
|
|
25
25
|
};
|
|
26
|
-
}
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
export interface Options {
|
|
29
29
|
transformImport?: (parent: ImportContract) => ImportContract;
|
|
@@ -32,16 +32,16 @@ export interface Options {
|
|
|
32
32
|
export interface Helpers extends Required<Options> {
|
|
33
33
|
upgradeable: boolean;
|
|
34
34
|
transformName: (name: ReferencedContract) => string;
|
|
35
|
+
transformImport: (name: ImportContract) => ImportContract;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export function withHelpers(contract: Contract, opts: Options = {}): Helpers {
|
|
38
39
|
const contractUpgradeable = contract.upgradeable;
|
|
39
|
-
const transformName = (n: ReferencedContract) =>
|
|
40
|
-
contractUpgradeable && inferTranspiled(n) ? upgradeableName(n.name) : n.name;
|
|
41
40
|
return {
|
|
42
41
|
upgradeable: contractUpgradeable,
|
|
43
|
-
transformName
|
|
44
|
-
|
|
42
|
+
transformName: (n: ReferencedContract) =>
|
|
43
|
+
contractUpgradeable && inferTranspiled(n) ? upgradeableName(n.name) : n.name,
|
|
44
|
+
transformImport: (p1: ImportContract) => {
|
|
45
45
|
const p2 = contractUpgradeable && inferTranspiled(p1) ? upgradeableImport(p1) : p1;
|
|
46
46
|
return opts.transformImport?.(p2) ?? p2;
|
|
47
47
|
},
|
package/src/print.ts
CHANGED
|
@@ -82,21 +82,39 @@ function printConstructor(contract: Contract, helpers: Helpers): Lines[] {
|
|
|
82
82
|
const hasConstructorCode = contract.constructorCode.length > 0;
|
|
83
83
|
const parentsWithInitializers = contract.parents.filter(hasInitializer);
|
|
84
84
|
if (hasParentParams || hasConstructorCode || (helpers.upgradeable && parentsWithInitializers.length > 0)) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
if (helpers.upgradeable) {
|
|
86
|
+
const upgradeableParents = parentsWithInitializers.filter(p => inferTranspiled(p.contract));
|
|
87
|
+
const nonUpgradeableParents = contract.parents.filter(p => !inferTranspiled(p.contract));
|
|
88
|
+
const constructor = printFunction2(
|
|
89
|
+
[
|
|
90
|
+
nonUpgradeableParents.length > 0
|
|
91
|
+
? '/// @custom:oz-upgrades-unsafe-allow-reachable constructor'
|
|
92
|
+
: '/// @custom:oz-upgrades-unsafe-allow constructor',
|
|
93
|
+
],
|
|
94
|
+
'constructor',
|
|
95
|
+
[],
|
|
96
|
+
nonUpgradeableParents.flatMap(p => printParentConstructor(p, helpers)),
|
|
97
|
+
['_disableInitializers();'],
|
|
98
|
+
);
|
|
99
|
+
const initializer = printFunction2(
|
|
100
|
+
[],
|
|
101
|
+
'function initialize',
|
|
102
|
+
contract.constructorArgs.map(a => printArgument(a, helpers)),
|
|
103
|
+
['public', 'initializer'],
|
|
104
|
+
spaceBetween(
|
|
105
|
+
upgradeableParents.flatMap(p => printParentConstructor(p, helpers)).map(p => p + ';'),
|
|
91
106
|
contract.constructorCode,
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const constructor = printFunction2([], head, args, modifiers, body);
|
|
96
|
-
if (!helpers.upgradeable) {
|
|
97
|
-
return constructor;
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
return spaceBetween(constructor, upgradeableParents.length > 0 ? initializer : []);
|
|
98
110
|
} else {
|
|
99
|
-
return
|
|
111
|
+
return printFunction2(
|
|
112
|
+
[],
|
|
113
|
+
'constructor',
|
|
114
|
+
contract.constructorArgs.map(a => printArgument(a, helpers)),
|
|
115
|
+
contract.parents.flatMap(p => printParentConstructor(p, helpers)),
|
|
116
|
+
contract.constructorCode,
|
|
117
|
+
);
|
|
100
118
|
}
|
|
101
119
|
} else if (!helpers.upgradeable) {
|
|
102
120
|
return [];
|
package/src/set-upgradeable.ts
CHANGED
|
@@ -58,6 +58,12 @@ export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradea
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export function setUpgradeableAccount(c: ContractBuilder, upgradeable: Upgradeable) {
|
|
62
|
+
setUpgradeableBase(c, upgradeable, () => {
|
|
63
|
+
c.addModifier('onlyEntryPointOrSelf', functions._authorizeUpgrade);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
const functions = defineFunctions({
|
|
62
68
|
_authorizeUpgrade: {
|
|
63
69
|
args: [{ name: 'newImplementation', type: 'address' }],
|
package/src/signer.ts
CHANGED
|
@@ -1,112 +1,91 @@
|
|
|
1
1
|
import type { ContractBuilder } from './contract';
|
|
2
|
+
import { OptionsError } from './error';
|
|
3
|
+
import type { Upgradeable } from './set-upgradeable';
|
|
2
4
|
import { defineFunctions } from './utils/define-functions';
|
|
3
5
|
|
|
4
6
|
export const SignerOptions = [false, 'ERC7702', 'ECDSA', 'P256', 'RSA', 'Multisig', 'MultisigWeighted'] as const;
|
|
5
7
|
export type SignerOptions = (typeof SignerOptions)[number];
|
|
6
8
|
|
|
7
|
-
export function addSigner(c: ContractBuilder, signer: SignerOptions): void {
|
|
9
|
+
export function addSigner(c: ContractBuilder, signer: SignerOptions, upgradeable: Upgradeable): void {
|
|
8
10
|
if (!signer) return;
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
c.addOverride(
|
|
12
|
-
{ name: signer === 'MultisigWeighted' ? signers.Multisig.name : signers[signer].name },
|
|
13
|
-
signerFunctions._rawSignatureValidation,
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// ERC-7702 doesn't require initialization
|
|
17
|
-
if (signer === 'ERC7702') return;
|
|
18
|
-
|
|
19
|
-
c.addParent({
|
|
20
|
-
name: 'Initializable',
|
|
21
|
-
path: '@openzeppelin/contracts/proxy/utils/Initializable.sol',
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Add locking constructor
|
|
25
|
-
c.addNatspecTag('@custom:oz-upgrades-unsafe-allow', 'constructor');
|
|
26
|
-
c.addConstructorCode(`_disableInitializers();`);
|
|
27
|
-
|
|
28
|
-
// Add initializer
|
|
29
|
-
const fn = signerFunctions[`initialize${signer}`];
|
|
30
|
-
c.addModifier('initializer', fn);
|
|
12
|
+
const signerName = signer === 'MultisigWeighted' ? signers.Multisig.name : signers[signer].name;
|
|
13
|
+
c.addOverride({ name: signerName }, signerFunctions._rawSignatureValidation);
|
|
31
14
|
|
|
32
15
|
switch (signer) {
|
|
33
|
-
case '
|
|
34
|
-
c.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
16
|
+
case 'ERC7702':
|
|
17
|
+
c.addParent(signers[signer]);
|
|
18
|
+
if (upgradeable) {
|
|
19
|
+
throw new OptionsError({
|
|
20
|
+
erc7702: 'EOAs can upgrade by redelegating to a new account',
|
|
21
|
+
upgradeable: 'EOAs can upgrade by redelegating to a new account',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
41
24
|
break;
|
|
42
25
|
case 'ECDSA':
|
|
43
26
|
case 'P256':
|
|
44
27
|
case 'RSA':
|
|
45
|
-
|
|
28
|
+
case 'Multisig':
|
|
29
|
+
case 'MultisigWeighted': {
|
|
30
|
+
signerArgs[signer].forEach(arg => c.addConstructorArgument(arg));
|
|
31
|
+
c.addParent(
|
|
32
|
+
signers[signer],
|
|
33
|
+
signerArgs[signer].map(arg => ({ lit: arg.name })),
|
|
34
|
+
);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
46
37
|
}
|
|
47
38
|
}
|
|
48
39
|
|
|
49
40
|
export const signers = {
|
|
50
41
|
ERC7702: {
|
|
51
42
|
name: 'SignerERC7702',
|
|
52
|
-
path: '@openzeppelin/
|
|
43
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/SignerERC7702.sol',
|
|
53
44
|
},
|
|
54
45
|
ECDSA: {
|
|
55
46
|
name: 'SignerECDSA',
|
|
56
|
-
path: '@openzeppelin/
|
|
47
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/SignerECDSA.sol',
|
|
57
48
|
},
|
|
58
49
|
P256: {
|
|
59
50
|
name: 'SignerP256',
|
|
60
|
-
path: '@openzeppelin/
|
|
51
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/SignerP256.sol',
|
|
61
52
|
},
|
|
62
53
|
RSA: {
|
|
63
54
|
name: 'SignerRSA',
|
|
64
|
-
path: '@openzeppelin/
|
|
55
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/SignerRSA.sol',
|
|
65
56
|
},
|
|
66
57
|
Multisig: {
|
|
67
58
|
name: 'MultiSignerERC7913',
|
|
68
|
-
path: '@openzeppelin/
|
|
59
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/MultiSignerERC7913.sol',
|
|
69
60
|
},
|
|
70
61
|
MultisigWeighted: {
|
|
71
62
|
name: 'MultiSignerERC7913Weighted',
|
|
72
|
-
path: '@openzeppelin/
|
|
63
|
+
path: '@openzeppelin/contracts/utils/cryptography/signers/MultiSignerERC7913Weighted.sol',
|
|
73
64
|
},
|
|
74
65
|
};
|
|
75
66
|
|
|
67
|
+
export const signerArgs: Record<Exclude<SignerOptions, false | 'ERC7702'>, { name: string; type: string }[]> = {
|
|
68
|
+
ECDSA: [{ name: 'signer', type: 'address' }],
|
|
69
|
+
P256: [
|
|
70
|
+
{ name: 'qx', type: 'bytes32' },
|
|
71
|
+
{ name: 'qy', type: 'bytes32' },
|
|
72
|
+
],
|
|
73
|
+
RSA: [
|
|
74
|
+
{ name: 'e', type: 'bytes memory' },
|
|
75
|
+
{ name: 'n', type: 'bytes memory' },
|
|
76
|
+
],
|
|
77
|
+
Multisig: [
|
|
78
|
+
{ name: 'signers', type: 'bytes[] memory' },
|
|
79
|
+
{ name: 'threshold', type: 'uint64' },
|
|
80
|
+
],
|
|
81
|
+
MultisigWeighted: [
|
|
82
|
+
{ name: 'signers', type: 'bytes[] memory' },
|
|
83
|
+
{ name: 'weights', type: 'uint64[] memory' },
|
|
84
|
+
{ name: 'threshold', type: 'uint64' },
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
|
|
76
88
|
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
89
|
_rawSignatureValidation: {
|
|
111
90
|
kind: 'internal' as const,
|
|
112
91
|
args: [
|
package/src/zip-foundry.ts
CHANGED
|
@@ -6,22 +6,82 @@ import SOLIDITY_VERSION from './solidity-version.json';
|
|
|
6
6
|
import contracts from '../openzeppelin-contracts';
|
|
7
7
|
import type { Lines } from './utils/format-lines';
|
|
8
8
|
import { formatLinesWithSpaces, spaceBetween } from './utils/format-lines';
|
|
9
|
+
import type { Upgradeable } from './set-upgradeable';
|
|
9
10
|
|
|
10
11
|
function getHeader(c: Contract) {
|
|
11
12
|
return [`// SPDX-License-Identifier: ${c.license}`, `pragma solidity ^${SOLIDITY_VERSION};`];
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
function shouldUseUnsafeAllowConstructor(c: Contract): boolean {
|
|
16
|
+
// TODO: remove that selector when the upgrades plugin supports @custom:oz-upgrades-unsafe-allow-reachable
|
|
17
|
+
return c.parents.find(p => ['EIP712'].includes(p.contract.name)) !== undefined;
|
|
18
|
+
}
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
function getImports(c: Contract, prepopulateImports: string[]): string[] {
|
|
21
|
+
const result: string[] = [...prepopulateImports];
|
|
22
|
+
if (c.upgradeable) {
|
|
23
|
+
const unsafeAllowConstructor = shouldUseUnsafeAllowConstructor(c);
|
|
24
|
+
|
|
25
|
+
result.push(
|
|
26
|
+
unsafeAllowConstructor
|
|
27
|
+
? 'import {Upgrades, Options} from "openzeppelin-foundry-upgrades/Upgrades.sol";'
|
|
28
|
+
: 'import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";',
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
result.push(`import {${c.name}} from "src/${c.name}.sol";`);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getDeploymentCode(
|
|
36
|
+
c: Contract,
|
|
37
|
+
args: string[],
|
|
38
|
+
declareContractVariable: boolean,
|
|
39
|
+
upgradeable?: Upgradeable,
|
|
40
|
+
): Lines[] {
|
|
41
|
+
const unsafeAllowConstructor = shouldUseUnsafeAllowConstructor(c);
|
|
42
|
+
const instanceDeclaration = declareContractVariable ? `${c.name} ` : '';
|
|
43
|
+
|
|
44
|
+
switch (upgradeable) {
|
|
45
|
+
case 'transparent':
|
|
46
|
+
return printDeployProxyAndAssignInstance('deployTransparentProxy', true);
|
|
47
|
+
case 'uups':
|
|
48
|
+
return printDeployProxyAndAssignInstance('deployUUPSProxy', false);
|
|
49
|
+
default:
|
|
50
|
+
return [`${instanceDeclaration}instance = new ${c.name}(${args.join(', ')});`];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function printDeployProxyAndAssignInstance(deployProxyFunctionName: string, includeInitialOwner: boolean) {
|
|
54
|
+
const deployProxyArgs = [`"${c.name}.sol"`];
|
|
55
|
+
if (includeInitialOwner) {
|
|
56
|
+
deployProxyArgs.push('initialOwner');
|
|
57
|
+
}
|
|
58
|
+
deployProxyArgs.push(`abi.encodeCall(${c.name}.initialize, (${args.join(', ')}))`);
|
|
59
|
+
if (unsafeAllowConstructor) {
|
|
60
|
+
deployProxyArgs.push('opts');
|
|
61
|
+
}
|
|
62
|
+
for (let i = 0; i < deployProxyArgs.length - 1; i++) {
|
|
63
|
+
deployProxyArgs[i] += ',';
|
|
21
64
|
}
|
|
22
|
-
|
|
23
|
-
return
|
|
65
|
+
|
|
66
|
+
return [
|
|
67
|
+
unsafeAllowConstructor && 'Options memory opts;',
|
|
68
|
+
unsafeAllowConstructor && 'opts.unsafeAllow = "constructor";',
|
|
69
|
+
`address proxy = Upgrades.${deployProxyFunctionName}(`,
|
|
70
|
+
deployProxyArgs,
|
|
71
|
+
');',
|
|
72
|
+
// Account has a receive function, this requires a payable address
|
|
73
|
+
c.parents.find(p => ['Account'].includes(p.contract.name))
|
|
74
|
+
? `${instanceDeclaration}instance = ${c.name}(payable(proxy));`
|
|
75
|
+
: `${instanceDeclaration}instance = ${c.name}(proxy);`,
|
|
76
|
+
].filter(line => line !== false);
|
|
24
77
|
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const test = (c: Contract, opts?: GenericOptions) => {
|
|
81
|
+
return formatLinesWithSpaces(
|
|
82
|
+
2,
|
|
83
|
+
...spaceBetween(getHeader(c), getImports(c, ['import {Test} from "forge-std/Test.sol";']), getTestCase(c)),
|
|
84
|
+
);
|
|
25
85
|
|
|
26
86
|
function getTestCase(c: Contract) {
|
|
27
87
|
const args = getAddressArgs(c);
|
|
@@ -29,35 +89,18 @@ const test = (c: Contract, opts?: GenericOptions) => {
|
|
|
29
89
|
`contract ${c.name}Test is Test {`,
|
|
30
90
|
spaceBetween(
|
|
31
91
|
[`${c.name} public instance;`],
|
|
32
|
-
[
|
|
92
|
+
[
|
|
93
|
+
'function setUp() public {',
|
|
94
|
+
getAddressVariables(c, args),
|
|
95
|
+
getDeploymentCode(c, args, false, opts?.upgradeable),
|
|
96
|
+
'}',
|
|
97
|
+
],
|
|
33
98
|
getContractSpecificTestFunction(),
|
|
34
99
|
),
|
|
35
100
|
'}',
|
|
36
101
|
];
|
|
37
102
|
}
|
|
38
103
|
|
|
39
|
-
function getDeploymentCode(c: Contract, args: string[]): Lines[] {
|
|
40
|
-
if (c.upgradeable) {
|
|
41
|
-
if (opts?.upgradeable === 'transparent') {
|
|
42
|
-
return [
|
|
43
|
-
`address proxy = Upgrades.deployTransparentProxy(`,
|
|
44
|
-
[`"${c.name}.sol",`, `initialOwner,`, `abi.encodeCall(${c.name}.initialize, (${args.join(', ')}))`],
|
|
45
|
-
');',
|
|
46
|
-
`instance = ${c.name}(proxy);`,
|
|
47
|
-
];
|
|
48
|
-
} else {
|
|
49
|
-
return [
|
|
50
|
-
`address proxy = Upgrades.deployUUPSProxy(`,
|
|
51
|
-
[`"${c.name}.sol",`, `abi.encodeCall(${c.name}.initialize, (${args.join(', ')}))`],
|
|
52
|
-
');',
|
|
53
|
-
`instance = ${c.name}(proxy);`,
|
|
54
|
-
];
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
return [`instance = new ${c.name}(${args.join(', ')});`];
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
104
|
function getAddressVariables(c: Contract, args: string[]): Lines[] {
|
|
62
105
|
const vars = [];
|
|
63
106
|
let i = 1; // private key index starts from 1 since it must be non-zero
|
|
@@ -80,6 +123,7 @@ const test = (c: Contract, opts?: GenericOptions) => {
|
|
|
80
123
|
case 'ERC1155':
|
|
81
124
|
return ['function testUri() public view {', [`assertEq(instance.uri(0), "${opts.uri}");`], '}'];
|
|
82
125
|
|
|
126
|
+
case 'Account':
|
|
83
127
|
case 'Governor':
|
|
84
128
|
case 'Custom':
|
|
85
129
|
return ['function testSomething() public {', ['// Add your test here'], '}'];
|
|
@@ -103,23 +147,21 @@ function getAddressArgs(c: Contract): string[] {
|
|
|
103
147
|
}
|
|
104
148
|
|
|
105
149
|
const script = (c: Contract, opts?: GenericOptions) => {
|
|
106
|
-
return formatLinesWithSpaces(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return result;
|
|
115
|
-
}
|
|
150
|
+
return formatLinesWithSpaces(
|
|
151
|
+
2,
|
|
152
|
+
...spaceBetween(
|
|
153
|
+
getHeader(c),
|
|
154
|
+
getImports(c, ['import {Script} from "forge-std/Script.sol";', 'import {console} from "forge-std/console.sol";']),
|
|
155
|
+
getScript(c),
|
|
156
|
+
),
|
|
157
|
+
);
|
|
116
158
|
|
|
117
159
|
function getScript(c: Contract) {
|
|
118
160
|
const args = getAddressArgs(c);
|
|
119
161
|
const deploymentLines = [
|
|
120
162
|
'vm.startBroadcast();',
|
|
121
163
|
...getAddressVariables(c, args),
|
|
122
|
-
...getDeploymentCode(c, args),
|
|
164
|
+
...getDeploymentCode(c, args, true, opts?.upgradeable),
|
|
123
165
|
`console.log("${c.upgradeable ? 'Proxy' : 'Contract'} deployed to %s", address(instance));`,
|
|
124
166
|
'vm.stopBroadcast();',
|
|
125
167
|
];
|
|
@@ -133,28 +175,6 @@ const script = (c: Contract, opts?: GenericOptions) => {
|
|
|
133
175
|
];
|
|
134
176
|
}
|
|
135
177
|
|
|
136
|
-
function getDeploymentCode(c: Contract, args: string[]): Lines[] {
|
|
137
|
-
if (c.upgradeable) {
|
|
138
|
-
if (opts?.upgradeable === 'transparent') {
|
|
139
|
-
return [
|
|
140
|
-
`address proxy = Upgrades.deployTransparentProxy(`,
|
|
141
|
-
[`"${c.name}.sol",`, `initialOwner,`, `abi.encodeCall(${c.name}.initialize, (${args.join(', ')}))`],
|
|
142
|
-
');',
|
|
143
|
-
`${c.name} instance = ${c.name}(proxy);`,
|
|
144
|
-
];
|
|
145
|
-
} else {
|
|
146
|
-
return [
|
|
147
|
-
`address proxy = Upgrades.deployUUPSProxy(`,
|
|
148
|
-
[`"${c.name}.sol",`, `abi.encodeCall(${c.name}.initialize, (${args.join(', ')}))`],
|
|
149
|
-
');',
|
|
150
|
-
`${c.name} instance = ${c.name}(proxy);`,
|
|
151
|
-
];
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
return [`${c.name} instance = new ${c.name}(${args.join(', ')});`];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
178
|
function getAddressVariables(c: Contract, args: string[]): Lines[] {
|
|
159
179
|
const vars = [];
|
|
160
180
|
if (c.upgradeable && opts?.upgradeable === 'transparent' && !args.includes('initialOwner')) {
|
package/src/zip-hardhat.ts
CHANGED
|
@@ -87,6 +87,7 @@ const test = (c: Contract, opts?: GenericOptions) => {
|
|
|
87
87
|
case 'ERC1155':
|
|
88
88
|
return [`expect(await instance.uri(0)).to.equal("${opts.uri}");`];
|
|
89
89
|
|
|
90
|
+
case 'Account':
|
|
90
91
|
case 'Governor':
|
|
91
92
|
case 'Custom':
|
|
92
93
|
break;
|
|
@@ -118,9 +119,14 @@ function getAddressArgs(c: Contract): string[] {
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
function getDeploymentCall(c: Contract, args: string[]): string {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
// TODO: remove that selector when the upgrades plugin supports @custom:oz-upgrades-unsafe-allow-reachable
|
|
123
|
+
const unsafeAllowConstructor = c.parents.find(p => ['EIP712'].includes(p.contract.name)) !== undefined;
|
|
124
|
+
|
|
125
|
+
return !c.upgradeable
|
|
126
|
+
? `ContractFactory.deploy(${args.join(', ')})`
|
|
127
|
+
: unsafeAllowConstructor
|
|
128
|
+
? `upgrades.deployProxy(ContractFactory, [${args.join(', ')}], { unsafeAllow: 'constructor' })`
|
|
129
|
+
: `upgrades.deployProxy(ContractFactory, [${args.join(', ')}])`;
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
const script = (c: Contract) => {
|