@openzeppelin/wizard 0.1.0 → 0.1.1
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 +26 -1
- package/dist/add-pausable.d.ts.map +1 -1
- package/dist/add-pausable.js +2 -2
- package/dist/add-pausable.js.map +1 -1
- package/dist/api.d.ts +8 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +15 -5
- 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/common-options.js +2 -2
- package/dist/common-options.js.map +1 -1
- package/dist/custom.d.ts +11 -0
- package/dist/custom.d.ts.map +1 -0
- package/dist/custom.js +47 -0
- package/dist/custom.js.map +1 -0
- package/dist/custom.test.d.ts +2 -0
- package/dist/custom.test.d.ts.map +1 -0
- package/dist/custom.test.js +70 -0
- package/dist/custom.test.js.map +1 -0
- package/dist/erc1155.d.ts +2 -0
- package/dist/erc1155.d.ts.map +1 -1
- package/dist/erc1155.js +16 -7
- package/dist/erc1155.js.map +1 -1
- package/dist/erc1155.test.js +11 -0
- package/dist/erc1155.test.js.map +1 -1
- package/dist/erc20.d.ts +1 -0
- package/dist/erc20.d.ts.map +1 -1
- package/dist/erc20.js +8 -3
- package/dist/erc20.js.map +1 -1
- package/dist/erc20.test.js +7 -0
- package/dist/erc20.test.js.map +1 -1
- package/dist/erc721.d.ts +1 -0
- package/dist/erc721.d.ts.map +1 -1
- package/dist/erc721.js +7 -2
- package/dist/erc721.js.map +1 -1
- package/dist/erc721.test.js +6 -0
- package/dist/erc721.test.js.map +1 -1
- package/dist/generate/custom.d.ts +3 -0
- package/dist/generate/custom.d.ts.map +1 -0
- package/dist/generate/custom.js +20 -0
- package/dist/generate/custom.js.map +1 -0
- package/dist/generate/erc1155.d.ts.map +1 -1
- package/dist/generate/erc1155.js +1 -0
- package/dist/generate/erc1155.js.map +1 -1
- package/dist/generate/sources.d.ts.map +1 -1
- package/dist/generate/sources.js +5 -1
- package/dist/generate/sources.js.map +1 -1
- package/dist/governor.d.ts +1 -0
- package/dist/governor.d.ts.map +1 -1
- package/dist/governor.js +7 -1
- package/dist/governor.js.map +1 -1
- package/dist/governor.test.js +4 -0
- package/dist/governor.test.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 +1 -0
- package/dist/kind.js.map +1 -1
- package/dist/print.d.ts.map +1 -1
- package/dist/print.js +16 -12
- package/dist/print.js.map +1 -1
- package/dist/set-access-control.d.ts +9 -2
- package/dist/set-access-control.d.ts.map +1 -1
- package/dist/set-access-control.js +27 -6
- package/dist/set-access-control.js.map +1 -1
- package/dist/set-upgradeable.d.ts.map +1 -1
- package/dist/set-upgradeable.js +1 -1
- package/dist/set-upgradeable.js.map +1 -1
- package/dist/test.js +30 -1
- package/dist/test.js.map +1 -1
- package/package.json +3 -3
- package/src/add-pausable.ts +3 -3
- package/src/api.ts +25 -8
- package/src/build-generic.ts +5 -0
- package/src/common-options.ts +2 -2
- package/src/custom.test.ts +80 -0
- package/src/custom.test.ts.md +154 -0
- package/src/custom.test.ts.snap +0 -0
- package/src/custom.ts +55 -0
- package/src/erc1155.test.ts +13 -0
- package/src/erc1155.test.ts.md +16 -0
- package/src/erc1155.test.ts.snap +0 -0
- package/src/erc1155.ts +17 -7
- package/src/erc20.test.ts +8 -0
- package/src/erc20.ts +8 -4
- package/src/erc721.test.ts +7 -0
- package/src/erc721.ts +7 -3
- package/src/generate/custom.ts +19 -0
- package/src/generate/erc1155.ts +1 -0
- package/src/generate/sources.ts +6 -1
- package/src/governor.test.ts +5 -0
- package/src/governor.ts +6 -1
- package/src/index.ts +1 -1
- package/src/kind.ts +1 -0
- package/src/print.ts +17 -12
- package/src/set-access-control.ts +27 -4
- package/src/set-upgradeable.ts +2 -2
- package/src/test.ts +34 -2
- package/dist/general.d.ts +0 -8
- package/dist/general.d.ts.map +0 -1
- package/dist/general.js +0 -22
- package/dist/general.js.map +0 -1
- package/dist/general.test.d.ts +0 -2
- package/dist/general.test.d.ts.map +0 -1
- package/dist/general.test.js +0 -42
- package/dist/general.test.js.map +0 -1
package/src/erc1155.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Contract, ContractBuilder } from './contract';
|
|
2
|
-
import { Access, setAccessControl } from './set-access-control';
|
|
2
|
+
import { Access, setAccessControl, requireAccessControl } from './set-access-control';
|
|
3
3
|
import { addPausable } from './add-pausable';
|
|
4
4
|
import { supportsInterface } from './common-functions';
|
|
5
5
|
import { defineFunctions } from './utils/define-functions';
|
|
@@ -15,6 +15,7 @@ export interface ERC1155Options extends CommonOptions {
|
|
|
15
15
|
pausable?: boolean;
|
|
16
16
|
mintable?: boolean;
|
|
17
17
|
supply?: boolean;
|
|
18
|
+
updatableUri?: boolean;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export const defaults: Required<ERC1155Options> = {
|
|
@@ -24,7 +25,8 @@ export const defaults: Required<ERC1155Options> = {
|
|
|
24
25
|
pausable: false,
|
|
25
26
|
mintable: false,
|
|
26
27
|
supply: false,
|
|
27
|
-
|
|
28
|
+
updatableUri: true,
|
|
29
|
+
access: false,
|
|
28
30
|
upgradeable: commonDefaults.upgradeable,
|
|
29
31
|
info: commonDefaults.info
|
|
30
32
|
} as const;
|
|
@@ -37,6 +39,7 @@ function withDefaults(opts: ERC1155Options): Required<ERC1155Options> {
|
|
|
37
39
|
pausable: opts.pausable ?? defaults.pausable,
|
|
38
40
|
mintable: opts.mintable ?? defaults.mintable,
|
|
39
41
|
supply: opts.supply ?? defaults.supply,
|
|
42
|
+
updatableUri: opts.updatableUri ?? defaults.updatableUri,
|
|
40
43
|
};
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -44,6 +47,10 @@ export function printERC1155(opts: ERC1155Options = defaults): string {
|
|
|
44
47
|
return printContract(buildERC1155(opts));
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
export function isAccessControlRequired(opts: Partial<ERC1155Options>): boolean {
|
|
51
|
+
return opts.mintable || opts.pausable || opts.updatableUri !== false || opts.upgradeable === 'uups';
|
|
52
|
+
}
|
|
53
|
+
|
|
47
54
|
export function buildERC1155(opts: ERC1155Options): Contract {
|
|
48
55
|
const allOpts = withDefaults(opts);
|
|
49
56
|
|
|
@@ -52,7 +59,10 @@ export function buildERC1155(opts: ERC1155Options): Contract {
|
|
|
52
59
|
const { access, upgradeable, info } = allOpts;
|
|
53
60
|
|
|
54
61
|
addBase(c, allOpts.uri);
|
|
55
|
-
|
|
62
|
+
|
|
63
|
+
if (allOpts.updatableUri) {
|
|
64
|
+
addSetUri(c, access);
|
|
65
|
+
}
|
|
56
66
|
|
|
57
67
|
if (allOpts.pausable) {
|
|
58
68
|
addPausable(c, access, [functions._beforeTokenTransfer]);
|
|
@@ -70,8 +80,8 @@ export function buildERC1155(opts: ERC1155Options): Contract {
|
|
|
70
80
|
addSupply(c);
|
|
71
81
|
}
|
|
72
82
|
|
|
83
|
+
setAccessControl(c, access);
|
|
73
84
|
setUpgradeable(c, upgradeable, access);
|
|
74
|
-
|
|
75
85
|
setInfo(c, info);
|
|
76
86
|
|
|
77
87
|
return c;
|
|
@@ -98,14 +108,14 @@ function addBurnable(c: ContractBuilder) {
|
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
function addMintable(c: ContractBuilder, access: Access) {
|
|
101
|
-
|
|
102
|
-
|
|
111
|
+
requireAccessControl(c, functions.mint, access, 'MINTER');
|
|
112
|
+
requireAccessControl(c, functions.mintBatch, access, 'MINTER');
|
|
103
113
|
c.addFunctionCode('_mint(account, id, amount, data);', functions.mint);
|
|
104
114
|
c.addFunctionCode('_mintBatch(to, ids, amounts, data);', functions.mintBatch);
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
function addSetUri(c: ContractBuilder, access: Access) {
|
|
108
|
-
|
|
118
|
+
requireAccessControl(c, functions.setURI, access, 'URI_SETTER');
|
|
109
119
|
c.addFunctionCode('_setURI(newuri);', functions.setURI);
|
|
110
120
|
}
|
|
111
121
|
|
package/src/erc20.test.ts
CHANGED
|
@@ -141,4 +141,12 @@ testAPIEquivalence('erc20 API full upgradeable', {
|
|
|
141
141
|
|
|
142
142
|
test('erc20 API assert defaults', async t => {
|
|
143
143
|
t.is(erc20.print(erc20.defaults), erc20.print());
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('erc20 API isAccessControlRequired', async t => {
|
|
147
|
+
t.is(erc20.isAccessControlRequired({ mintable: true }), true);
|
|
148
|
+
t.is(erc20.isAccessControlRequired({ pausable: true }), true);
|
|
149
|
+
t.is(erc20.isAccessControlRequired({ snapshots: true }), true);
|
|
150
|
+
t.is(erc20.isAccessControlRequired({ upgradeable: 'uups' }), true);
|
|
151
|
+
t.is(erc20.isAccessControlRequired({ upgradeable: 'transparent' }), false);
|
|
144
152
|
});
|
package/src/erc20.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Contract, ContractBuilder } from './contract';
|
|
2
|
-
import { Access, setAccessControl } from './set-access-control';
|
|
2
|
+
import { Access, setAccessControl, requireAccessControl } from './set-access-control';
|
|
3
3
|
import { addPausable } from './add-pausable';
|
|
4
4
|
import { defineFunctions } from './utils/define-functions';
|
|
5
5
|
import { CommonOptions, withCommonDefaults, defaults as commonDefaults } from './common-options';
|
|
@@ -55,6 +55,10 @@ export function printERC20(opts: ERC20Options = defaults): string {
|
|
|
55
55
|
return printContract(buildERC20(opts));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
export function isAccessControlRequired(opts: Partial<ERC20Options>): boolean {
|
|
59
|
+
return opts.mintable || opts.pausable || opts.snapshots || opts.upgradeable === 'uups';
|
|
60
|
+
}
|
|
61
|
+
|
|
58
62
|
export function buildERC20(opts: ERC20Options): Contract {
|
|
59
63
|
const allOpts = withDefaults(opts);
|
|
60
64
|
|
|
@@ -97,8 +101,8 @@ export function buildERC20(opts: ERC20Options): Contract {
|
|
|
97
101
|
addFlashMint(c);
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
setAccessControl(c, access);
|
|
100
105
|
setUpgradeable(c, upgradeable, access);
|
|
101
|
-
|
|
102
106
|
setInfo(c, info);
|
|
103
107
|
|
|
104
108
|
return c;
|
|
@@ -134,7 +138,7 @@ function addSnapshot(c: ContractBuilder, access: Access) {
|
|
|
134
138
|
|
|
135
139
|
c.addOverride('ERC20Snapshot', functions._beforeTokenTransfer);
|
|
136
140
|
|
|
137
|
-
|
|
141
|
+
requireAccessControl(c, functions.snapshot, access, 'SNAPSHOT');
|
|
138
142
|
c.addFunctionCode('_snapshot();', functions.snapshot);
|
|
139
143
|
}
|
|
140
144
|
|
|
@@ -158,7 +162,7 @@ function addPremint(c: ContractBuilder, amount: string) {
|
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
function addMintable(c: ContractBuilder, access: Access) {
|
|
161
|
-
|
|
165
|
+
requireAccessControl(c, functions.mint, access, 'MINTER');
|
|
162
166
|
c.addFunctionCode('_mint(to, amount);', functions.mint);
|
|
163
167
|
}
|
|
164
168
|
|
package/src/erc721.test.ts
CHANGED
|
@@ -119,4 +119,11 @@ testAPIEquivalence('API full upgradeable', {
|
|
|
119
119
|
|
|
120
120
|
test('API assert defaults', async t => {
|
|
121
121
|
t.is(erc721.print(erc721.defaults), erc721.print());
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('API isAccessControlRequired', async t => {
|
|
125
|
+
t.is(erc721.isAccessControlRequired({ mintable: true }), true);
|
|
126
|
+
t.is(erc721.isAccessControlRequired({ pausable: true }), true);
|
|
127
|
+
t.is(erc721.isAccessControlRequired({ upgradeable: 'uups' }), true);
|
|
128
|
+
t.is(erc721.isAccessControlRequired({ upgradeable: 'transparent' }), false);
|
|
122
129
|
});
|
package/src/erc721.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Contract, ContractBuilder } from './contract';
|
|
2
|
-
import { Access, setAccessControl } from './set-access-control';
|
|
2
|
+
import { Access, setAccessControl, requireAccessControl } from './set-access-control';
|
|
3
3
|
import { addPausable } from './add-pausable';
|
|
4
4
|
import { supportsInterface } from './common-functions';
|
|
5
5
|
import { defineFunctions } from './utils/define-functions';
|
|
@@ -56,6 +56,10 @@ export function printERC721(opts: ERC721Options = defaults): string {
|
|
|
56
56
|
return printContract(buildERC721(opts));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export function isAccessControlRequired(opts: Partial<ERC721Options>): boolean {
|
|
60
|
+
return opts.mintable || opts.pausable || opts.upgradeable === 'uups';
|
|
61
|
+
}
|
|
62
|
+
|
|
59
63
|
export function buildERC721(opts: ERC721Options): Contract {
|
|
60
64
|
const allOpts = withDefaults(opts);
|
|
61
65
|
|
|
@@ -93,8 +97,8 @@ export function buildERC721(opts: ERC721Options): Contract {
|
|
|
93
97
|
addVotes(c, allOpts.name);
|
|
94
98
|
}
|
|
95
99
|
|
|
100
|
+
setAccessControl(c, access);
|
|
96
101
|
setUpgradeable(c, upgradeable, access);
|
|
97
|
-
|
|
98
102
|
setInfo(c, info);
|
|
99
103
|
|
|
100
104
|
return c;
|
|
@@ -150,7 +154,7 @@ function addBurnable(c: ContractBuilder) {
|
|
|
150
154
|
|
|
151
155
|
function addMintable(c: ContractBuilder, access: Access, incremental = false, uriStorage = false) {
|
|
152
156
|
const fn = getMintFunction(incremental, uriStorage);
|
|
153
|
-
|
|
157
|
+
requireAccessControl(c, fn, access, 'MINTER');
|
|
154
158
|
|
|
155
159
|
if (incremental) {
|
|
156
160
|
c.addUsing({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CustomOptions } from '../custom';
|
|
2
|
+
import { accessOptions } from '../set-access-control';
|
|
3
|
+
import { infoOptions } from '../set-info';
|
|
4
|
+
import { upgradeableOptions } from '../set-upgradeable';
|
|
5
|
+
import { generateAlternatives } from './alternatives';
|
|
6
|
+
|
|
7
|
+
const booleans = [true, false];
|
|
8
|
+
|
|
9
|
+
const blueprint = {
|
|
10
|
+
name: ['MyContract'],
|
|
11
|
+
pausable: booleans,
|
|
12
|
+
access: accessOptions,
|
|
13
|
+
upgradeable: upgradeableOptions,
|
|
14
|
+
info: infoOptions,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function* generateCustomOptions(): Generator<Required<CustomOptions>> {
|
|
18
|
+
yield* generateAlternatives(blueprint);
|
|
19
|
+
}
|
package/src/generate/erc1155.ts
CHANGED
package/src/generate/sources.ts
CHANGED
|
@@ -5,9 +5,10 @@ import crypto from 'crypto';
|
|
|
5
5
|
import { generateERC20Options } from './erc20';
|
|
6
6
|
import { generateERC721Options } from './erc721';
|
|
7
7
|
import { generateERC1155Options } from './erc1155';
|
|
8
|
+
import { generateGovernorOptions } from './governor';
|
|
9
|
+
import { generateCustomOptions } from './custom';
|
|
8
10
|
import { buildGeneric, GenericOptions } from '../build-generic';
|
|
9
11
|
import { printContract } from '../print';
|
|
10
|
-
import { generateGovernorOptions } from './governor';
|
|
11
12
|
import { OptionsError } from '../error';
|
|
12
13
|
import { findCover } from '../utils/find-cover';
|
|
13
14
|
import type { Contract } from '../contract';
|
|
@@ -30,6 +31,10 @@ export function* generateOptions(): Generator<GenericOptions> {
|
|
|
30
31
|
for (const kindOpts of generateGovernorOptions()) {
|
|
31
32
|
yield { kind: 'Governor', ...kindOpts };
|
|
32
33
|
}
|
|
34
|
+
|
|
35
|
+
for (const kindOpts of generateCustomOptions()) {
|
|
36
|
+
yield { kind: 'Custom', ...kindOpts };
|
|
37
|
+
}
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
interface GeneratedContract {
|
package/src/governor.test.ts
CHANGED
|
@@ -117,4 +117,9 @@ testAPIEquivalence('API basic upgradeable', { name: 'CustomGovernor', delay: '2
|
|
|
117
117
|
|
|
118
118
|
test('API assert defaults', async t => {
|
|
119
119
|
t.is(governor.print(governor.defaults), governor.print());
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('API isAccessControlRequired', async t => {
|
|
123
|
+
t.is(governor.isAccessControlRequired({ upgradeable: 'uups' }), true);
|
|
124
|
+
t.is(governor.isAccessControlRequired({}), false);
|
|
120
125
|
});
|
package/src/governor.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { supportsInterface } from "./common-functions";
|
|
|
2
2
|
import { CommonOptions, withCommonDefaults, defaults as commonDefaults } from "./common-options";
|
|
3
3
|
import { ContractBuilder, Contract } from "./contract";
|
|
4
4
|
import { OptionsError } from "./error";
|
|
5
|
+
import { setAccessControl } from "./set-access-control";
|
|
5
6
|
import { printContract } from "./print";
|
|
6
7
|
import { setInfo } from "./set-info";
|
|
7
8
|
import { setUpgradeable } from "./set-upgradeable";
|
|
@@ -55,6 +56,10 @@ export interface GovernorOptions extends CommonOptions {
|
|
|
55
56
|
settings?: boolean;
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
export function isAccessControlRequired(opts: Partial<GovernorOptions>): boolean {
|
|
60
|
+
return opts.upgradeable === 'uups';
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
function withDefaults(opts: GovernorOptions): Required<GovernorOptions> {
|
|
59
64
|
return {
|
|
60
65
|
...opts,
|
|
@@ -87,8 +92,8 @@ export function buildGovernor(opts: GovernorOptions): Contract {
|
|
|
87
92
|
addQuorum(c, allOpts);
|
|
88
93
|
addTimelock(c, allOpts);
|
|
89
94
|
|
|
95
|
+
setAccessControl(c, allOpts.access);
|
|
90
96
|
setUpgradeable(c, allOpts.upgradeable, allOpts.access);
|
|
91
|
-
|
|
92
97
|
setInfo(c, allOpts.info);
|
|
93
98
|
|
|
94
99
|
return c;
|
package/src/index.ts
CHANGED
package/src/kind.ts
CHANGED
package/src/print.ts
CHANGED
|
@@ -64,9 +64,9 @@ function printUsingFor(contract: Contract, { transformName }: Helpers): string[]
|
|
|
64
64
|
function printConstructor(contract: Contract, helpers: Helpers): Lines[] {
|
|
65
65
|
const hasParentParams = contract.parents.some(p => p.params.length > 0);
|
|
66
66
|
const hasConstructorCode = contract.constructorCode.length > 0;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const parentsWithInitializers = contract.parents.filter(hasInitializer);
|
|
68
|
+
if (hasParentParams || hasConstructorCode || (helpers.upgradeable && parentsWithInitializers.length > 0)) {
|
|
69
|
+
const parents = parentsWithInitializers
|
|
70
70
|
.flatMap(p => printParentConstructor(p, helpers));
|
|
71
71
|
const modifiers = helpers.upgradeable ? ['initializer public'] : parents;
|
|
72
72
|
const args = contract.constructorArgs.map(a => printArgument(a, helpers));
|
|
@@ -87,22 +87,27 @@ function printConstructor(contract: Contract, helpers: Helpers): Lines[] {
|
|
|
87
87
|
return constructor;
|
|
88
88
|
} else {
|
|
89
89
|
return spaceBetween(
|
|
90
|
-
|
|
91
|
-
'/// @custom:oz-upgrades-unsafe-allow constructor',
|
|
92
|
-
'constructor() {',
|
|
93
|
-
[
|
|
94
|
-
'_disableInitializers();'
|
|
95
|
-
],
|
|
96
|
-
'}'
|
|
97
|
-
],
|
|
90
|
+
DISABLE_INITIALIZERS,
|
|
98
91
|
constructor,
|
|
99
92
|
);
|
|
100
93
|
}
|
|
101
|
-
} else {
|
|
94
|
+
} else if (!helpers.upgradeable) {
|
|
102
95
|
return [];
|
|
96
|
+
} else {
|
|
97
|
+
return DISABLE_INITIALIZERS;
|
|
103
98
|
}
|
|
104
99
|
}
|
|
105
100
|
|
|
101
|
+
const DISABLE_INITIALIZERS =
|
|
102
|
+
[
|
|
103
|
+
'/// @custom:oz-upgrades-unsafe-allow constructor',
|
|
104
|
+
'constructor() {',
|
|
105
|
+
[
|
|
106
|
+
'_disableInitializers();'
|
|
107
|
+
],
|
|
108
|
+
'}'
|
|
109
|
+
];
|
|
110
|
+
|
|
106
111
|
function hasInitializer(parent: Parent) {
|
|
107
112
|
// CAUTION
|
|
108
113
|
// This list is validated by compilation of SafetyCheck.sol.
|
|
@@ -1,23 +1,46 @@
|
|
|
1
1
|
import type { ContractBuilder, BaseFunction } from './contract';
|
|
2
2
|
import { supportsInterface } from './common-functions';
|
|
3
3
|
|
|
4
|
-
export const accessOptions = ['ownable', 'roles'] as const;
|
|
4
|
+
export const accessOptions = [false, 'ownable', 'roles'] as const;
|
|
5
5
|
|
|
6
6
|
export type Access = typeof accessOptions[number];
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Sets access control for the contract by adding inheritance.
|
|
10
|
+
*/
|
|
11
|
+
export function setAccessControl(c: ContractBuilder, access: Access) {
|
|
9
12
|
switch (access) {
|
|
10
13
|
case 'ownable': {
|
|
11
14
|
c.addParent(parents.Ownable);
|
|
12
|
-
c.addModifier('onlyOwner', fn);
|
|
13
15
|
break;
|
|
14
16
|
}
|
|
15
17
|
case 'roles': {
|
|
16
|
-
const roleId = role + '_ROLE';
|
|
17
18
|
if (c.addParent(parents.AccessControl)) {
|
|
18
19
|
c.addConstructorCode('_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);');
|
|
19
20
|
}
|
|
20
21
|
c.addOverride(parents.AccessControl.name, supportsInterface);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Enables access control for the contract and restricts the given function with access control.
|
|
29
|
+
*/
|
|
30
|
+
export function requireAccessControl(c: ContractBuilder, fn: BaseFunction, access: Access, role: string) {
|
|
31
|
+
if (access === false) {
|
|
32
|
+
access = 'ownable';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setAccessControl(c, access);
|
|
36
|
+
|
|
37
|
+
switch (access) {
|
|
38
|
+
case 'ownable': {
|
|
39
|
+
c.addModifier('onlyOwner', fn);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case 'roles': {
|
|
43
|
+
const roleId = role + '_ROLE';
|
|
21
44
|
if (c.addVariable(`bytes32 public constant ${roleId} = keccak256("${roleId}");`)) {
|
|
22
45
|
c.addConstructorCode(`_grantRole(${roleId}, msg.sender);`);
|
|
23
46
|
}
|
package/src/set-upgradeable.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContractBuilder } from './contract';
|
|
2
|
-
import { Access,
|
|
2
|
+
import { Access, requireAccessControl } from './set-access-control';
|
|
3
3
|
import { defineFunctions } from './utils/define-functions';
|
|
4
4
|
|
|
5
5
|
export const upgradeableOptions = [false, 'transparent', 'uups'] as const;
|
|
@@ -22,7 +22,7 @@ export function setUpgradeable(c: ContractBuilder, upgradeable: Upgradeable, acc
|
|
|
22
22
|
case 'transparent': break;
|
|
23
23
|
|
|
24
24
|
case 'uups': {
|
|
25
|
-
|
|
25
|
+
requireAccessControl(c, functions._authorizeUpgrade, access, 'UPGRADER');
|
|
26
26
|
c.addParent({
|
|
27
27
|
name: 'UUPSUpgradeable',
|
|
28
28
|
path: '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol',
|
package/src/test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import hre from 'hardhat';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
3
|
import path from 'path';
|
|
5
4
|
|
|
6
|
-
import { writeGeneratedSources } from './generate/sources';
|
|
5
|
+
import { generateSources, writeGeneratedSources } from './generate/sources';
|
|
6
|
+
import type { GenericOptions } from './build-generic';
|
|
7
|
+
import { custom, erc1155, erc20, erc721, governor } from './api';
|
|
7
8
|
|
|
8
9
|
test('result compiles', async t => {
|
|
9
10
|
const generatedSourcesPath = path.join(hre.config.paths.sources, 'generated');
|
|
@@ -19,3 +20,34 @@ test('result compiles', async t => {
|
|
|
19
20
|
await hre.run('compile');
|
|
20
21
|
t.pass();
|
|
21
22
|
});
|
|
23
|
+
|
|
24
|
+
function isAccessControlRequired(opts: GenericOptions) {
|
|
25
|
+
switch(opts.kind) {
|
|
26
|
+
case 'ERC20':
|
|
27
|
+
return erc20.isAccessControlRequired(opts);
|
|
28
|
+
case 'ERC721':
|
|
29
|
+
return erc721.isAccessControlRequired(opts);
|
|
30
|
+
case 'ERC1155':
|
|
31
|
+
return erc1155.isAccessControlRequired(opts);
|
|
32
|
+
case 'Governor':
|
|
33
|
+
return governor.isAccessControlRequired(opts);
|
|
34
|
+
case 'Custom':
|
|
35
|
+
return custom.isAccessControlRequired(opts);
|
|
36
|
+
default:
|
|
37
|
+
throw new Error("No such kind");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
test('is access control required', async t => {
|
|
42
|
+
for (const contract of generateSources('all')) {
|
|
43
|
+
const regexOwnable = /import.*Ownable(Upgradeable)?.sol.*/gm;
|
|
44
|
+
|
|
45
|
+
if (!contract.options.access) {
|
|
46
|
+
if (isAccessControlRequired(contract.options)) {
|
|
47
|
+
t.regex(contract.source, regexOwnable, JSON.stringify(contract.options));
|
|
48
|
+
} else {
|
|
49
|
+
t.notRegex(contract.source, regexOwnable, JSON.stringify(contract.options));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
package/dist/general.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Contract } from './contract';
|
|
2
|
-
import { CommonOptions } from './common-options';
|
|
3
|
-
export interface GeneralOptions extends CommonOptions {
|
|
4
|
-
name: string;
|
|
5
|
-
pausable?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function buildGeneral(opts: GeneralOptions): Contract;
|
|
8
|
-
//# sourceMappingURL=general.d.ts.map
|
package/dist/general.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,aAAa,EAAsB,MAAM,kBAAkB,CAAC;AAMrE,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,QAAQ,CAc3D"}
|
package/dist/general.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildGeneral = void 0;
|
|
4
|
-
const contract_1 = require("./contract");
|
|
5
|
-
const common_options_1 = require("./common-options");
|
|
6
|
-
const set_upgradeable_1 = require("./set-upgradeable");
|
|
7
|
-
const set_info_1 = require("./set-info");
|
|
8
|
-
const set_access_control_1 = require("./set-access-control");
|
|
9
|
-
const add_pausable_1 = require("./add-pausable");
|
|
10
|
-
function buildGeneral(opts) {
|
|
11
|
-
const c = new contract_1.ContractBuilder(opts.name);
|
|
12
|
-
const { access, upgradeable, info } = (0, common_options_1.withCommonDefaults)(opts);
|
|
13
|
-
if (opts.pausable) {
|
|
14
|
-
(0, add_pausable_1.addPausable)(c, access, []);
|
|
15
|
-
}
|
|
16
|
-
(0, set_access_control_1.setAccessControlForContract)(c, access);
|
|
17
|
-
(0, set_upgradeable_1.setUpgradeable)(c, upgradeable, access);
|
|
18
|
-
(0, set_info_1.setInfo)(c, info);
|
|
19
|
-
return c;
|
|
20
|
-
}
|
|
21
|
-
exports.buildGeneral = buildGeneral;
|
|
22
|
-
//# sourceMappingURL=general.js.map
|
package/dist/general.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"general.js","sourceRoot":"","sources":["../src/general.ts"],"names":[],"mappings":";;;AAAA,yCAAuD;AACvD,qDAAqE;AACrE,uDAAmD;AACnD,yCAAqC;AACrC,6DAAmE;AACnE,iDAA6C;AAO7C,SAAgB,YAAY,CAAC,IAAoB;IAC/C,MAAM,CAAC,GAAG,IAAI,0BAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,IAAA,mCAAkB,EAAC,IAAI,CAAC,CAAC;IAE/D,IAAI,IAAI,CAAC,QAAQ,EAAE;QACjB,IAAA,0BAAW,EAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;KAC5B;IAED,IAAA,gDAA2B,EAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACvC,IAAA,gCAAc,EAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACvC,IAAA,kBAAO,EAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEjB,OAAO,CAAC,CAAC;AACX,CAAC;AAdD,oCAcC"}
|
package/dist/general.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"general.test.d.ts","sourceRoot":"","sources":["../src/general.test.ts"],"names":[],"mappings":""}
|
package/dist/general.test.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const ava_1 = __importDefault(require("ava"));
|
|
7
|
-
const general_1 = require("./general");
|
|
8
|
-
const print_1 = require("./print");
|
|
9
|
-
function testGeneral(title, opts) {
|
|
10
|
-
(0, ava_1.default)(title, t => {
|
|
11
|
-
const c = (0, general_1.buildGeneral)({
|
|
12
|
-
name: 'MyContract',
|
|
13
|
-
...opts,
|
|
14
|
-
});
|
|
15
|
-
t.snapshot((0, print_1.printContract)(c));
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
testGeneral('general', {});
|
|
19
|
-
testGeneral('pausable', {
|
|
20
|
-
pausable: true,
|
|
21
|
-
});
|
|
22
|
-
testGeneral('upgradeable transparent', {
|
|
23
|
-
upgradeable: 'transparent',
|
|
24
|
-
});
|
|
25
|
-
testGeneral('upgradeable uups', {
|
|
26
|
-
upgradeable: 'uups',
|
|
27
|
-
});
|
|
28
|
-
testGeneral('access control disabled', {
|
|
29
|
-
access: false,
|
|
30
|
-
});
|
|
31
|
-
testGeneral('access control ownable', {
|
|
32
|
-
access: 'ownable',
|
|
33
|
-
});
|
|
34
|
-
testGeneral('access control roles', {
|
|
35
|
-
access: 'roles',
|
|
36
|
-
});
|
|
37
|
-
testGeneral('upgradeable uups with access control disabled', {
|
|
38
|
-
// API should override access to true since it is required for UUPS
|
|
39
|
-
access: false,
|
|
40
|
-
upgradeable: 'uups',
|
|
41
|
-
});
|
|
42
|
-
//# sourceMappingURL=general.test.js.map
|
package/dist/general.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"general.test.js","sourceRoot":"","sources":["../src/general.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAAuB;AAGvB,uCAAyD;AACzD,mCAAwC;AAExC,SAAS,WAAW,CAAC,KAAa,EAAE,IAA6B;IAC/D,IAAA,aAAI,EAAC,KAAK,EAAE,CAAC,CAAC,EAAE;QACd,MAAM,CAAC,GAAG,IAAA,sBAAY,EAAC;YACrB,IAAI,EAAE,YAAY;YAClB,GAAG,IAAI;SACR,CAAC,CAAC;QACH,CAAC,CAAC,QAAQ,CAAC,IAAA,qBAAa,EAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AAE3B,WAAW,CAAC,UAAU,EAAE;IACtB,QAAQ,EAAE,IAAI;CACf,CAAC,CAAC;AAEH,WAAW,CAAC,yBAAyB,EAAE;IACrC,WAAW,EAAE,aAAa;CAC3B,CAAC,CAAC;AAEH,WAAW,CAAC,kBAAkB,EAAE;IAC9B,WAAW,EAAE,MAAM;CACpB,CAAC,CAAC;AAEH,WAAW,CAAC,yBAAyB,EAAE;IACrC,MAAM,EAAE,KAAK;CACd,CAAC,CAAC;AAEH,WAAW,CAAC,wBAAwB,EAAE;IACpC,MAAM,EAAE,SAAS;CAClB,CAAC,CAAC;AAEH,WAAW,CAAC,sBAAsB,EAAE;IAClC,MAAM,EAAE,OAAO;CAChB,CAAC,CAAC;AAEH,WAAW,CAAC,+CAA+C,EAAE;IAC3D,mEAAmE;IACnE,MAAM,EAAE,KAAK;IACb,WAAW,EAAE,MAAM;CACpB,CAAC,CAAC"}
|