Created
January 4, 2019 09:31
-
-
Save roderik/5ebc445431eb4bb58d2770ca1de10ee1 to your computer and use it in GitHub Desktop.
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.4.25; | |
// File: @settlemint/solidity-mint/contracts/authentication/interfaces/IRoleRegistry.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
/** | |
* @title RoleRegistry | |
* @dev The RoleRegistry contract defines the methods and data structures to | |
* record if addresses have certain roles or not. | |
*/ | |
contract IRoleRegistry { | |
event Designated(address _address); | |
event Discharged(address _address); | |
event RoleRegistryCreated(address _address); | |
/** | |
* @dev Checks if an address has a certain role | |
* @param _address The address to check for the role. | |
* @return A boolean that is True if the address has the role. | |
*/ | |
function hasRole(address _address) public view returns (bool hasTheRole); | |
/** | |
* @dev Gives the role to an address | |
* @param _address The address to designate the role to. | |
*/ | |
function designate(address _address) public; | |
/** | |
* @dev Removes the role from an address | |
* @param _address The address to discharge fromn the role. | |
*/ | |
function discharge(address _address) public; | |
} | |
// File: @settlemint/solidity-mint/contracts/authentication/GateKeeper.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
contract GateKeeper { | |
bytes32 constant public CREATE_PERMISSIONS_ROLE = bytes32("CREATE_PERMISSIONS_ROLE"); | |
bytes32 constant public ADD_ROLEREGISTRY_ROLE = bytes32("ADD_ROLEREGISTRY_ROLE"); | |
event SetPermission(address indexed entity, address indexed contractAddress, bytes32 indexed role, bool allowed); | |
event ChangePermissionManager(address indexed contractAddress, bytes32 indexed role, address indexed manager); | |
// whether a certain entity has a permission | |
mapping (address => mapping (address => mapping (bytes32 => bool))) permissions; | |
// who is the manager of a permission | |
mapping (address => mapping (bytes32 => address)) permissionManager; | |
// a mapping of roles to the address of their correspending role registry | |
mapping(bytes32 => address) roleToRoleRegistry; | |
// a list of all RoleRegistries | |
IRoleRegistry[] roleRegistries; | |
modifier onlyPermissionManager(address _contract, bytes32 role) { | |
require(msg.sender == getPermissionManager(_contract, role), "Sender is not the permission manager"); | |
_; | |
} | |
modifier auth(bytes32 _role) { | |
require(hasPermission(msg.sender, address(this), _role), "Sender does not have the correct permissions"); | |
_; | |
} | |
constructor() public { | |
_createPermission( | |
msg.sender, | |
address(this), | |
CREATE_PERMISSIONS_ROLE, | |
msg.sender | |
); | |
_createPermission( | |
msg.sender, | |
address(this), | |
ADD_ROLEREGISTRY_ROLE, | |
msg.sender | |
); | |
} | |
function addRoleRegistry(address roleRegisty) external auth(ADD_ROLEREGISTRY_ROLE) { | |
roleRegistries.push(IRoleRegistry(roleRegisty)); | |
} | |
/** | |
* @dev Creates a permission that wasn't previously set. Access is limited by the ACL. | |
* if a created permission is removed it is possible to reset it with createPermission. | |
* @notice Create a new permission granting `_entity` the ability to perform actions of role `_role` on `_contract` (setting `_manager` as parent) | |
* @param _entity Address of the whitelisted entity that will be able to perform the role, this can be a user or a roleregistry | |
* @param _contract Address of the app in which the role will be allowed (requires app to depend on kernel for ACL) | |
* @param _role Identifier for the group of actions in app given access to perform | |
* @param _manager Address of the entity that will be able to grant and revoke the permission further. | |
*/ | |
function createPermission( | |
address _entity, | |
address _contract, | |
bytes32 _role, | |
address _manager | |
) | |
public | |
auth(CREATE_PERMISSIONS_ROLE) | |
{ | |
_createPermission( | |
_entity, | |
_contract, | |
_role, | |
_manager | |
); | |
} | |
/** | |
* @dev Grants a permission if allowed. This requires `msg.sender` to be the permission manager | |
* @notice Grants `_entity` the ability to perform actions of role `_role` on `_contract` | |
* @param _entity Address of the whitelisted entity that will be able to perform the role | |
* @param _contract Address of the app in which the role will be allowed (requires app to depend on kernel for ACL) | |
* @param _role Identifier for the group of actions in app given access to perform | |
*/ | |
function grantPermission(address _entity, address _contract, bytes32 _role) | |
public | |
onlyPermissionManager(_contract, _role) | |
{ | |
_setPermission( | |
_entity, | |
_contract, | |
_role, | |
true | |
); | |
} | |
/** | |
* @dev Revokes permission if allowed. This requires `msg.sender` to be the parent of the permission | |
* @notice Revokes `_entity` the ability to perform actions of role `_role` on `_contract` | |
* @param _entity Address of the whitelisted entity that will be revoked access | |
* @param _contract Address of the app in which the role is revoked | |
* @param _role Identifier for the group of actions in app given access to perform | |
*/ | |
function revokePermission(address _entity, address _contract, bytes32 _role) | |
public | |
onlyPermissionManager(_contract, _role) | |
{ | |
_setPermission( | |
_entity, | |
_contract, | |
_role, | |
false | |
); | |
} | |
/** | |
* @notice Sets `_newManager` as the manager of the permission `_role` in `_contract` | |
* @param _newManager Address for the new manager | |
* @param _contract Address of the app in which the permission management is being transferred | |
* @param _role Identifier for the group of actions in app given access to perform | |
*/ | |
function setPermissionManager(address _newManager, address _contract, bytes32 _role) | |
public | |
onlyPermissionManager(_contract, _role) | |
{ | |
_setPermissionManager(_newManager, _contract, _role); | |
} | |
/** | |
* @dev Get manager address for permission | |
* @param _contract Address of the app | |
* @param _role Identifier for a group of actions in app | |
* @return address of the manager for the permission | |
*/ | |
function getPermissionManager(address _contract, bytes32 _role) public view returns (address) { | |
return permissionManager[_contract][_role]; | |
} | |
/** | |
* @dev Function called by apps to check ACL on kernel or to check permission statu | |
* @param _entity Sender of the original call | |
* @param _contract Address of the app | |
* @param _role Identifier for a group of actions in app | |
* @return boolean indicating whether the ACL allows the role or not | |
*/ | |
function hasPermission(address _entity, address _contract, bytes32 _role) public view returns (bool) { | |
// the address passed in has the permissions themselves | |
bool personalPermission = permissions[_entity][_contract][_role]; | |
if (personalPermission) { | |
return personalPermission; | |
} | |
// or we will check if any of the role registries have the permission | |
for (uint256 counter = 0; counter < roleRegistries.length; counter++) { | |
address registry = address(roleRegistries[counter]); | |
bool registryPermission = permissions[registry][_contract][_role]; | |
if (registryPermission) { | |
if (roleRegistries[counter].hasRole(_entity)) { | |
return true; | |
} | |
} | |
} | |
// if, not, deny! | |
return false; | |
} | |
/** | |
* @dev Function called to retrieve the role registry for a given role | |
* @param _role Identifier for the role mapped to a role registry | |
* @return address of the role registry that corresponds to the role | |
*/ | |
function getRoleRegistryAddress(bytes32 _role) public view returns (address) { | |
return roleToRoleRegistry[_role]; | |
} | |
/** | |
* @dev Function called to set the role registry for a given role | |
* @param _role Identifier for the role mapped to a role registry | |
* @param _address address of the role registry to put into the store | |
*/ | |
function setRoleRegistryAddress(bytes32 _role, address _address) public auth(ADD_ROLEREGISTRY_ROLE) { | |
roleToRoleRegistry[_role] = _address; | |
} | |
/** | |
* @dev Internal createPermission for access inside the gatekeeper (on instantiation) | |
*/ | |
function _createPermission( | |
address _entity, | |
address _contract, | |
bytes32 _role, | |
address _manager | |
) | |
internal | |
{ | |
require(permissionManager[_contract][_role] == 0, "only allow permission creation when it has no manager (hasn't been created before)"); | |
_setPermission( | |
_entity, | |
_contract, | |
_role, | |
true | |
); | |
_setPermissionManager(_manager, _contract, _role); | |
} | |
/** | |
* @dev Internal function called to actually save the permission | |
*/ | |
function _setPermission( | |
address _entity, | |
address _contract, | |
bytes32 _role, | |
bool _allowed | |
) | |
internal | |
{ | |
permissions[_entity][_contract][_role] = _allowed; | |
emit SetPermission( | |
_entity, | |
_contract, | |
_role, | |
_allowed | |
); | |
} | |
/** | |
* @dev Internal function that sets management | |
*/ | |
function _setPermissionManager(address _newManager, address _contract, bytes32 _role) internal { | |
require(_newManager > 0, "_newManager should be a real address"); | |
permissionManager[_contract][_role] = _newManager; | |
emit ChangePermissionManager(_contract, _role, _newManager); | |
} | |
} | |
// File: @settlemint/solidity-mint/contracts/utility/conversions/Converter.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
contract Converter { | |
function addressToString(address x) internal pure returns (string) { | |
bytes memory b = new bytes(20); | |
for (uint i = 0; i < 20; i++) { | |
b[i] = byte(uint8(uint(x) / (2**(8*(19 - i))))); | |
} | |
return string(b); | |
} | |
function bytes32ToString(bytes32 x) internal pure returns (string) { | |
bytes memory bytesString = new bytes(32); | |
uint charCount = 0; | |
for (uint j = 0; j < 32; j++) { | |
byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); | |
if (char != 0) { | |
bytesString[charCount] = char; | |
charCount++; | |
} | |
} | |
bytes memory bytesStringTrimmed = new bytes(charCount); | |
for (j = 0; j < charCount; j++) { | |
bytesStringTrimmed[j] = bytesString[j]; | |
} | |
return string(bytesStringTrimmed); | |
} | |
} | |
// File: @settlemint/solidity-mint/contracts/authentication/Secured.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
contract Secured is Converter { | |
GateKeeper public gateKeeper; | |
modifier auth(bytes32 _role) { | |
require( | |
canPerform(msg.sender, _role), | |
"Sender do not have the correct role"); | |
_; | |
} | |
constructor(address _gateKeeper) public { | |
gateKeeper = GateKeeper(_gateKeeper); | |
} | |
function canPerform(address _sender, bytes32 _role) internal view returns (bool) { | |
return address(gateKeeper) == 0 || gateKeeper.hasPermission(_sender, address(this), _role); | |
} | |
} | |
// File: @settlemint/solidity-mint/contracts/utility/syncing/Syncable.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
/** | |
* The listable item should also implement | |
* @dev function getInfo() constant public returns (bytes32 _productID, bytes32 _issuerProductID, bytes32 _productPayoffCode, address _currency, uint256 _totalSupply) { | |
*/ | |
contract Syncable { | |
function getIndexLength() public view returns (uint length); | |
// Waiting for the time we can return structs from functions! | |
//function getByIndex(uint index) constant public returns (address key, bool hasRole){ | |
//function getByKey(address _key) constant public returns (address key, bool hasRole){ | |
} | |
// File: @settlemint/solidity-mint/contracts/authentication/RoleRegistry.sol | |
/** | |
* Copyright (C) SettleMint NV - All Rights Reserved | |
* | |
* Use of this file is strictly prohibited without an active license agreement. | |
* Distribution of this file, via any medium, is strictly prohibited. | |
* | |
* For license inquiries, contact [email protected] | |
*/ | |
pragma solidity ^0.4.24; | |
pragma experimental ABIEncoderV2; | |
/** | |
* @title RoleRegistry | |
* @dev The RoleRegistry contract defines the methods and data structures to | |
* record if addresses have certain roles or not. | |
*/ | |
contract RoleRegistry is IRoleRegistry, Syncable, Secured { | |
bytes32 constant public DESIGNATE_ROLE = bytes32("DESIGNATE_ROLE"); | |
struct RoleHolderContainer { | |
bool roleDesignated; | |
uint256 creationDate; | |
} | |
mapping(address => RoleHolderContainer) private roleHolders; | |
address[] private roleHoldersIndex; | |
event Designated(address _address); | |
event Discharged(address _address); | |
event RoleRegistryCreated(address _address); | |
constructor(address _gateKeeper) Secured(_gateKeeper) public { | |
emit RoleRegistryCreated(this); | |
} | |
/** | |
* @notice Returns a list of all the holders of this role. | |
*/ | |
function getRoleHolders() public view returns(address[] allRoleHolders) { | |
return roleHoldersIndex; | |
} | |
/** | |
* @dev Checks if an address has a certain role | |
* @param _address The address to check for the role. | |
* @return A boolean that is True if the address has the role. | |
*/ | |
function hasRole(address _address) public view returns (bool hasTheRole) { | |
hasTheRole = roleHolders[_address].roleDesignated; | |
} | |
/** | |
* @dev Gives the role to an address | |
* @param _address The address to designate the role to. | |
*/ | |
function designate(address _address) public auth(DESIGNATE_ROLE) { | |
if (roleHolders[_address].creationDate == 0) { | |
roleHoldersIndex.push(_address); | |
roleHolders[_address].creationDate = now; | |
} | |
roleHolders[_address].roleDesignated = true; | |
emit Designated(_address); | |
} | |
/** | |
* @dev Removes the role from an address | |
* @param _address The address to discharge fromn the role. | |
*/ | |
function discharge(address _address) public auth(DESIGNATE_ROLE) { | |
require(roleHolders[_address].creationDate > 0, "This address was never designated to this role"); | |
uint i = 0; | |
while (roleHoldersIndex[i] != _address) { | |
i++; | |
} | |
for (uint j = i; j<roleHoldersIndex.length-1; j++) { | |
roleHoldersIndex[j] = roleHoldersIndex[j+1]; | |
} | |
roleHoldersIndex.length--; | |
roleHolders[_address].roleDesignated = false; | |
emit Discharged(_address); | |
} | |
/** | |
* @dev Returns the length of the index array | |
* @return the amount of items in the index array | |
*/ | |
function getIndexLength() public view returns (uint length) { | |
length = roleHoldersIndex.length; | |
} | |
/** | |
* @dev Returns the information for the key on a certain index | |
* @param _index The index of the key in the key array | |
* @return the information for the key on a certain index | |
*/ | |
function getByIndex(uint _index) public view returns (address key, bool hasTheRole) { | |
key = roleHoldersIndex[_index]; | |
hasTheRole = roleHolders[roleHoldersIndex[_index]].roleDesignated; | |
} | |
/** | |
* @dev Returns the information for the key | |
* @param _key The key to get the info for | |
* @return the information for the key | |
*/ | |
function getByKey(address _key) public view returns (address key, bool hasTheRole) { | |
key = _key; | |
hasTheRole = roleHolders[_key].roleDesignated; | |
} | |
} | |
// File: contracts/Administrator/AdministratorRegistry.sol | |
/** | |
* @title AdministratorRegistry | |
* @dev Contains all the administrators of this system. | |
*/ | |
contract AdministratorRegistry is RoleRegistry { | |
bytes32 constant public ROLE = "ADMIN_ROLE"; | |
constructor(address _gateKeeper) public RoleRegistry(_gateKeeper) {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment