-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathUpgradeableAccessControlCore.sol
88 lines (85 loc) · 4.19 KB
/
UpgradeableAccessControlCore.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;
import "./InitializableAccessControlCore.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
/**
* @title Upgradeable Role-based Access Control Core (U-RBAC-C) // ERC1967Proxy
*
* @notice Access control smart contract provides an API to check
* if a specific operation is permitted globally and/or
* if a particular user has a permission to execute it.
*
* @notice This contract is inherited by other contracts requiring the role-based access control (RBAC)
* protection for the restricted access functions
*
* @notice It deals with two main entities: features and roles.
*
* @notice Features are designed to be used to enable/disable public functions
* of the smart contract (used by a wide audience).
* @notice User roles are designed to control the access to restricted functions
* of the smart contract (used by a limited set of maintainers).
*
* @notice Terms "role", "permissions" and "set of permissions" have equal meaning
* in the documentation text and may be used interchangeably.
* @notice Terms "permission", "single permission" implies only one permission bit set.
*
* @notice Access manager is a special role which allows to grant/revoke other roles.
* Access managers can only grant/revoke permissions which they have themselves.
* As an example, access manager with no other roles set can only grant/revoke its own
* access manager permission and nothing else.
*
* @notice Access manager permission should be treated carefully, as a super admin permission:
* Access manager with even no other permission can interfere with another account by
* granting own access manager permission to it and effectively creating more powerful
* permission set than its own.
*
* @dev Both current and OpenZeppelin AccessControl implementations feature a similar API
* to check/know "who is allowed to do this thing".
* @dev Zeppelin implementation is more flexible:
* - it allows setting unlimited number of roles, while current is limited to 256 different roles
* - it allows setting an admin for each role, while current allows having only one global admin
* @dev Current implementation is more lightweight:
* - it uses only 1 bit per role, while Zeppelin uses 256 bits
* - it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows
* setting only one role in a single transaction
*
* @dev This smart contract is designed to be inherited by other
* smart contracts which require access control management capabilities.
*
* @dev Access manager permission has a bit 255 set.
* This bit must not be used by inheriting contracts for any other permissions/features.
*
* @dev This is an upgradeable version of the RBAC, based on Zeppelin implementation for ERC1967,
* see https://docs.openzeppelin.com/contracts/4.x/upgradeable
* see https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable
* see https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786
*
* @dev The 'core' version of the RBAC contract hides three rarely used external functions from the public ABI,
* making them internal and thus reducing the overall compiled implementation size.
* isFeatureEnabled() public -> _isFeatureEnabled() internal
* isSenderInRole() public -> _isSenderInRole() internal
* isOperatorInRole() public -> _isOperatorInRole() internal
*
* @custom:since 1.1.0
*
* @author Basil Gorin
*/
abstract contract UpgradeableAccessControlCore is InitializableAccessControlCore, UUPSUpgradeable {
/**
* @notice Returns an address of the implementation smart contract,
* see ERC1967Upgrade._getImplementation()
*
* @return the current implementation address
*/
function getImplementation() external view virtual returns (address) {
// delegate to `ERC1967Upgrade._getImplementation()`
return _getImplementation();
}
/**
* @inheritdoc UUPSUpgradeable
*/
function _authorizeUpgrade(address) internal virtual override {
// caller must have a permission to upgrade the contract
_requireSenderInRole(ROLE_UPGRADE_MANAGER);
}
}