0
# Access Control
1
2
Comprehensive access control mechanisms including single-owner patterns and flexible role-based access control systems for secure smart contract administration.
3
4
## Capabilities
5
6
### Single Owner Pattern
7
8
Simple ownership model with transfer and renouncement capabilities for contracts requiring single administrator access.
9
10
```solidity { .api }
11
/**
12
* @dev Contract module which provides a basic access control mechanism, where
13
* there is an account (an owner) that can be granted exclusive access to
14
* specific functions.
15
*/
16
abstract contract Ownable is Context {
17
/**
18
* @dev Sets the initial owner to the address provided by the deployer
19
*/
20
constructor(address initialOwner);
21
22
/**
23
* @dev Returns the address of the current owner
24
*/
25
function owner() public view virtual returns (address);
26
27
/**
28
* @dev Transfers ownership of the contract to a new account (`newOwner`)
29
* Can only be called by the current owner
30
*/
31
function transferOwnership(address newOwner) public virtual onlyOwner;
32
33
/**
34
* @dev Leaves the contract without owner. It will not be possible to call
35
* `onlyOwner` functions anymore. Can only be called by the current owner
36
*/
37
function renounceOwnership() public virtual onlyOwner;
38
39
/**
40
* @dev Throws if called by any account other than the owner
41
*/
42
modifier onlyOwner();
43
}
44
```
45
46
**Usage Example:**
47
48
```solidity
49
import "@openzeppelin/contracts/access/Ownable.sol";
50
51
contract MyContract is Ownable {
52
uint256 private _value;
53
54
constructor(address initialOwner) Ownable(initialOwner) {}
55
56
function setValue(uint256 newValue) public onlyOwner {
57
_value = newValue;
58
}
59
60
function getValue() public view returns (uint256) {
61
return _value;
62
}
63
}
64
```
65
66
### Two-Step Ownership Transfer
67
68
Enhanced ownership pattern that requires new owner acceptance to prevent accidental transfers to invalid addresses.
69
70
```solidity { .api }
71
/**
72
* @dev Contract module which provides access control mechanism, where
73
* there is an account (an owner) that can be granted exclusive access to
74
* specific functions, and ownership transfer is a two-step process.
75
*/
76
abstract contract Ownable2Step is Ownable {
77
/**
78
* @dev Returns the address of the pending owner
79
*/
80
function pendingOwner() public view virtual returns (address);
81
82
/**
83
* @dev Starts the ownership transfer of the contract to a new account
84
* Replaces the pending transfer if there is one
85
*/
86
function transferOwnership(address newOwner) public virtual override onlyOwner;
87
88
/**
89
* @dev The new owner accepts the ownership transfer
90
*/
91
function acceptOwnership() public virtual;
92
}
93
```
94
95
**Usage Example:**
96
97
```solidity
98
import "@openzeppelin/contracts/access/Ownable2Step.sol";
99
100
contract SecureContract is Ownable2Step {
101
constructor(address initialOwner) Ownable(initialOwner) {}
102
103
// Contract functions requiring ownership
104
function sensitiveOperation() public onlyOwner {
105
// Protected operation
106
}
107
}
108
109
// Transfer process:
110
// 1. Current owner calls transferOwnership(newOwnerAddress)
111
// 2. New owner calls acceptOwnership() to complete transfer
112
```
113
114
### Role-Based Access Control
115
116
Flexible role-based access control system supporting multiple roles with hierarchical administration.
117
118
```solidity { .api }
119
/**
120
* @dev Contract module that allows children to implement role-based access
121
* control mechanisms. Roles are referred to by their `bytes32` identifier.
122
*/
123
abstract contract AccessControl is Context, IAccessControl, ERC165 {
124
/**
125
* @dev Returns `true` if `account` has been granted `role`
126
*/
127
function hasRole(bytes32 role, address account) public view virtual returns (bool);
128
129
/**
130
* @dev Returns the admin role that controls `role`
131
*/
132
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32);
133
134
/**
135
* @dev Grants `role` to `account`
136
* If `account` had not been already granted `role`, emits a {RoleGranted} event
137
*/
138
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role));
139
140
/**
141
* @dev Revokes `role` from `account`
142
* If `account` had been granted `role`, emits a {RoleRevoked} event
143
*/
144
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role));
145
146
/**
147
* @dev Revokes `role` from the calling account
148
*/
149
function renounceRole(bytes32 role, address callerConfirmation) public virtual;
150
151
/**
152
* @dev Sets `adminRole` as ``role``'s admin role
153
* Internal function without access restriction
154
*/
155
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual;
156
157
/**
158
* @dev Grants `role` to `account`
159
* Internal function without access restriction
160
*/
161
function _grantRole(bytes32 role, address account) internal virtual;
162
163
/**
164
* @dev Revokes `role` from `account`
165
* Internal function without access restriction
166
*/
167
function _revokeRole(bytes32 role, address account) internal virtual;
168
169
/**
170
* @dev Modifier that checks that an account has a specific role
171
*/
172
modifier onlyRole(bytes32 role);
173
}
174
```
175
176
**Usage Example:**
177
178
```solidity
179
import "@openzeppelin/contracts/access/AccessControl.sol";
180
181
contract MyContract is AccessControl {
182
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
183
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
184
185
constructor(address defaultAdmin) {
186
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
187
}
188
189
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
190
// Minting logic
191
}
192
193
function burn(uint256 amount) public onlyRole(BURNER_ROLE) {
194
// Burning logic
195
}
196
197
function setupRoles(address minter, address burner) public onlyRole(DEFAULT_ADMIN_ROLE) {
198
_grantRole(MINTER_ROLE, minter);
199
_grantRole(BURNER_ROLE, burner);
200
}
201
}
202
```
203
204
### Enhanced Access Control Extensions
205
206
Advanced access control features including enumerable roles and default admin rules.
207
208
```solidity { .api }
209
// Enumerable Access Control - Track role members
210
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
211
/**
212
* @dev Returns one of the accounts that have `role`
213
*/
214
function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address);
215
216
/**
217
* @dev Returns the number of accounts that have `role`
218
*/
219
function getRoleMemberCount(bytes32 role) public view virtual returns (uint256);
220
221
/**
222
* @dev Returns an array of all accounts that have `role`
223
*/
224
function getRoleMembers(bytes32 role) public view virtual returns (address[] memory);
225
}
226
227
// Default Admin Rules - Enhanced admin role management
228
abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRules, AccessControl {
229
/**
230
* @dev Returns the address of the current default admin
231
*/
232
function defaultAdmin() public view virtual returns (address);
233
234
/**
235
* @dev Returns the address of the pending default admin
236
*/
237
function pendingDefaultAdmin() public view virtual returns (address);
238
239
/**
240
* @dev Returns the remaining time in seconds until the default admin transfer delay ends
241
*/
242
function defaultAdminDelayIncreaseWait() public view virtual returns (uint48);
243
244
/**
245
* @dev Starts a default admin transfer by setting a pending default admin
246
*/
247
function beginDefaultAdminTransfer(address newAdmin) public virtual onlyRole(DEFAULT_ADMIN_ROLE);
248
249
/**
250
* @dev Accepts the pending default admin transfer
251
*/
252
function acceptDefaultAdminTransfer() public virtual;
253
254
/**
255
* @dev Cancels a pending default admin transfer
256
*/
257
function cancelDefaultAdminTransfer() public virtual onlyRole(DEFAULT_ADMIN_ROLE);
258
}
259
```
260
261
### Access Manager
262
263
Advanced access management system for complex authorization scenarios with time-based controls.
264
265
```solidity { .api }
266
/**
267
* @dev AccessManager is a central contract to store the permissions of a system.
268
* It provides a flexible and modular access control mechanism.
269
*/
270
contract AccessManager is Context, Multicall, IAccessManager {
271
/**
272
* @dev Check if an account can perform an operation
273
*/
274
function canCall(address caller, address target, bytes4 selector) public view virtual returns (bool immediate, uint32 delay);
275
276
/**
277
* @dev Get the role of an account
278
*/
279
function getAccess(uint64 roleId, address account) public view virtual returns (uint48 since, uint32 currentDelay, uint32 pendingDelay, uint48 effect);
280
281
/**
282
* @dev Grant a role to an account
283
*/
284
function grantRole(uint64 roleId, address account, uint32 executionDelay) public virtual onlyAuthorized;
285
286
/**
287
* @dev Revoke a role from an account
288
*/
289
function revokeRole(uint64 roleId, address account) public virtual onlyAuthorized;
290
291
/**
292
* @dev Set the role required to call a function
293
*/
294
function setTargetFunctionRole(address target, bytes4[] calldata selectors, uint64 roleId) public virtual onlyAuthorized;
295
296
/**
297
* @dev Schedule an operation that is subject to a delay
298
*/
299
function schedule(address target, bytes calldata data, uint48 when) public virtual returns (bytes32 operationId);
300
301
/**
302
* @dev Execute a scheduled operation
303
*/
304
function execute(address target, bytes calldata data) public payable virtual returns (bytes32 operationId);
305
306
/**
307
* @dev Cancel a scheduled operation
308
*/
309
function cancel(address caller, address target, bytes calldata data) public virtual returns (bytes32 operationId);
310
}
311
```
312
313
## Access Control Interfaces
314
315
```solidity { .api }
316
// Core Access Control Interface
317
interface IAccessControl {
318
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
319
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
320
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
321
322
function hasRole(bytes32 role, address account) external view returns (bool);
323
function getRoleAdmin(bytes32 role) external view returns (bytes32);
324
function grantRole(bytes32 role, address account) external;
325
function revokeRole(bytes32 role, address account) external;
326
function renounceRole(bytes32 role, address callerConfirmation) external;
327
}
328
329
// Enumerable Access Control Interface
330
interface IAccessControlEnumerable is IAccessControl {
331
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
332
function getRoleMemberCount(bytes32 role) external view returns (uint256);
333
}
334
335
// Default Admin Rules Interface
336
interface IAccessControlDefaultAdminRules is IAccessControl {
337
event DefaultAdminTransferScheduled(address indexed newAdmin, uint48 acceptSchedule);
338
event DefaultAdminTransferCanceled();
339
event DefaultAdminDelayChangeScheduled(uint48 newDelay, uint48 effectSchedule);
340
event DefaultAdminDelayChangeCanceled();
341
342
function defaultAdmin() external view returns (address);
343
function pendingDefaultAdmin() external view returns (address, uint48);
344
function defaultAdminDelay() external view returns (uint48);
345
function pendingDefaultAdminDelay() external view returns (uint48, uint48);
346
function defaultAdminDelayIncreaseWait() external view returns (uint48);
347
}
348
349
// Access Manager Interface
350
interface IAccessManager {
351
event RoleGranted(uint64 indexed roleId, address indexed account, uint32 delay, uint48 since, address indexed caller);
352
event RoleRevoked(uint64 indexed roleId, address indexed account, address indexed caller);
353
event OperationScheduled(bytes32 indexed operationId, uint32 indexed nonce, uint48 schedule, address caller, address target, bytes data);
354
event OperationExecuted(bytes32 indexed operationId, uint32 indexed nonce, address caller, address target, bytes data);
355
event OperationCanceled(bytes32 indexed operationId, uint32 indexed nonce, address caller, address target, bytes data);
356
357
function canCall(address caller, address target, bytes4 selector) external view returns (bool allowed, uint32 delay);
358
function expiration() external view returns (uint32);
359
function minSetback() external view returns (uint32);
360
function isTargetClosed(address target) external view returns (bool);
361
function getTargetFunctionRole(address target, bytes4 selector) external view returns (uint64);
362
function getAccess(uint64 roleId, address account) external view returns (uint48, uint32, uint32, uint48);
363
function hasRole(uint64 roleId, address account) external view returns (bool, uint32);
364
}
365
```
366
367
## Common Patterns
368
369
### Basic Access Control Pattern
370
371
```solidity
372
import "@openzeppelin/contracts/access/Ownable.sol";
373
374
contract SimpleContract is Ownable {
375
mapping(address => bool) public authorized;
376
377
constructor(address initialOwner) Ownable(initialOwner) {}
378
379
function authorizeUser(address user) public onlyOwner {
380
authorized[user] = true;
381
}
382
383
function revokeUser(address user) public onlyOwner {
384
authorized[user] = false;
385
}
386
387
function protectedFunction() public {
388
require(authorized[msg.sender], "Not authorized");
389
// Function logic
390
}
391
}
392
```
393
394
### Multi-Role Pattern
395
396
```solidity
397
import "@openzeppelin/contracts/access/AccessControl.sol";
398
399
contract MultiRoleContract is AccessControl {
400
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
401
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
402
bytes32 public constant USER_ROLE = keccak256("USER_ROLE");
403
404
constructor(address defaultAdmin) {
405
_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
406
_grantRole(ADMIN_ROLE, defaultAdmin);
407
408
// Set role hierarchy
409
_setRoleAdmin(OPERATOR_ROLE, ADMIN_ROLE);
410
_setRoleAdmin(USER_ROLE, OPERATOR_ROLE);
411
}
412
413
function adminFunction() public onlyRole(ADMIN_ROLE) {
414
// Admin-only functionality
415
}
416
417
function operatorFunction() public onlyRole(OPERATOR_ROLE) {
418
// Operator functionality
419
}
420
421
function userFunction() public onlyRole(USER_ROLE) {
422
// User functionality
423
}
424
}
425
```
426
427
### Combined Access Control Pattern
428
429
```solidity
430
import "@openzeppelin/contracts/access/Ownable.sol";
431
import "@openzeppelin/contracts/access/AccessControl.sol";
432
433
contract HybridAccessContract is Ownable, AccessControl {
434
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
435
436
constructor(address initialOwner) Ownable(initialOwner) {
437
_grantRole(DEFAULT_ADMIN_ROLE, initialOwner);
438
}
439
440
// Owner can grant roles
441
function grantManagerRole(address account) public onlyOwner {
442
grantRole(MANAGER_ROLE, account);
443
}
444
445
// Managers can perform operations
446
function manageOperation() public onlyRole(MANAGER_ROLE) {
447
// Management functionality
448
}
449
450
// Owner retains ultimate control
451
function emergencyFunction() public onlyOwner {
452
// Emergency functionality
453
}
454
}
455
```