Last active
May 10, 2022 09:29
-
-
Save nventuro/ac42bd936f678ebf55c4c0c4a4ee4c72 to your computer and use it in GitHub Desktop.
Access Control Proposal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
import "./IAccessControl.sol"; | |
import "../utils/EnumerableSet.sol"; | |
abstract contract AccessControl is IAccessControl { | |
using EnumerableSet for EnumerableSet.AddressSet; | |
struct Role { | |
EnumerableSet.AddressSet members; | |
bytes32 admin; | |
} | |
mapping (bytes32 => Role) _roles; | |
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x0000000000000000000000000000000000000000; | |
function hasRole(bytes32 roleId, address account) | |
public view returns (bool) | |
{ | |
return _roles[roleId].members.contains(account); | |
} | |
function getRoleMembersCount(bytes32 roleId) | |
external | |
view | |
returns (uint256) | |
{ | |
return _roles[roleId].members.length(); | |
} | |
function getRoleMember(bytes32 roleId, uint256 index) | |
external | |
view | |
returns (address) | |
{ | |
return _roles[roleId].members.get(index); | |
} | |
function getRoleAdmin(bytes32 roleId) | |
external | |
view | |
returns (bytes32) | |
{ | |
return _roles[roleId].admin; | |
} | |
function grantRole(bytes32 roleId, address account) external { | |
require(hasRole(_roles[roleId].admin, msg.sender), | |
"AccessControl: sender must be an admin to grant" | |
); | |
_grantRole(roleId, account); | |
} | |
function revokeRole(bytes32 roleId, address account) external { | |
require(hasRole(_roles[roleId].admin, msg.sender), | |
"AccessControl: sender must be an admin to revoke" | |
); | |
_revokeRole(roleId, account); | |
} | |
function renounceRole(bytes32 roleId, address account) external { | |
require(account == msg.sender, | |
"AccessControl: can only renounce roles for self"); | |
require(hasRole(roleId, msg.sender), | |
"AccessControl: sender have the role to revoke" | |
); | |
_revokeRole(roleId, account); | |
} | |
function _grantRole(bytes32 roleId, address account) internal { | |
bool added = _roles[roleId].members.add(account); | |
require(added, "AccessControl: account already has role"); | |
} | |
function _revokeRole(bytes32 roleId, address account) internal { | |
bool removed = _roles[roleId].members.remove(account); | |
require(removed, "AccessControl: account does not have role"); | |
} | |
function _setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) internal { | |
_roles[roleId].admin = adminRoleId; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
import "../access/AccessControl.sol"; | |
import "../lifecycle/Pausable.sol"; | |
import "../token/ERC20/ERC20.sol"; | |
// Only the deployer of the token can ever mint tokens | |
contract ERC20SingleMinter is ERC20, AccessControl { | |
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | |
constructor () { | |
_grantRole(MINTER_ROLE, msg.sender); | |
} | |
function mint(address recipient, uint256 amount) external { | |
require(hasRole(msg.sender, MINTER_ROLE); | |
_mint(recipient, amount); | |
} | |
} | |
// The deployer of the token can grant and revoke the minter role | |
contract ERC20MultipleMinters is ERC20, AccessControl { | |
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | |
constructor () { | |
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | |
} | |
function mint(address recipient, uint256 amount) external { | |
require(hasRole(msg.sender, MINTER_ROLE); | |
_mint(recipient, amount); | |
} | |
} | |
// The deployer of the token can grant and revoke the minter and pauser roles | |
contract ERC20MintablePausable is ERC20, ERC20Pausable, AccessControl { | |
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | |
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); | |
constructor () { | |
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | |
} | |
function mint(address recipient, uint256 amount) external { | |
require(hasRole(msg.sender, MINTER_ROLE); | |
_mint(recipient, amount); | |
} | |
function pause() external { | |
require(hasRole(msg.sender, PAUSER_ROLE)); | |
_pause(); | |
} | |
} | |
// The deployer of the token can grant and revoke the permission to grant and | |
// revoke minter or pauser roles | |
contract ERC20MintablePausable is ERC20, ERC20Pausable, AccessControl { | |
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); | |
bytes32 public constant MINTER_ADMIN_ROLE = keccak256("MINTER_ADMIN_ROLE"); | |
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); | |
bytes32 public constant PAUSER_ADMIN_ROLE = keccak256("PAUSER_ADMIN_ROLE"); | |
constructor () { | |
_setRoleAdmin(MINTER_ROLE, MINTER_ADMIN_ROLE); | |
_setRoleAdmin(PAUSER_ROLE, PAUSER_ADMIN_ROLE); | |
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | |
} | |
function mint(address recipient, uint256 amount) external { | |
require(hasRole(msg.sender, MINTER_ROLE); | |
_mint(recipient, amount); | |
} | |
function pause() external { | |
require(hasRole(msg.sender, PAUSER_ROLE)); | |
_pause(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
interface IAccessControl { | |
// Queries | |
// Returns true if an account has a role | |
function hasRole(bytes32 roleId, address account) external view returns (bool); | |
// Returns the number of accounts with a role | |
function getRoleMembersCount(bytes32 roleId) external view returns (uint256); | |
// Returns an account with a role at index | |
function getRoleMember(bytes32 roleId, uint256 index) external view returns (address); | |
// Returns a role's admin role | |
function getRoleAdmin(bytes32 roleId) external view returns (bytes32); | |
// Operations | |
// Gives a role to an account. Caller must have its admin role | |
function grantRole(bytes32 roleId, address account) external; | |
// Revokes a role from an account. Caller must have its admin role | |
function revokeRole(bytes32 roleId, address account) external; | |
// Renounces a role. Caller must be `account` | |
function renounceRole(bytes32 roleId, address account) external; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment