-
Notifications
You must be signed in to change notification settings - Fork 2
/
KeyInfrastructure.sol
121 lines (106 loc) · 3.44 KB
/
KeyInfrastructure.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
/**
* @title KeyInfrastructure
* @dev Contract to manage keys using a 3-tiered key relationship.
* Each tier specifies a role that can only be managed by the tier above it.
* In order from 'coldest' to 'hottest' keys, these roles are:
* - Root key
* - Intermediate key
* - Active Issuer(s)
*/
contract KeyInfrastructure {
address internal immutable _root;
address internal _intermediate;
address[] internal _activeIssuers;
mapping(address => bool) internal _isActiveIssuer;
event IntermediateRotated(address newKey);
event IssuerActivated(address activatedIssuer);
event IssuerDeactivated(address deactivatedIssuer);
modifier onlyRoot() {
// MBR -> Must be root
require(msg.sender == _root, "unauthorised: MBR");
_;
}
modifier onlyIntermediate() {
// MBI -> Must be intermediate
require(msg.sender == _intermediate, "unauthorised: MBI");
_;
}
constructor(address root) {
_root = root;
}
/**
* @dev Rotates the Intermediate key.
* Only callable by the Root key.
*/
function rotateIntermediate(address newIntermediate) public onlyRoot {
_intermediate = newIntermediate;
emit IntermediateRotated(newIntermediate);
}
/**
* @dev Adds addresses to the list of Active Issuers.
* Only callable by the Intermediate key.
*/
function activateIssuers(address[] calldata newIssuers) public onlyIntermediate {
for (uint256 i = 0; i < newIssuers.length; i++) {
address newKey = newIssuers[i];
if (!_isActiveIssuer[newKey]) {
_addToActiveIssuers(newKey);
emit IssuerActivated(newKey);
}
}
}
/**
* @dev Remove `issuers` from the list of Active Issuers.
* Only callable by the Intermediate key.
*/
function deactivateIssuers(address[] calldata issuers) public onlyIntermediate {
for (uint256 i = 0; i < issuers.length; i++) {
address oldKey = issuers[i];
if (_isActiveIssuer[oldKey]) {
_removeFromActiveIssuers(oldKey);
emit IssuerDeactivated(oldKey);
}
}
}
/**
* @dev Returns the Root key.
*/
function getRootKey() public view returns (address) {
return _root;
}
/**
* @dev Returns the Intermediate key.
*/
function getIntermediateKey() public view returns (address) {
return _intermediate;
}
/**
* @dev Returns the list of Active Issuers.
*/
function getActiveIssuers() public view returns (address[] memory) {
return _activeIssuers;
}
/**
* @dev Returns whether a given address is registered as Active Issuer.
*/
function isActiveIssuer(address addr) public view returns (bool) {
return _isActiveIssuer[addr];
}
function _addToActiveIssuers(address addr) internal {
_isActiveIssuer[addr] = true;
_activeIssuers.push(addr);
}
function _removeFromActiveIssuers(address addr) internal {
_isActiveIssuer[addr] = false;
for (uint256 i = 0; i < _activeIssuers.length; i++) {
address issuer = _activeIssuers[i];
if (addr == issuer) {
_activeIssuers[i] = _activeIssuers[_activeIssuers.length - 1];
_activeIssuers.pop();
break;
}
}
}
}