@lazy-sol/access-control 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }