Skip to content

Commit f7feef7

Browse files
Krishang NadgaudaKrishang Nadgauda
authored andcommitted
begin Permissions implementation
1 parent 77ab8b3 commit f7feef7

File tree

5 files changed

+272
-0
lines changed

5 files changed

+272
-0
lines changed

contracts/feature/Context.sol

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: MIT
2+
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
3+
4+
pragma solidity ^0.8.0;
5+
6+
/**
7+
* @dev Provides information about the current execution context, including the
8+
* sender of the transaction and its data. While these are generally available
9+
* via msg.sender and msg.data, they should not be accessed in such a direct
10+
* manner, since when dealing with meta-transactions the account sending and
11+
* paying for execution may not be the actual sender (as far as an application
12+
* is concerned).
13+
*
14+
* This contract is only required for intermediate, library-like contracts.
15+
*/
16+
abstract contract Context {
17+
function _msgSender() internal view virtual returns (address) {
18+
return msg.sender;
19+
}
20+
21+
function _msgData() internal view virtual returns (bytes calldata) {
22+
return msg.data;
23+
}
24+
}

contracts/feature/Permissions.sol

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
import "./interface/IPermissions.sol";
5+
import "./Context.sol";
6+
import "../lib/Strings.sol";
7+
8+
contract Permissions is IPermissions, Context {
9+
10+
mapping(bytes32 => mapping(address => bool)) public hasRole;
11+
mapping(bytes32 => bytes32) public getRoleAdmin;
12+
13+
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
14+
15+
function grantRole(bytes32 role, address account) external {
16+
require(
17+
hasRole[getRoleAdmin[role]][_msgSender()],
18+
"Not role admin."
19+
);
20+
21+
hasRole[role][account] = true;
22+
23+
emit RoleGranted(role, account, _msgSender());
24+
}
25+
26+
function revokeRole(bytes32 role, address account) external {
27+
require(
28+
hasRole[getRoleAdmin[role]][_msgSender()],
29+
"Not role admin."
30+
);
31+
32+
delete hasRole[role][account];
33+
34+
emit RoleRevoked(role, account, _msgSender());
35+
}
36+
37+
function renounceRole(bytes32 role, address account) external {
38+
require(
39+
_msgSender() == account,
40+
"Can only renounce for self"
41+
);
42+
43+
delete hasRole[role][account];
44+
45+
emit RoleRevoked(role, account, _msgSender());
46+
}
47+
48+
function _checkRole(bytes32 role, address account) internal view virtual {
49+
if (!hasRole[role][account]) {
50+
revert(
51+
string(
52+
abi.encodePacked(
53+
"AccessControl: account ",
54+
Strings.toHexString(uint160(account), 20),
55+
" is missing role ",
56+
Strings.toHexString(uint256(role), 32)
57+
)
58+
)
59+
);
60+
}
61+
}
62+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: MIT
2+
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
3+
4+
pragma solidity ^0.8.0;
5+
6+
/**
7+
* @dev External interface of AccessControl declared to support ERC165 detection.
8+
*/
9+
interface IPermissions {
10+
/**
11+
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
12+
*
13+
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
14+
* {RoleAdminChanged} not being emitted signaling this.
15+
*
16+
* _Available since v3.1._
17+
*/
18+
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
19+
20+
/**
21+
* @dev Emitted when `account` is granted `role`.
22+
*
23+
* `sender` is the account that originated the contract call, an admin role
24+
* bearer except when using {AccessControl-_setupRole}.
25+
*/
26+
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
27+
28+
/**
29+
* @dev Emitted when `account` is revoked `role`.
30+
*
31+
* `sender` is the account that originated the contract call:
32+
* - if using `revokeRole`, it is the admin role bearer
33+
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
34+
*/
35+
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
36+
37+
/**
38+
* @dev Returns `true` if `account` has been granted `role`.
39+
*/
40+
function hasRole(bytes32 role, address account) external view returns (bool);
41+
42+
/**
43+
* @dev Returns the admin role that controls `role`. See {grantRole} and
44+
* {revokeRole}.
45+
*
46+
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
47+
*/
48+
function getRoleAdmin(bytes32 role) external view returns (bytes32);
49+
50+
/**
51+
* @dev Grants `role` to `account`.
52+
*
53+
* If `account` had not been already granted `role`, emits a {RoleGranted}
54+
* event.
55+
*
56+
* Requirements:
57+
*
58+
* - the caller must have ``role``'s admin role.
59+
*/
60+
function grantRole(bytes32 role, address account) external;
61+
62+
/**
63+
* @dev Revokes `role` from `account`.
64+
*
65+
* If `account` had been granted `role`, emits a {RoleRevoked} event.
66+
*
67+
* Requirements:
68+
*
69+
* - the caller must have ``role``'s admin role.
70+
*/
71+
function revokeRole(bytes32 role, address account) external;
72+
73+
/**
74+
* @dev Revokes `role` from the calling account.
75+
*
76+
* Roles are often managed via {grantRole} and {revokeRole}: this function's
77+
* purpose is to provide a mechanism for accounts to lose their privileges
78+
* if they are compromised (such as when a trusted device is misplaced).
79+
*
80+
* If the calling account had been granted `role`, emits a {RoleRevoked}
81+
* event.
82+
*
83+
* Requirements:
84+
*
85+
* - the caller must be `account`.
86+
*/
87+
function renounceRole(bytes32 role, address account) external;
88+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: MIT
2+
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
3+
4+
pragma solidity ^0.8.0;
5+
6+
import "./IPermissions.sol";
7+
8+
/**
9+
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
10+
*/
11+
interface IPermissionsEnumerable is IPermissions {
12+
/**
13+
* @dev Returns one of the accounts that have `role`. `index` must be a
14+
* value between 0 and {getRoleMemberCount}, non-inclusive.
15+
*
16+
* Role bearers are not sorted in any particular way, and their ordering may
17+
* change at any point.
18+
*
19+
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
20+
* you perform all queries on the same block. See the following
21+
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
22+
* for more information.
23+
*/
24+
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
25+
26+
/**
27+
* @dev Returns the number of accounts that have `role`. Can be used
28+
* together with {getRoleMember} to enumerate all bearers of a role.
29+
*/
30+
function getRoleMemberCount(bytes32 role) external view returns (uint256);
31+
}

contracts/lib/Strings.sol

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: MIT
2+
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
3+
4+
pragma solidity ^0.8.0;
5+
6+
/**
7+
* @dev String operations.
8+
*/
9+
library Strings {
10+
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
11+
12+
/**
13+
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
14+
*/
15+
function toString(uint256 value) internal pure returns (string memory) {
16+
// Inspired by OraclizeAPI's implementation - MIT licence
17+
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
18+
19+
if (value == 0) {
20+
return "0";
21+
}
22+
uint256 temp = value;
23+
uint256 digits;
24+
while (temp != 0) {
25+
digits++;
26+
temp /= 10;
27+
}
28+
bytes memory buffer = new bytes(digits);
29+
while (value != 0) {
30+
digits -= 1;
31+
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
32+
value /= 10;
33+
}
34+
return string(buffer);
35+
}
36+
37+
/**
38+
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
39+
*/
40+
function toHexString(uint256 value) internal pure returns (string memory) {
41+
if (value == 0) {
42+
return "0x00";
43+
}
44+
uint256 temp = value;
45+
uint256 length = 0;
46+
while (temp != 0) {
47+
length++;
48+
temp >>= 8;
49+
}
50+
return toHexString(value, length);
51+
}
52+
53+
/**
54+
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
55+
*/
56+
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
57+
bytes memory buffer = new bytes(2 * length + 2);
58+
buffer[0] = "0";
59+
buffer[1] = "x";
60+
for (uint256 i = 2 * length + 1; i > 1; --i) {
61+
buffer[i] = _HEX_SYMBOLS[value & 0xf];
62+
value >>= 4;
63+
}
64+
require(value == 0, "Strings: hex length insufficient");
65+
return string(buffer);
66+
}
67+
}

0 commit comments

Comments
 (0)