-
Notifications
You must be signed in to change notification settings - Fork 4
/
Moduleable.sol
135 lines (120 loc) · 4.28 KB
/
Moduleable.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "../interfaces/IModuleContract.sol";
/**
* @title Moduleable
* @dev Base contract which allows children to add or remove module contracts
*/
contract Moduleable is Ownable {
/*----------- Globals -----------*/
mapping (uint8 => address[]) public modules;
/*----------- Events -----------*/
event LogModuleAdded(
uint8 moduleType,
bytes32 moduleName,
address moduleAddress,
uint256 timestamp
);
event LogModuleRemoved(
uint8 moduleType,
address moduleAddress,
uint256 timestamp
);
event LogModuleIndexUpdate(
uint256 moduleIndex,
uint8 moduleType,
address moduleAddress,
uint256 timestamp
);
/*----------- Methods -----------*/
/**
* @notice Function used to attach the module to the Asset Token
* @param _moduleAddress Contract address of the module that needs to be attached
*/
function addModule(
IModuleContract _moduleAddress
) external onlyOwner {
// Add to Asset Token module map
IModuleContract moduleContract = IModuleContract(_moduleAddress);
uint8 moduleType = moduleContract.getType();
bytes32 moduleName = moduleContract.getName();
// Resolves the case where modules were added, then all removed, and new modules added.
if (modules[moduleType].length == 1 && modules[moduleType][0] == address(0)) {
modules[moduleType][0] = _moduleAddress;
} else {
modules[moduleType].push(_moduleAddress);
}
// Emit log event
emit LogModuleAdded(
moduleType,
moduleName,
_moduleAddress,
block.timestamp // solhint-disable-line not-rely-on-time
);
// Emit Index event
emit LogModuleIndexUpdate(
modules[moduleType].length - 1,
moduleType,
_moduleAddress,
block.timestamp // solhint-disable-line not-rely-on-time
);
}
/**
* @notice Removes a module attached to the Asset Token
* @param _moduleType is which type of module we are trying to remove
* @param _moduleIndex is the index of the module within the chosen type
*/
function removeModule(
uint8 _moduleType,
uint8 _moduleIndex
) external onlyOwner {
require(
_moduleIndex < modules[_moduleType].length,
"Module index is out of range"
);
require(
modules[_moduleType][_moduleIndex] != address(0),
"Module contract address should not be 0x"
);
// Emit the event before removing the index
emit LogModuleRemoved(
_moduleType,
modules[_moduleType][_moduleIndex],
block.timestamp // solhint-disable-line not-rely-on-time
);
uint lastIndex = modules[_moduleType].length - 1;
if (lastIndex == 0) {
modules[_moduleType][0] = address(0);
} else {
modules[_moduleType][_moduleIndex] = modules[_moduleType][lastIndex];
delete modules[_moduleType][lastIndex];
modules[_moduleType].length = lastIndex;
if (_moduleIndex != lastIndex) {
// Emit an event describing the new index of the moved module
emit LogModuleIndexUpdate(
_moduleIndex,
_moduleType,
modules[_moduleType][_moduleIndex],
block.timestamp // solhint-disable-line not-rely-on-time
);
}
}
}
/**
* @notice Returns module name and address for a given type and index
* @param _moduleType is the type of module we are searching for
* @param _moduleIndex is the index of the module within the chosen type
* @return bytes32 is the name of the module
* @return address is the address of the module
*/
function getModuleByTypeAndIndex(
uint8 _moduleType,
uint _moduleIndex
) external view returns (address) {
if (modules[_moduleType].length > 0 && _moduleIndex < modules[_moduleType].length) {
return modules[_moduleType][_moduleIndex];
} else {
return (address(0));
}
}
}