@lazy-sol/access-control 1.0.3

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.
@@ -0,0 +1,342 @@
1
+ {
2
+ "_format": "hh-sol-artifact-1",
3
+ "contractName": "OwnableToAccessControlAdapter",
4
+ "sourceName": "contracts/OwnableToAccessControlAdapter.sol",
5
+ "abi": [
6
+ {
7
+ "inputs": [
8
+ {
9
+ "internalType": "address",
10
+ "name": "_target",
11
+ "type": "address"
12
+ },
13
+ {
14
+ "internalType": "address",
15
+ "name": "_owner",
16
+ "type": "address"
17
+ }
18
+ ],
19
+ "stateMutability": "nonpayable",
20
+ "type": "constructor"
21
+ },
22
+ {
23
+ "anonymous": false,
24
+ "inputs": [
25
+ {
26
+ "indexed": false,
27
+ "internalType": "bytes4",
28
+ "name": "selector",
29
+ "type": "bytes4"
30
+ },
31
+ {
32
+ "indexed": false,
33
+ "internalType": "uint256",
34
+ "name": "role",
35
+ "type": "uint256"
36
+ }
37
+ ],
38
+ "name": "AccessRoleUpdated",
39
+ "type": "event"
40
+ },
41
+ {
42
+ "anonymous": false,
43
+ "inputs": [
44
+ {
45
+ "indexed": false,
46
+ "internalType": "bytes4",
47
+ "name": "selector",
48
+ "type": "bytes4"
49
+ },
50
+ {
51
+ "indexed": false,
52
+ "internalType": "bytes",
53
+ "name": "data",
54
+ "type": "bytes"
55
+ },
56
+ {
57
+ "indexed": false,
58
+ "internalType": "bytes",
59
+ "name": "result",
60
+ "type": "bytes"
61
+ }
62
+ ],
63
+ "name": "ExecutionComplete",
64
+ "type": "event"
65
+ },
66
+ {
67
+ "anonymous": false,
68
+ "inputs": [
69
+ {
70
+ "indexed": true,
71
+ "internalType": "address",
72
+ "name": "operator",
73
+ "type": "address"
74
+ },
75
+ {
76
+ "indexed": false,
77
+ "internalType": "uint256",
78
+ "name": "requested",
79
+ "type": "uint256"
80
+ },
81
+ {
82
+ "indexed": false,
83
+ "internalType": "uint256",
84
+ "name": "assigned",
85
+ "type": "uint256"
86
+ }
87
+ ],
88
+ "name": "RoleUpdated",
89
+ "type": "event"
90
+ },
91
+ {
92
+ "stateMutability": "payable",
93
+ "type": "fallback"
94
+ },
95
+ {
96
+ "inputs": [],
97
+ "name": "ROLE_ACCESS_MANAGER",
98
+ "outputs": [
99
+ {
100
+ "internalType": "uint256",
101
+ "name": "",
102
+ "type": "uint256"
103
+ }
104
+ ],
105
+ "stateMutability": "view",
106
+ "type": "function"
107
+ },
108
+ {
109
+ "inputs": [],
110
+ "name": "ROLE_ACCESS_ROLES_MANAGER",
111
+ "outputs": [
112
+ {
113
+ "internalType": "uint256",
114
+ "name": "",
115
+ "type": "uint256"
116
+ }
117
+ ],
118
+ "stateMutability": "view",
119
+ "type": "function"
120
+ },
121
+ {
122
+ "inputs": [
123
+ {
124
+ "internalType": "bytes4",
125
+ "name": "",
126
+ "type": "bytes4"
127
+ }
128
+ ],
129
+ "name": "accessRoles",
130
+ "outputs": [
131
+ {
132
+ "internalType": "uint256",
133
+ "name": "",
134
+ "type": "uint256"
135
+ }
136
+ ],
137
+ "stateMutability": "view",
138
+ "type": "function"
139
+ },
140
+ {
141
+ "inputs": [
142
+ {
143
+ "internalType": "bytes",
144
+ "name": "data",
145
+ "type": "bytes"
146
+ }
147
+ ],
148
+ "name": "execute",
149
+ "outputs": [
150
+ {
151
+ "internalType": "bytes",
152
+ "name": "",
153
+ "type": "bytes"
154
+ }
155
+ ],
156
+ "stateMutability": "payable",
157
+ "type": "function"
158
+ },
159
+ {
160
+ "inputs": [],
161
+ "name": "features",
162
+ "outputs": [
163
+ {
164
+ "internalType": "uint256",
165
+ "name": "",
166
+ "type": "uint256"
167
+ }
168
+ ],
169
+ "stateMutability": "view",
170
+ "type": "function"
171
+ },
172
+ {
173
+ "inputs": [
174
+ {
175
+ "internalType": "address",
176
+ "name": "operator",
177
+ "type": "address"
178
+ }
179
+ ],
180
+ "name": "getRole",
181
+ "outputs": [
182
+ {
183
+ "internalType": "uint256",
184
+ "name": "",
185
+ "type": "uint256"
186
+ }
187
+ ],
188
+ "stateMutability": "view",
189
+ "type": "function"
190
+ },
191
+ {
192
+ "inputs": [
193
+ {
194
+ "internalType": "uint256",
195
+ "name": "required",
196
+ "type": "uint256"
197
+ }
198
+ ],
199
+ "name": "isFeatureEnabled",
200
+ "outputs": [
201
+ {
202
+ "internalType": "bool",
203
+ "name": "",
204
+ "type": "bool"
205
+ }
206
+ ],
207
+ "stateMutability": "view",
208
+ "type": "function"
209
+ },
210
+ {
211
+ "inputs": [
212
+ {
213
+ "internalType": "address",
214
+ "name": "operator",
215
+ "type": "address"
216
+ },
217
+ {
218
+ "internalType": "uint256",
219
+ "name": "required",
220
+ "type": "uint256"
221
+ }
222
+ ],
223
+ "name": "isOperatorInRole",
224
+ "outputs": [
225
+ {
226
+ "internalType": "bool",
227
+ "name": "",
228
+ "type": "bool"
229
+ }
230
+ ],
231
+ "stateMutability": "view",
232
+ "type": "function"
233
+ },
234
+ {
235
+ "inputs": [
236
+ {
237
+ "internalType": "uint256",
238
+ "name": "required",
239
+ "type": "uint256"
240
+ }
241
+ ],
242
+ "name": "isSenderInRole",
243
+ "outputs": [
244
+ {
245
+ "internalType": "bool",
246
+ "name": "",
247
+ "type": "bool"
248
+ }
249
+ ],
250
+ "stateMutability": "view",
251
+ "type": "function"
252
+ },
253
+ {
254
+ "inputs": [],
255
+ "name": "target",
256
+ "outputs": [
257
+ {
258
+ "internalType": "address",
259
+ "name": "",
260
+ "type": "address"
261
+ }
262
+ ],
263
+ "stateMutability": "view",
264
+ "type": "function"
265
+ },
266
+ {
267
+ "inputs": [
268
+ {
269
+ "internalType": "bytes4",
270
+ "name": "selector",
271
+ "type": "bytes4"
272
+ },
273
+ {
274
+ "internalType": "uint256",
275
+ "name": "role",
276
+ "type": "uint256"
277
+ }
278
+ ],
279
+ "name": "updateAccessRole",
280
+ "outputs": [],
281
+ "stateMutability": "nonpayable",
282
+ "type": "function"
283
+ },
284
+ {
285
+ "inputs": [
286
+ {
287
+ "internalType": "string",
288
+ "name": "signature",
289
+ "type": "string"
290
+ },
291
+ {
292
+ "internalType": "uint256",
293
+ "name": "role",
294
+ "type": "uint256"
295
+ }
296
+ ],
297
+ "name": "updateAccessRole",
298
+ "outputs": [],
299
+ "stateMutability": "nonpayable",
300
+ "type": "function"
301
+ },
302
+ {
303
+ "inputs": [
304
+ {
305
+ "internalType": "uint256",
306
+ "name": "_mask",
307
+ "type": "uint256"
308
+ }
309
+ ],
310
+ "name": "updateFeatures",
311
+ "outputs": [],
312
+ "stateMutability": "nonpayable",
313
+ "type": "function"
314
+ },
315
+ {
316
+ "inputs": [
317
+ {
318
+ "internalType": "address",
319
+ "name": "operator",
320
+ "type": "address"
321
+ },
322
+ {
323
+ "internalType": "uint256",
324
+ "name": "role",
325
+ "type": "uint256"
326
+ }
327
+ ],
328
+ "name": "updateRole",
329
+ "outputs": [],
330
+ "stateMutability": "nonpayable",
331
+ "type": "function"
332
+ },
333
+ {
334
+ "stateMutability": "payable",
335
+ "type": "receive"
336
+ }
337
+ ],
338
+ "bytecode": "0x608060405234801561001057600080fd5b50604051610b40380380610b4083398101604081905261002f9161012f565b80600061003f82600019806100bb565b61004a3082806100bb565b50506001600160a01b0382166100955760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b604482015260640160405180910390fd5b50600180546001600160a01b0319166001600160a01b0392909216919091179055610162565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b80516001600160a01b038116811461012a57600080fd5b919050565b6000806040838503121561014257600080fd5b61014b83610113565b915061015960208401610113565b90509250929050565b6109cf806101716000396000f3fe6080604052600436106100e15760003560e01c8063725f36261161007f578063c688d69311610059578063c688d693146102bc578063d4b83992146102dc578063d5bb7f6714610314578063fcc2c0781461033457610100565b8063725f362614610254578063ae5b102e14610284578063ae682e2e146102a457610100565b806334e48c9e116100bb57806334e48c9e146101c657806344276733146101de578063491d2611146102145780635defb40d1461023457610100565b806309c5eabe146101405780630e82fe25146101695780632b521416146101a457610100565b36610100576100fe60405180602001604052806000815250610354565b005b6100fe6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061035492505050565b61015361014e366004610742565b610354565b60405161016091906107e3565b60405180910390f35b34801561017557600080fd5b50610196610184366004610813565b60026020526000908152604090205481565b604051908152602001610160565b3480156101b057600080fd5b5030600090815260208190526040902054610196565b3480156101d257600080fd5b50610196600160fd1b81565b3480156101ea57600080fd5b506101966101f9366004610845565b6001600160a01b031660009081526020819052604090205490565b34801561022057600080fd5b506100fe61022f366004610860565b6104de565b34801561024057600080fd5b506100fe61024f36600461088a565b610560565b34801561026057600080fd5b5061027461026f3660046108e3565b610575565b6040519015158152602001610160565b34801561029057600080fd5b506100fe61029f3660046108fc565b610597565b3480156102b057600080fd5b50610196600160ff1b81565b3480156102c857600080fd5b506102746102d73660046108fc565b61061c565b3480156102e857600080fd5b506001546102fc906001600160a01b031681565b6040516001600160a01b039091168152602001610160565b34801561032057600080fd5b506100fe61032f3660046108e3565b610645565b34801561034057600080fd5b5061027461034f3660046108e3565b610652565b6020810151815160609190156103f0576001600160e01b03198116600090815260026020526040812054908190036103c95760405162461bcd60e51b81526020600482015260136024820152721858d8d95cdcc81c9bdb19481b9bdd081cd95d606a1b60448201526064015b60405180910390fd5b6103d281610652565b6103ee5760405162461bcd60e51b81526004016103c090610918565b505b60015460405160009182916001600160a01b0390911690349061041490889061093f565b60006040518083038185875af1925050503d8060008114610451576040519150601f19603f3d011682016040523d82523d6000602084013e610456565b606091505b50915091508161049b5760405162461bcd60e51b815260206004820152601060248201526f195e1958dd5d1a5bdb8819985a5b195960821b60448201526064016103c0565b7f57a62eca76fc623c92f161d2a4b851851ece707135ce2af1eec256d660571b6d8386836040516104ce9392919061095b565b60405180910390a1949350505050565b6104eb600160fd1b610652565b6105075760405162461bcd60e51b81526004016103c090610918565b6001600160e01b03198216600081815260026020908152604091829020849055815192835282018390527fdb8ed917742b49e83acd1322bcaa8f18b1e5f78a70784c43ea14db7ab50e628d910160405180910390a15050565b6105718280519060200120826104de565b5050565b30600090815260208190526040812054610591905b8316831490565b92915050565b6105a4600160ff1b610652565b6105c05760405162461bcd60e51b81526004016103c090610918565b6105718282610617336105e8876001600160a01b031660009081526020819052604090205490565b6001600160a01b0391909116600090815260208190526040902054600019808818821618908716919091171690565b61065e565b6001600160a01b03821660009081526020819052604081205461063e9061058a565b9392505050565b61064f3082610597565b50565b6000610591338361061c565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156106e7576106e76106b6565b604051601f8501601f19908116603f0116810190828211818310171561070f5761070f6106b6565b8160405280935085815286868601111561072857600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561075457600080fd5b813567ffffffffffffffff81111561076b57600080fd5b8201601f8101841361077c57600080fd5b61078b848235602084016106cc565b949350505050565b60005b838110156107ae578181015183820152602001610796565b50506000910152565b600081518084526107cf816020860160208601610793565b601f01601f19169290920160200192915050565b60208152600061063e60208301846107b7565b80356001600160e01b03198116811461080e57600080fd5b919050565b60006020828403121561082557600080fd5b61063e826107f6565b80356001600160a01b038116811461080e57600080fd5b60006020828403121561085757600080fd5b61063e8261082e565b6000806040838503121561087357600080fd5b61087c836107f6565b946020939093013593505050565b6000806040838503121561089d57600080fd5b823567ffffffffffffffff8111156108b457600080fd5b8301601f810185136108c557600080fd5b6108d4858235602084016106cc565b95602094909401359450505050565b6000602082840312156108f557600080fd5b5035919050565b6000806040838503121561090f57600080fd5b61087c8361082e565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b60008251610951818460208701610793565b9190910192915050565b63ffffffff60e01b8416815260606020820152600061097d60608301856107b7565b828103604084015261098f81856107b7565b969550505050505056fea26469706673582212206993ad950cca82a01e8e72c0503e3a006930148e125b67ad2894063853f6078264736f6c63430008150033",
339
+ "deployedBytecode": "0x6080604052600436106100e15760003560e01c8063725f36261161007f578063c688d69311610059578063c688d693146102bc578063d4b83992146102dc578063d5bb7f6714610314578063fcc2c0781461033457610100565b8063725f362614610254578063ae5b102e14610284578063ae682e2e146102a457610100565b806334e48c9e116100bb57806334e48c9e146101c657806344276733146101de578063491d2611146102145780635defb40d1461023457610100565b806309c5eabe146101405780630e82fe25146101695780632b521416146101a457610100565b36610100576100fe60405180602001604052806000815250610354565b005b6100fe6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061035492505050565b61015361014e366004610742565b610354565b60405161016091906107e3565b60405180910390f35b34801561017557600080fd5b50610196610184366004610813565b60026020526000908152604090205481565b604051908152602001610160565b3480156101b057600080fd5b5030600090815260208190526040902054610196565b3480156101d257600080fd5b50610196600160fd1b81565b3480156101ea57600080fd5b506101966101f9366004610845565b6001600160a01b031660009081526020819052604090205490565b34801561022057600080fd5b506100fe61022f366004610860565b6104de565b34801561024057600080fd5b506100fe61024f36600461088a565b610560565b34801561026057600080fd5b5061027461026f3660046108e3565b610575565b6040519015158152602001610160565b34801561029057600080fd5b506100fe61029f3660046108fc565b610597565b3480156102b057600080fd5b50610196600160ff1b81565b3480156102c857600080fd5b506102746102d73660046108fc565b61061c565b3480156102e857600080fd5b506001546102fc906001600160a01b031681565b6040516001600160a01b039091168152602001610160565b34801561032057600080fd5b506100fe61032f3660046108e3565b610645565b34801561034057600080fd5b5061027461034f3660046108e3565b610652565b6020810151815160609190156103f0576001600160e01b03198116600090815260026020526040812054908190036103c95760405162461bcd60e51b81526020600482015260136024820152721858d8d95cdcc81c9bdb19481b9bdd081cd95d606a1b60448201526064015b60405180910390fd5b6103d281610652565b6103ee5760405162461bcd60e51b81526004016103c090610918565b505b60015460405160009182916001600160a01b0390911690349061041490889061093f565b60006040518083038185875af1925050503d8060008114610451576040519150601f19603f3d011682016040523d82523d6000602084013e610456565b606091505b50915091508161049b5760405162461bcd60e51b815260206004820152601060248201526f195e1958dd5d1a5bdb8819985a5b195960821b60448201526064016103c0565b7f57a62eca76fc623c92f161d2a4b851851ece707135ce2af1eec256d660571b6d8386836040516104ce9392919061095b565b60405180910390a1949350505050565b6104eb600160fd1b610652565b6105075760405162461bcd60e51b81526004016103c090610918565b6001600160e01b03198216600081815260026020908152604091829020849055815192835282018390527fdb8ed917742b49e83acd1322bcaa8f18b1e5f78a70784c43ea14db7ab50e628d910160405180910390a15050565b6105718280519060200120826104de565b5050565b30600090815260208190526040812054610591905b8316831490565b92915050565b6105a4600160ff1b610652565b6105c05760405162461bcd60e51b81526004016103c090610918565b6105718282610617336105e8876001600160a01b031660009081526020819052604090205490565b6001600160a01b0391909116600090815260208190526040902054600019808818821618908716919091171690565b61065e565b6001600160a01b03821660009081526020819052604081205461063e9061058a565b9392505050565b61064f3082610597565b50565b6000610591338361061c565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156106e7576106e76106b6565b604051601f8501601f19908116603f0116810190828211818310171561070f5761070f6106b6565b8160405280935085815286868601111561072857600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561075457600080fd5b813567ffffffffffffffff81111561076b57600080fd5b8201601f8101841361077c57600080fd5b61078b848235602084016106cc565b949350505050565b60005b838110156107ae578181015183820152602001610796565b50506000910152565b600081518084526107cf816020860160208601610793565b601f01601f19169290920160200192915050565b60208152600061063e60208301846107b7565b80356001600160e01b03198116811461080e57600080fd5b919050565b60006020828403121561082557600080fd5b61063e826107f6565b80356001600160a01b038116811461080e57600080fd5b60006020828403121561085757600080fd5b61063e8261082e565b6000806040838503121561087357600080fd5b61087c836107f6565b946020939093013593505050565b6000806040838503121561089d57600080fd5b823567ffffffffffffffff8111156108b457600080fd5b8301601f810185136108c557600080fd5b6108d4858235602084016106cc565b95602094909401359450505050565b6000602082840312156108f557600080fd5b5035919050565b6000806040838503121561090f57600080fd5b61087c8361082e565b6020808252600d908201526c1858d8d95cdcc819195b9a5959609a1b604082015260600190565b60008251610951818460208701610793565b9190910192915050565b63ffffffff60e01b8416815260606020820152600061097d60608301856107b7565b828103604084015261098f81856107b7565b969550505050505056fea26469706673582212206993ad950cca82a01e8e72c0503e3a006930148e125b67ad2894063853f6078264736f6c63430008150033",
340
+ "linkReferences": {},
341
+ "deployedLinkReferences": {}
342
+ }
@@ -0,0 +1,305 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity >=0.4.22; // require with message (0.4.22), pure/view modifiers (0.4.16), hardhat (0.4.11)
3
+
4
+ /**
5
+ * @title Role-based Access Control (RBAC)
6
+ *
7
+ * @notice Access control smart contract provides an API to check
8
+ * if a specific operation is permitted globally and/or
9
+ * if a particular user has a permission to execute it.
10
+ *
11
+ * @notice This contract is inherited by other contracts requiring the role-based access control (RBAC)
12
+ * protection for the restricted access functions
13
+ *
14
+ * @notice It deals with two main entities: features and roles.
15
+ *
16
+ * @notice Features are designed to be used to enable/disable public functions
17
+ * of the smart contract (used by a wide audience).
18
+ * @notice User roles are designed to control the access to restricted functions
19
+ * of the smart contract (used by a limited set of maintainers).
20
+ *
21
+ * @notice Terms "role", "permissions" and "set of permissions" have equal meaning
22
+ * in the documentation text and may be used interchangeably.
23
+ * @notice Terms "permission", "single permission" implies only one permission bit set.
24
+ *
25
+ * @notice Access manager is a special role which allows to grant/revoke other roles.
26
+ * Access managers can only grant/revoke permissions which they have themselves.
27
+ * As an example, access manager with no other roles set can only grant/revoke its own
28
+ * access manager permission and nothing else.
29
+ *
30
+ * @notice Access manager permission should be treated carefully, as a super admin permission:
31
+ * Access manager with even no other permission can interfere with another account by
32
+ * granting own access manager permission to it and effectively creating more powerful
33
+ * permission set than its own.
34
+ *
35
+ * @dev Both current and OpenZeppelin AccessControl implementations feature a similar API
36
+ * to check/know "who is allowed to do this thing".
37
+ * @dev Zeppelin implementation is more flexible:
38
+ * - it allows setting unlimited number of roles, while current is limited to 256 different roles
39
+ * - it allows setting an admin for each role, while current allows having only one global admin
40
+ * @dev Current implementation is more lightweight:
41
+ * - it uses only 1 bit per role, while Zeppelin uses 256 bits
42
+ * - it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows
43
+ * setting only one role in a single transaction
44
+ *
45
+ * @dev This smart contract is designed to be inherited by other
46
+ * smart contracts which require access control management capabilities.
47
+ *
48
+ * @dev Access manager permission has a bit 255 set.
49
+ * This bit must not be used by inheriting contracts for any other permissions/features.
50
+ *
51
+ * @author Basil Gorin
52
+ */
53
+ abstract contract AccessControl {
54
+ /**
55
+ * @dev Privileged addresses with defined roles/permissions
56
+ * @dev In the context of ERC20/ERC721 tokens these can be permissions to
57
+ * allow minting or burning tokens, transferring on behalf and so on
58
+ *
59
+ * @dev Maps user address to the permissions bitmask (role), where each bit
60
+ * represents a permission
61
+ * @dev Bitmask 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
62
+ * represents all possible permissions
63
+ * @dev 'This' address mapping represents global features of the smart contract
64
+ *
65
+ * @dev We keep the mapping private to prevent direct writes to it from the inheriting
66
+ * contracts, `getRole()` and `updateRole()` functions should be used instead
67
+ */
68
+ mapping(address => uint256) private userRoles;
69
+
70
+ /**
71
+ * @notice Access manager is responsible for assigning the roles to users,
72
+ * enabling/disabling global features of the smart contract
73
+ * @notice Access manager can add, remove and update user roles,
74
+ * remove and update global features
75
+ *
76
+ * @dev Role ROLE_ACCESS_MANAGER allows modifying user roles and global features
77
+ * @dev Role ROLE_ACCESS_MANAGER has single bit at position 255 enabled
78
+ */
79
+ uint256 public constant ROLE_ACCESS_MANAGER = 0x8000000000000000000000000000000000000000000000000000000000000000;
80
+
81
+ /**
82
+ * @dev Bitmask representing all the possible permissions (super admin role)
83
+ * @dev Has all the bits are enabled (2^256 - 1 value)
84
+ */
85
+ uint256 internal constant FULL_PRIVILEGES_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
86
+
87
+ /**
88
+ * @dev Fired in updateRole() and updateFeatures()
89
+ *
90
+ * @param operator address which was granted/revoked permissions
91
+ * @param requested permissions requested
92
+ * @param assigned permissions effectively set
93
+ */
94
+ event RoleUpdated(address indexed operator, uint256 requested, uint256 assigned);
95
+
96
+ /**
97
+ * @notice Function modifier making a function defined as public behave as restricted
98
+ * (so that only a pre-configured set of accounts can execute it)
99
+ *
100
+ * @param role the role transaction executor is required to have;
101
+ * the function throws an "access denied" exception if this condition is not met
102
+ */
103
+ modifier restrictedTo(uint256 role) {
104
+ // verify the access permission
105
+ require(isSenderInRole(role), "access denied");
106
+
107
+ // execute the rest of the function
108
+ _;
109
+ }
110
+
111
+ /**
112
+ * @notice Creates an access control instance, setting the contract owner to have full privileges
113
+ *
114
+ * @param _owner smart contract owner having full privileges, can be zero
115
+ * @param _features initial features mask of the contract, can be zero
116
+ */
117
+ constructor(address _owner, uint256 _features) internal { // visibility modifier is required to be compilable with 0.6.x
118
+ // grant owner full privileges
119
+ __setRole(_owner, FULL_PRIVILEGES_MASK, FULL_PRIVILEGES_MASK);
120
+ // update initial features bitmask
121
+ __setRole(address(this), _features, _features);
122
+ }
123
+
124
+ /**
125
+ * @notice Retrieves globally set of features enabled
126
+ *
127
+ * @dev Effectively reads userRoles role for the contract itself
128
+ *
129
+ * @return 256-bit bitmask of the features enabled
130
+ */
131
+ function features() public view returns (uint256) {
132
+ // features are stored in 'this' address mapping of `userRoles`
133
+ return getRole(address(this));
134
+ }
135
+
136
+ /**
137
+ * @notice Updates set of the globally enabled features (`features`),
138
+ * taking into account sender's permissions
139
+ *
140
+ * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
141
+ * @dev Function is left for backward compatibility with older versions
142
+ *
143
+ * @param _mask bitmask representing a set of features to enable/disable
144
+ */
145
+ function updateFeatures(uint256 _mask) public {
146
+ // delegate call to `updateRole`
147
+ updateRole(address(this), _mask);
148
+ }
149
+
150
+ /**
151
+ * @notice Reads the permissions (role) for a given user from the `userRoles` mapping
152
+ * (privileged addresses with defined roles/permissions)
153
+ * @notice In the context of ERC20/ERC721 tokens these can be permissions to
154
+ * allow minting or burning tokens, transferring on behalf and so on
155
+ *
156
+ * @dev Having a simple getter instead of making the mapping public
157
+ * allows enforcing the encapsulation of the mapping and protects from
158
+ * writing to it directly in the inheriting smart contracts
159
+ *
160
+ * @param operator address of a user to read permissions for,
161
+ * or self address to read global features of the smart contract
162
+ */
163
+ function getRole(address operator) public view returns(uint256) {
164
+ // read the value from `userRoles` and return
165
+ return userRoles[operator];
166
+ }
167
+
168
+ /**
169
+ * @notice Updates set of permissions (role) for a given user,
170
+ * taking into account sender's permissions.
171
+ *
172
+ * @dev Setting role to zero is equivalent to removing an all permissions
173
+ * @dev Setting role to `FULL_PRIVILEGES_MASK` is equivalent to
174
+ * copying senders' permissions (role) to the user
175
+ * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
176
+ *
177
+ * @param operator address of a user to alter permissions for,
178
+ * or self address to alter global features of the smart contract
179
+ * @param role bitmask representing a set of permissions to
180
+ * enable/disable for a user specified
181
+ */
182
+ function updateRole(address operator, uint256 role) public {
183
+ // caller must have a permission to update user roles
184
+ require(isSenderInRole(ROLE_ACCESS_MANAGER), "access denied");
185
+
186
+ // evaluate the role and reassign it
187
+ __setRole(operator, role, _evaluateBy(msg.sender, getRole(operator), role));
188
+ }
189
+
190
+ /**
191
+ * @notice Determines the permission bitmask an operator can set on the
192
+ * target permission set
193
+ * @notice Used to calculate the permission bitmask to be set when requested
194
+ * in `updateRole` and `updateFeatures` functions
195
+ *
196
+ * @dev Calculated based on:
197
+ * 1) operator's own permission set read from userRoles[operator]
198
+ * 2) target permission set - what is already set on the target
199
+ * 3) desired permission set - what do we want set target to
200
+ *
201
+ * @dev Corner cases:
202
+ * 1) Operator is super admin and its permission set is `FULL_PRIVILEGES_MASK`:
203
+ * `desired` bitset is returned regardless of the `target` permission set value
204
+ * (what operator sets is what they get)
205
+ * 2) Operator with no permissions (zero bitset):
206
+ * `target` bitset is returned regardless of the `desired` value
207
+ * (operator has no authority and cannot modify anything)
208
+ *
209
+ * @dev Example:
210
+ * Consider an operator with the permissions bitmask 00001111
211
+ * is about to modify the target permission set 01010101
212
+ * Operator wants to set that permission set to 00110011
213
+ * Based on their role, an operator has the permissions
214
+ * to update only lowest 4 bits on the target, meaning that
215
+ * high 4 bits of the target set in this example is left
216
+ * unchanged and low 4 bits get changed as desired: 01010011
217
+ *
218
+ * @param operator address of the contract operator which is about to set the permissions
219
+ * @param target input set of permissions to operator is going to modify
220
+ * @param desired desired set of permissions operator would like to set
221
+ * @return resulting set of permissions given operator will set
222
+ */
223
+ function _evaluateBy(address operator, uint256 target, uint256 desired) internal view returns (uint256) {
224
+ // read operator's permissions
225
+ uint256 p = getRole(operator);
226
+
227
+ // taking into account operator's permissions,
228
+ // 1) enable the permissions desired on the `target`
229
+ target |= p & desired;
230
+ // 2) disable the permissions desired on the `target`
231
+ target &= FULL_PRIVILEGES_MASK ^ (p & (FULL_PRIVILEGES_MASK ^ desired));
232
+
233
+ // return calculated result
234
+ return target;
235
+ }
236
+
237
+ /**
238
+ * @notice Checks if requested set of features is enabled globally on the contract
239
+ *
240
+ * @param required set of features to check against
241
+ * @return true if all the features requested are enabled, false otherwise
242
+ */
243
+ function isFeatureEnabled(uint256 required) public view returns (bool) {
244
+ // delegate call to `__hasRole`, passing `features` property
245
+ return __hasRole(features(), required);
246
+ }
247
+
248
+ /**
249
+ * @notice Checks if transaction sender `msg.sender` has all the permissions required
250
+ *
251
+ * @param required set of permissions (role) to check against
252
+ * @return true if all the permissions requested are enabled, false otherwise
253
+ */
254
+ function isSenderInRole(uint256 required) public view returns (bool) {
255
+ // delegate call to `isOperatorInRole`, passing transaction sender
256
+ return isOperatorInRole(msg.sender, required);
257
+ }
258
+
259
+ /**
260
+ * @notice Checks if operator has all the permissions (role) required
261
+ *
262
+ * @param operator address of the user to check role for
263
+ * @param required set of permissions (role) to check
264
+ * @return true if all the permissions requested are enabled, false otherwise
265
+ */
266
+ function isOperatorInRole(address operator, uint256 required) public view returns (bool) {
267
+ // delegate call to `__hasRole`, passing operator's permissions (role)
268
+ return __hasRole(getRole(operator), required);
269
+ }
270
+
271
+ /**
272
+ * @dev Sets the `assignedRole` role to the operator, logs both `requestedRole` and `actualRole`
273
+ *
274
+ * @dev Unsafe:
275
+ * provides direct write access to `userRoles` mapping without any security checks,
276
+ * doesn't verify the executor (msg.sender) permissions,
277
+ * must be kept private at all times
278
+ *
279
+ * @param operator address of a user to alter permissions for,
280
+ * or self address to alter global features of the smart contract
281
+ * @param requestedRole bitmask representing a set of permissions requested
282
+ * to be enabled/disabled for a user specified, used only to be logged into event
283
+ * @param assignedRole bitmask representing a set of permissions to
284
+ * enable/disable for a user specified, used to update the mapping and to be logged into event
285
+ */
286
+ function __setRole(address operator, uint256 requestedRole, uint256 assignedRole) private {
287
+ // assign the role to the operator
288
+ userRoles[operator] = assignedRole;
289
+
290
+ // fire an event
291
+ emit RoleUpdated(operator, requestedRole, assignedRole);
292
+ }
293
+
294
+ /**
295
+ * @dev Checks if role `actual` contains all the permissions required `required`
296
+ *
297
+ * @param actual existent role
298
+ * @param required required role
299
+ * @return true if actual has required role (all permissions), false otherwise
300
+ */
301
+ function __hasRole(uint256 actual, uint256 required) private pure returns (bool) {
302
+ // check the bitmask for the role required and return the result
303
+ return actual & required == required;
304
+ }
305
+ }