@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.
- package/README.md +13 -3
- package/dist/account.d.ts +20 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +256 -0
- package/dist/account.js.map +1 -0
- package/dist/api.d.ts +12 -7
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -1
- package/dist/api.js.map +1 -1
- package/dist/build-generic.d.ts +4 -0
- package/dist/build-generic.d.ts.map +1 -1
- package/dist/build-generic.js +3 -0
- package/dist/build-generic.js.map +1 -1
- package/dist/environments/hardhat/package-lock.json +3 -3
- package/dist/environments/hardhat/upgradeable/package-lock.json +7 -7
- package/dist/erc20.js +1 -1
- package/dist/erc20.js.map +1 -1
- package/dist/generate/account.d.ts +3 -0
- package/dist/generate/account.d.ts.map +1 -0
- package/dist/generate/account.js +21 -0
- package/dist/generate/account.js.map +1 -0
- package/dist/generate/sources.d.ts.map +1 -1
- package/dist/generate/sources.js +6 -0
- package/dist/generate/sources.js.map +1 -1
- package/dist/governor.d.ts +1 -1
- package/dist/governor.d.ts.map +1 -1
- package/dist/governor.js +10 -10
- package/dist/governor.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/kind.js +2 -1
- package/dist/kind.js.map +1 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +2 -1
- 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 +13 -2
- package/dist/set-upgradeable.js.map +1 -1
- package/dist/signer.d.ts +39 -0
- package/dist/signer.d.ts.map +1 -0
- package/dist/signer.js +115 -0
- package/dist/signer.js.map +1 -0
- package/dist/solidity-version.json +1 -1
- package/dist/stablecoin.js +2 -2
- package/dist/stablecoin.js.map +1 -1
- package/dist/test.js +17 -6
- package/dist/test.js.map +1 -1
- package/dist/utils/sanitize.d.ts +2 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +9 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/zip-foundry.js +4 -4
- package/package.json +6 -7
- package/src/account.ts +296 -0
- package/src/api.ts +16 -7
- package/src/build-generic.ts +6 -0
- package/src/environments/hardhat/package-lock.json +3 -3
- package/src/environments/hardhat/upgradeable/package-lock.json +7 -7
- package/src/erc20.ts +1 -1
- package/src/generate/account.ts +20 -0
- package/src/generate/sources.ts +7 -0
- package/src/governor.ts +13 -12
- package/src/index.ts +1 -1
- package/src/kind.ts +2 -1
- package/src/print.ts +2 -1
- package/src/set-upgradeable.ts +18 -2
- package/src/signer.ts +124 -0
- package/src/solidity-version.json +1 -1
- package/src/stablecoin.ts +2 -2
- package/src/test.ts +17 -5
- package/src/utils/sanitize.ts +6 -0
- package/src/zip-foundry.ts +4 -4
package/src/governor.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { supportsInterface } from './common-functions';
|
|
2
2
|
import type { CommonOptions } from './common-options';
|
|
3
3
|
import { withCommonDefaults, defaults as commonDefaults } from './common-options';
|
|
4
|
-
import type { Contract } from './contract';
|
|
4
|
+
import type { Contract, ImportContract } from './contract';
|
|
5
5
|
import { ContractBuilder } from './contract';
|
|
6
6
|
import { OptionsError } from './error';
|
|
7
7
|
import { setAccessControl } from './set-access-control';
|
|
8
8
|
import { printContract } from './print';
|
|
9
9
|
import { setInfo } from './set-info';
|
|
10
|
-
import {
|
|
10
|
+
import { setUpgradeableGovernor } from './set-upgradeable';
|
|
11
11
|
import { defineFunctions } from './utils/define-functions';
|
|
12
12
|
import { durationToBlocks, durationToTimestamp } from './utils/duration';
|
|
13
13
|
import { clockModeDefault, type ClockMode } from './set-clock-mode';
|
|
@@ -61,8 +61,8 @@ export interface GovernorOptions extends CommonOptions {
|
|
|
61
61
|
settings?: boolean;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export function isAccessControlRequired(
|
|
65
|
-
return
|
|
64
|
+
export function isAccessControlRequired(_: Partial<GovernorOptions>): boolean {
|
|
65
|
+
return false;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function withDefaults(opts: GovernorOptions): Required<GovernorOptions> {
|
|
@@ -99,21 +99,19 @@ export function buildGovernor(opts: GovernorOptions): Contract {
|
|
|
99
99
|
addTimelock(c, allOpts);
|
|
100
100
|
|
|
101
101
|
setAccessControl(c, allOpts.access);
|
|
102
|
-
|
|
102
|
+
setUpgradeableGovernor(c, allOpts.upgradeable);
|
|
103
103
|
setInfo(c, allOpts.info);
|
|
104
104
|
|
|
105
105
|
return c;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
const Governor: ImportContract = {
|
|
109
|
+
name: 'Governor',
|
|
110
|
+
path: '@openzeppelin/contracts/governance/Governor.sol',
|
|
111
|
+
};
|
|
112
|
+
|
|
108
113
|
function addBase(c: ContractBuilder, { name }: GovernorOptions) {
|
|
109
|
-
const Governor = {
|
|
110
|
-
name: 'Governor',
|
|
111
|
-
path: '@openzeppelin/contracts/governance/Governor.sol',
|
|
112
|
-
};
|
|
113
114
|
c.addParent(Governor, [name]);
|
|
114
|
-
c.addOverride(Governor, functions.votingDelay);
|
|
115
|
-
c.addOverride(Governor, functions.votingPeriod);
|
|
116
|
-
c.addOverride(Governor, functions.quorum);
|
|
117
115
|
c.addOverride(Governor, functions.state);
|
|
118
116
|
c.addOverride(Governor, functions.propose);
|
|
119
117
|
c.addOverride(Governor, functions.proposalNeedsQueuing);
|
|
@@ -221,6 +219,7 @@ function setVotingParameters(c: ContractBuilder, opts: Required<GovernorOptions>
|
|
|
221
219
|
} else {
|
|
222
220
|
c.setFunctionBody([`return ${delayBlocks.value}; // ${delayBlocks.note}`], functions.votingDelay);
|
|
223
221
|
}
|
|
222
|
+
c.addOverride(Governor, functions.votingDelay);
|
|
224
223
|
|
|
225
224
|
const periodBlocks = getVotingPeriod(opts);
|
|
226
225
|
if ('lit' in periodBlocks) {
|
|
@@ -228,6 +227,7 @@ function setVotingParameters(c: ContractBuilder, opts: Required<GovernorOptions>
|
|
|
228
227
|
} else {
|
|
229
228
|
c.setFunctionBody([`return ${periodBlocks.value}; // ${periodBlocks.note}`], functions.votingPeriod);
|
|
230
229
|
}
|
|
230
|
+
c.addOverride(Governor, functions.votingPeriod);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
function setProposalThreshold(c: ContractBuilder, opts: Required<GovernorOptions>) {
|
|
@@ -308,6 +308,7 @@ function addQuorum(c: ContractBuilder, opts: Required<GovernorOptions>) {
|
|
|
308
308
|
: `return ${opts.quorumAbsolute}e${opts.decimals};`;
|
|
309
309
|
|
|
310
310
|
c.setFunctionBody([returnStatement], functions.quorum, 'pure');
|
|
311
|
+
c.addOverride(Governor, functions.quorum);
|
|
311
312
|
}
|
|
312
313
|
}
|
|
313
314
|
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,6 @@ export { OptionsError } from './error';
|
|
|
19
19
|
export type { Kind } from './kind';
|
|
20
20
|
export { sanitizeKind } from './kind';
|
|
21
21
|
|
|
22
|
-
export { erc20, erc721, erc1155, stablecoin, realWorldAsset, governor, custom } from './api';
|
|
22
|
+
export { erc20, erc721, erc1155, stablecoin, realWorldAsset, account, governor, custom } from './api';
|
|
23
23
|
|
|
24
24
|
export { compatibleContractsSemver } from './utils/version';
|
package/src/kind.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type Kind = GenericOptions['kind'];
|
|
|
4
4
|
|
|
5
5
|
export function sanitizeKind(kind: unknown): Kind {
|
|
6
6
|
if (typeof kind === 'string') {
|
|
7
|
-
const sanitized = kind.replace(/^(ERC|.)/i, c => c.toUpperCase());
|
|
7
|
+
const sanitized = kind.replace(/^(ERC|.)/i, c => c.toUpperCase()).replace(/^(RealWorldAsset)$/i, 'RealWorldAsset');
|
|
8
8
|
if (isKind(sanitized)) {
|
|
9
9
|
return sanitized;
|
|
10
10
|
}
|
|
@@ -19,6 +19,7 @@ function isKind<T>(value: Kind | T): value is Kind {
|
|
|
19
19
|
case 'ERC721':
|
|
20
20
|
case 'Stablecoin':
|
|
21
21
|
case 'RealWorldAsset':
|
|
22
|
+
case 'Account':
|
|
22
23
|
case 'Governor':
|
|
23
24
|
case 'Custom':
|
|
24
25
|
return true;
|
package/src/print.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { mapValues } from './utils/map-values';
|
|
|
16
16
|
import SOLIDITY_VERSION from './solidity-version.json';
|
|
17
17
|
import { inferTranspiled } from './infer-transpiled';
|
|
18
18
|
import { compatibleContractsSemver } from './utils/version';
|
|
19
|
+
import { stringifyUnicodeSafe } from './utils/sanitize';
|
|
19
20
|
|
|
20
21
|
export function printContract(contract: Contract, opts?: Options): string {
|
|
21
22
|
const helpers = withHelpers(contract, opts);
|
|
@@ -148,7 +149,7 @@ export function printValue(value: Value): string {
|
|
|
148
149
|
throw new Error(`Number not representable (${value})`);
|
|
149
150
|
}
|
|
150
151
|
} else {
|
|
151
|
-
return
|
|
152
|
+
return stringifyUnicodeSafe(value);
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
|
package/src/set-upgradeable.ts
CHANGED
|
@@ -7,7 +7,11 @@ export const upgradeableOptions = [false, 'transparent', 'uups'] as const;
|
|
|
7
7
|
|
|
8
8
|
export type Upgradeable = (typeof upgradeableOptions)[number];
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
function setUpgradeableBase(
|
|
11
|
+
c: ContractBuilder,
|
|
12
|
+
upgradeable: Upgradeable,
|
|
13
|
+
restrictAuthorizeUpgradeWhenUUPS: () => void,
|
|
14
|
+
) {
|
|
11
15
|
if (upgradeable === false) {
|
|
12
16
|
return;
|
|
13
17
|
}
|
|
@@ -24,7 +28,7 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc
|
|
|
24
28
|
break;
|
|
25
29
|
|
|
26
30
|
case 'uups': {
|
|
27
|
-
|
|
31
|
+
restrictAuthorizeUpgradeWhenUUPS();
|
|
28
32
|
const UUPSUpgradeable = {
|
|
29
33
|
name: 'UUPSUpgradeable',
|
|
30
34
|
path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol',
|
|
@@ -42,6 +46,18 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc
|
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, access: Access) {
|
|
50
|
+
setUpgradeableBase(c, upgradeable, () => {
|
|
51
|
+
requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER', 'upgrader');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function setUpgradeableGovernor(c: ContractBuilder, upgradeable: Upgradeable) {
|
|
56
|
+
setUpgradeableBase(c, upgradeable, () => {
|
|
57
|
+
c.addModifier('onlyGovernance', functions._authorizeUpgrade);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
45
61
|
const functions = defineFunctions({
|
|
46
62
|
_authorizeUpgrade: {
|
|
47
63
|
args: [{ name: 'newImplementation', type: 'address' }],
|
package/src/signer.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { ContractBuilder } from './contract';
|
|
2
|
+
import { defineFunctions } from './utils/define-functions';
|
|
3
|
+
|
|
4
|
+
export const SignerOptions = [false, 'ERC7702', 'ECDSA', 'P256', 'RSA', 'Multisig', 'MultisigWeighted'] as const;
|
|
5
|
+
export type SignerOptions = (typeof SignerOptions)[number];
|
|
6
|
+
|
|
7
|
+
export function addSigner(c: ContractBuilder, signer: SignerOptions): void {
|
|
8
|
+
if (!signer) return;
|
|
9
|
+
const parent = signers[signer];
|
|
10
|
+
const name = parent.name;
|
|
11
|
+
c.addParent(parent);
|
|
12
|
+
c.addOverride(
|
|
13
|
+
{ name: name === signers.MultisigWeighted.name ? signers.Multisig.name : name },
|
|
14
|
+
signerFunctions._rawSignatureValidation,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// ERC-7702 doesn't require initialization
|
|
18
|
+
if (signer === 'ERC7702') return;
|
|
19
|
+
|
|
20
|
+
c.addParent({
|
|
21
|
+
name: 'Initializable',
|
|
22
|
+
path: '@openzeppelin/contracts/proxy/utils/Initializable.sol',
|
|
23
|
+
});
|
|
24
|
+
const fn = signerFunctions[`initialize${signer}`];
|
|
25
|
+
c.addModifier('initializer', fn);
|
|
26
|
+
|
|
27
|
+
const args = fn.args;
|
|
28
|
+
|
|
29
|
+
switch (signer) {
|
|
30
|
+
case 'Multisig':
|
|
31
|
+
c.addFunctionCode(`_addSigners(${args[0]!.name});`, fn);
|
|
32
|
+
c.addFunctionCode(`_setThreshold(${args[1]!.name});`, fn);
|
|
33
|
+
break;
|
|
34
|
+
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
|
+
break;
|
|
39
|
+
case 'ECDSA':
|
|
40
|
+
case 'P256':
|
|
41
|
+
case 'RSA':
|
|
42
|
+
c.addFunctionCode(
|
|
43
|
+
`_setSigner(${fn.args
|
|
44
|
+
.map(({ name }) => name)
|
|
45
|
+
.join(', ')
|
|
46
|
+
.trimEnd()});`,
|
|
47
|
+
fn,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const signers = {
|
|
53
|
+
ERC7702: {
|
|
54
|
+
name: 'SignerERC7702',
|
|
55
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/SignerERC7702.sol',
|
|
56
|
+
},
|
|
57
|
+
ECDSA: {
|
|
58
|
+
name: 'SignerECDSA',
|
|
59
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/SignerECDSA.sol',
|
|
60
|
+
},
|
|
61
|
+
P256: {
|
|
62
|
+
name: 'SignerP256',
|
|
63
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/SignerP256.sol',
|
|
64
|
+
},
|
|
65
|
+
RSA: {
|
|
66
|
+
name: 'SignerRSA',
|
|
67
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/SignerRSA.sol',
|
|
68
|
+
},
|
|
69
|
+
Multisig: {
|
|
70
|
+
name: 'MultiSignerERC7913',
|
|
71
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/MultiSignerERC7913.sol',
|
|
72
|
+
},
|
|
73
|
+
MultisigWeighted: {
|
|
74
|
+
name: 'MultiSignerERC7913Weighted',
|
|
75
|
+
path: '@openzeppelin/community-contracts/utils/cryptography/MultiSignerERC7913Weighted.sol',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
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
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"0.8.
|
|
1
|
+
"0.8.27"
|
package/src/stablecoin.ts
CHANGED
|
@@ -65,7 +65,7 @@ function addLimitations(c: ContractBuilder, access: Access, mode: boolean | 'all
|
|
|
65
65
|
const type = mode === 'allowlist';
|
|
66
66
|
const ERC20Limitation = {
|
|
67
67
|
name: type ? 'ERC20Allowlist' : 'ERC20Blocklist',
|
|
68
|
-
path: `@openzeppelin/community-contracts/
|
|
68
|
+
path: `@openzeppelin/community-contracts/token/ERC20/extensions/${type ? 'ERC20Allowlist' : 'ERC20Blocklist'}.sol`,
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
c.addParent(ERC20Limitation);
|
|
@@ -86,7 +86,7 @@ function addLimitations(c: ContractBuilder, access: Access, mode: boolean | 'all
|
|
|
86
86
|
function addCustodian(c: ContractBuilder, access: Access) {
|
|
87
87
|
const ERC20Custodian = {
|
|
88
88
|
name: 'ERC20Custodian',
|
|
89
|
-
path: '@openzeppelin/community-contracts/
|
|
89
|
+
path: '@openzeppelin/community-contracts/token/ERC20/extensions/ERC20Custodian.sol',
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
c.addParent(ERC20Custodian);
|
package/src/test.ts
CHANGED
|
@@ -30,6 +30,10 @@ test.serial('stablecoin result compiles', async t => {
|
|
|
30
30
|
await testCompile(t, 'Stablecoin');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
+
test.serial('account result compiles', async t => {
|
|
34
|
+
await testCompile(t, 'Account');
|
|
35
|
+
});
|
|
36
|
+
|
|
33
37
|
test.serial('governor result compiles', async t => {
|
|
34
38
|
await testCompile(t, 'Governor');
|
|
35
39
|
});
|
|
@@ -66,6 +70,8 @@ function isAccessControlRequired(opts: GenericOptions) {
|
|
|
66
70
|
return stablecoin.isAccessControlRequired(opts);
|
|
67
71
|
case 'RealWorldAsset':
|
|
68
72
|
return stablecoin.isAccessControlRequired(opts);
|
|
73
|
+
case 'Account':
|
|
74
|
+
throw new Error(`Not applicable for ${opts.kind}`);
|
|
69
75
|
case 'Governor':
|
|
70
76
|
return governor.isAccessControlRequired(opts);
|
|
71
77
|
case 'Custom':
|
|
@@ -79,11 +85,17 @@ test('is access control required', async t => {
|
|
|
79
85
|
for (const contract of generateSources('all')) {
|
|
80
86
|
const regexOwnable = /import.*Ownable(Upgradeable)?.sol.*/gm;
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
switch (contract.options.kind) {
|
|
89
|
+
case 'Account':
|
|
90
|
+
break;
|
|
91
|
+
default: {
|
|
92
|
+
if (!contract.options.access) {
|
|
93
|
+
if (isAccessControlRequired(contract.options)) {
|
|
94
|
+
t.regex(contract.source, regexOwnable, JSON.stringify(contract.options));
|
|
95
|
+
} else {
|
|
96
|
+
t.notRegex(contract.source, regexOwnable, JSON.stringify(contract.options));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
87
99
|
}
|
|
88
100
|
}
|
|
89
101
|
}
|
package/src/zip-foundry.ts
CHANGED
|
@@ -202,18 +202,18 @@ then
|
|
|
202
202
|
mv README.md README-oz.md
|
|
203
203
|
|
|
204
204
|
# Initialize sample Foundry project
|
|
205
|
-
forge init --force --
|
|
205
|
+
forge init --force --quiet
|
|
206
206
|
|
|
207
207
|
${
|
|
208
208
|
c.upgradeable
|
|
209
209
|
? `\
|
|
210
210
|
# Install OpenZeppelin Contracts and Upgrades
|
|
211
|
-
forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v${contracts.version} --
|
|
212
|
-
forge install OpenZeppelin/openzeppelin-foundry-upgrades --
|
|
211
|
+
forge install OpenZeppelin/openzeppelin-contracts-upgradeable@v${contracts.version} --quiet
|
|
212
|
+
forge install OpenZeppelin/openzeppelin-foundry-upgrades --quiet\
|
|
213
213
|
`
|
|
214
214
|
: `\
|
|
215
215
|
# Install OpenZeppelin Contracts
|
|
216
|
-
forge install OpenZeppelin/openzeppelin-contracts@v${contracts.version} --
|
|
216
|
+
forge install OpenZeppelin/openzeppelin-contracts@v${contracts.version} --quiet\
|
|
217
217
|
`
|
|
218
218
|
}
|
|
219
219
|
|