Skip to content

Commit 6684edb

Browse files
authored
Delegated Manager System internal audit fixes [SIM-179] (#23)
1 parent 7e75980 commit 6684edb

20 files changed

+681
-207
lines changed

contracts/ManagerCore.sol

Lines changed: 97 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ import { AddressArrayUtils } from "./lib/AddressArrayUtils.sol";
2626
* @title ManagerCore
2727
* @author Set Protocol
2828
*
29-
* Registry for governance approved DelegatedManagerFactories and DelegatedManagers.
29+
* Registry for governance approved GlobalExtensions, DelegatedManagerFactories, and DelegatedManagers.
3030
*/
3131
contract ManagerCore is Ownable {
3232
using AddressArrayUtils for address[];
3333

3434
/* ============ Events ============ */
3535

36+
event ExtensionAdded(address indexed _extension);
37+
event ExtensionRemoved(address indexed _extension);
3638
event FactoryAdded(address indexed _factory);
3739
event FactoryRemoved(address indexed _factory);
3840
event ManagerAdded(address indexed _manager, address indexed _factory);
@@ -55,14 +57,18 @@ contract ManagerCore is Ownable {
5557

5658
/* ============ State Variables ============ */
5759

58-
// List of enabled managers
59-
address[] public managers;
60+
// List of enabled extensions
61+
address[] public extensions;
6062
// List of enabled factories of managers
6163
address[] public factories;
64+
// List of enabled managers
65+
address[] public managers;
6266

63-
// Mapping to check whether address is valid Manager or Factory
64-
mapping(address => bool) public isManager;
67+
// Mapping to check whether address is valid Extension, Factory, or Manager
68+
mapping(address => bool) public isExtension;
6569
mapping(address => bool) public isFactory;
70+
mapping(address => bool) public isManager;
71+
6672

6773
// Return true if the ManagerCore is initialized
6874
bool public isInitialized;
@@ -73,57 +79,59 @@ contract ManagerCore is Ownable {
7379
* Initializes any predeployed factories. Note: This function can only be called by
7480
* the owner once to batch initialize the initial system contracts.
7581
*
82+
* @param _extensions List of extensions to add
7683
* @param _factories List of factories to add
7784
*/
7885
function initialize(
86+
address[] memory _extensions,
7987
address[] memory _factories
8088
)
8189
external
8290
onlyOwner
8391
{
8492
require(!isInitialized, "ManagerCore is already initialized");
8593

94+
extensions = _extensions;
8695
factories = _factories;
8796

88-
// Loop through and initialize isFactory mapping
97+
// Loop through and initialize isExtension and isFactory mapping
98+
for (uint256 i = 0; i < _extensions.length; i++) {
99+
_addExtension(_extensions[i]);
100+
}
89101
for (uint256 i = 0; i < _factories.length; i++) {
90-
address factory = _factories[i];
91-
require(factory != address(0), "Zero address submitted.");
92-
isFactory[factory] = true;
102+
_addFactory(_factories[i]);
93103
}
94104

95105
// Set to true to only allow initialization once
96106
isInitialized = true;
97107
}
98108

99109
/**
100-
* PRIVILEGED FACTORY FUNCTION. Adds a newly deployed manager as an enabled manager.
110+
* PRIVILEGED GOVERNANCE FUNCTION. Allows governance to add an extension
101111
*
102-
* @param _manager Address of the manager contract to add
112+
* @param _extension Address of the extension contract to add
103113
*/
104-
function addManager(address _manager) external onlyInitialized onlyFactory {
105-
require(!isManager[_manager], "Manager already exists");
114+
function addExtension(address _extension) external onlyInitialized onlyOwner {
115+
require(!isExtension[_extension], "Extension already exists");
106116

107-
isManager[_manager] = true;
108-
109-
managers.push(_manager);
117+
_addExtension(_extension);
110118

111-
emit ManagerAdded(_manager, msg.sender);
119+
extensions.push(_extension);
112120
}
113121

114122
/**
115-
* PRIVILEGED GOVERNANCE FUNCTION. Allows governance to remove a manager
123+
* PRIVILEGED GOVERNANCE FUNCTION. Allows governance to remove an extension
116124
*
117-
* @param _manager Address of the manager contract to remove
125+
* @param _extension Address of the extension contract to remove
118126
*/
119-
function removeManager(address _manager) external onlyInitialized onlyOwner {
120-
require(isManager[_manager], "Manager does not exist");
127+
function removeExtension(address _extension) external onlyInitialized onlyOwner {
128+
require(isExtension[_extension], "Extension does not exist");
121129

122-
managers.removeStorage(_manager);
130+
extensions.removeStorage(_extension);
123131

124-
isManager[_manager] = false;
132+
isExtension[_extension] = false;
125133

126-
emit ManagerRemoved(_manager);
134+
emit ExtensionRemoved(_extension);
127135
}
128136

129137
/**
@@ -134,11 +142,9 @@ contract ManagerCore is Ownable {
134142
function addFactory(address _factory) external onlyInitialized onlyOwner {
135143
require(!isFactory[_factory], "Factory already exists");
136144

137-
isFactory[_factory] = true;
145+
_addFactory(_factory);
138146

139147
factories.push(_factory);
140-
141-
emit FactoryAdded(_factory);
142148
}
143149

144150
/**
@@ -156,13 +162,75 @@ contract ManagerCore is Ownable {
156162
emit FactoryRemoved(_factory);
157163
}
158164

165+
/**
166+
* PRIVILEGED FACTORY FUNCTION. Adds a newly deployed manager as an enabled manager.
167+
*
168+
* @param _manager Address of the manager contract to add
169+
*/
170+
function addManager(address _manager) external onlyInitialized onlyFactory {
171+
require(!isManager[_manager], "Manager already exists");
172+
173+
isManager[_manager] = true;
174+
175+
managers.push(_manager);
176+
177+
emit ManagerAdded(_manager, msg.sender);
178+
}
179+
180+
/**
181+
* PRIVILEGED GOVERNANCE FUNCTION. Allows governance to remove a manager
182+
*
183+
* @param _manager Address of the manager contract to remove
184+
*/
185+
function removeManager(address _manager) external onlyInitialized onlyOwner {
186+
require(isManager[_manager], "Manager does not exist");
187+
188+
managers.removeStorage(_manager);
189+
190+
isManager[_manager] = false;
191+
192+
emit ManagerRemoved(_manager);
193+
}
194+
159195
/* ============ External Getter Functions ============ */
160196

161-
function getManagers() external view returns (address[] memory) {
162-
return managers;
197+
function getExtensions() external view returns (address[] memory) {
198+
return extensions;
163199
}
164200

165201
function getFactories() external view returns (address[] memory) {
166202
return factories;
167203
}
204+
205+
function getManagers() external view returns (address[] memory) {
206+
return managers;
207+
}
208+
209+
/* ============ Internal Functions ============ */
210+
211+
/**
212+
* Add an extension tracked on the ManagerCore
213+
*
214+
* @param _extension Address of the extension contract to add
215+
*/
216+
function _addExtension(address _extension) internal {
217+
require(_extension != address(0), "Zero address submitted.");
218+
219+
isExtension[_extension] = true;
220+
221+
emit ExtensionAdded(_extension);
222+
}
223+
224+
/**
225+
* Add a factory tracked on the ManagerCore
226+
*
227+
* @param _factory Address of the factory contract to add
228+
*/
229+
function _addFactory(address _factory) internal {
230+
require(_factory != address(0), "Zero address submitted.");
231+
232+
isFactory[_factory] = true;
233+
234+
emit FactoryAdded(_factory);
235+
}
168236
}

contracts/extensions/IssuanceExtension.sol

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ import { IManagerCore } from "../interfaces/IManagerCore.sol";
3434
* @title IssuanceExtension
3535
* @author Set Protocol
3636
*
37-
* Smart contract global extension which provides DelegatedManager owner and methodologist the ability to accrue and split
37+
* Smart contract global extension which provides DelegatedManager owner and methodologist the ability to accrue and split
3838
* issuance and redemption fees. Owner may configure the fee split percentages.
39+
*
40+
* Notes
41+
* - the fee split is set on the Delegated Manager contract
42+
* - when fees distributed via this contract will be inclusive of all fee types that have already been accrued
3943
*/
4044
contract IssuanceExtension is BaseGlobalExtension {
4145
using Address for address;
@@ -119,16 +123,16 @@ contract IssuanceExtension is BaseGlobalExtension {
119123
uint256 _managerRedeemFee,
120124
address _feeRecipient,
121125
address _managerIssuanceHook
122-
)
123-
external
124-
onlyOwnerAndValidManager(_delegatedManager)
126+
)
127+
external
128+
onlyOwnerAndValidManager(_delegatedManager)
125129
{
126130
require(_delegatedManager.isInitializedExtension(address(this)), "Extension must be initialized");
127131

128132
_initializeModule(
129133
_delegatedManager.setToken(),
130134
_delegatedManager,
131-
_maxManagerFee,
135+
_maxManagerFee,
132136
_managerIssueFee,
133137
_managerRedeemFee,
134138
_feeRecipient,
@@ -168,7 +172,7 @@ contract IssuanceExtension is BaseGlobalExtension {
168172
uint256 _managerRedeemFee,
169173
address _feeRecipient,
170174
address _managerIssuanceHook
171-
)
175+
)
172176
external
173177
onlyOwnerAndValidManager(_delegatedManager)
174178
{
@@ -180,7 +184,7 @@ contract IssuanceExtension is BaseGlobalExtension {
180184
_initializeModule(
181185
setToken,
182186
_delegatedManager,
183-
_maxManagerFee,
187+
_maxManagerFee,
184188
_managerIssueFee,
185189
_managerRedeemFee,
186190
_feeRecipient,
@@ -191,10 +195,13 @@ contract IssuanceExtension is BaseGlobalExtension {
191195
}
192196

193197
/**
194-
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the IssuanceExtension
198+
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the IssuanceExtension
195199
*/
196200
function removeExtension() external override {
197-
_removeExtension();
201+
IDelegatedManager delegatedManager = IDelegatedManager(msg.sender);
202+
ISetToken setToken = delegatedManager.setToken();
203+
204+
_removeExtension(setToken, delegatedManager);
198205
}
199206

200207
/**
@@ -260,11 +267,11 @@ contract IssuanceExtension is BaseGlobalExtension {
260267
uint256 _managerRedeemFee,
261268
address _feeRecipient,
262269
address _managerIssuanceHook
263-
)
270+
)
264271
internal
265272
{
266273
bytes memory callData = abi.encodeWithSignature(
267-
"initialize(address,uint256,uint256,uint256,address,address)",
274+
"initialize(address,uint256,uint256,uint256,address,address)",
268275
_setToken,
269276
_maxManagerFee,
270277
_managerIssueFee,

contracts/extensions/StreamingFeeSplitExtension.sol

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
15-
15+
1616
SPDX-License-Identifier: Apache License, Version 2.0
1717
*/
1818

@@ -34,8 +34,12 @@ import { IStreamingFeeModule } from "../interfaces/IStreamingFeeModuleV2.sol";
3434
* @title StreamingFeeSplitExtension
3535
* @author Set Protocol
3636
*
37-
* Smart contract global extension which provides DelegatedManager owner and methodologist the ability to accrue and split
37+
* Smart contract global extension which provides DelegatedManager owner and methodologist the ability to accrue and split
3838
* streaming fees. Owner may configure the fee split percentages.
39+
*
40+
* Notes
41+
* - the fee split is set on the Delegated Manager contract
42+
* - when fees distributed via this contract will be inclusive of all fee types
3943
*/
4044
contract StreamingFeeSplitExtension is BaseGlobalExtension {
4145
using Address for address;
@@ -114,9 +118,9 @@ contract StreamingFeeSplitExtension is BaseGlobalExtension {
114118
function initializeModule(
115119
IDelegatedManager _delegatedManager,
116120
IStreamingFeeModule.FeeState memory _settings
117-
)
118-
external
119-
onlyOwnerAndValidManager(_delegatedManager)
121+
)
122+
external
123+
onlyOwnerAndValidManager(_delegatedManager)
120124
{
121125
require(_delegatedManager.isInitializedExtension(address(this)), "Extension must be initialized");
122126

@@ -147,8 +151,8 @@ contract StreamingFeeSplitExtension is BaseGlobalExtension {
147151
function initializeModuleAndExtension(
148152
IDelegatedManager _delegatedManager,
149153
IStreamingFeeModule.FeeState memory _settings
150-
)
151-
external
154+
)
155+
external
152156
onlyOwnerAndValidManager(_delegatedManager)
153157
{
154158
require(_delegatedManager.isPendingExtension(address(this)), "Extension must be pending");
@@ -162,10 +166,13 @@ contract StreamingFeeSplitExtension is BaseGlobalExtension {
162166
}
163167

164168
/**
165-
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the StreamingFeeSplitExtension
169+
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the StreamingFeeSplitExtension
166170
*/
167171
function removeExtension() external override {
168-
_removeExtension();
172+
IDelegatedManager delegatedManager = IDelegatedManager(msg.sender);
173+
ISetToken setToken = delegatedManager.setToken();
174+
175+
_removeExtension(setToken, delegatedManager);
169176
}
170177

171178
/**
@@ -211,11 +218,11 @@ contract StreamingFeeSplitExtension is BaseGlobalExtension {
211218
ISetToken _setToken,
212219
IDelegatedManager _delegatedManager,
213220
IStreamingFeeModule.FeeState memory _settings
214-
)
221+
)
215222
internal
216223
{
217224
bytes memory callData = abi.encodeWithSignature(
218-
"initialize(address,(address,uint256,uint256,uint256))",
225+
"initialize(address,(address,uint256,uint256,uint256))",
219226
_setToken,
220227
_settings);
221228
_invokeManager(_delegatedManager, address(streamingFeeModule), callData);

contracts/extensions/TradeExtension.sol

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ contract TradeExtension is BaseGlobalExtension {
9999
}
100100

101101
/**
102-
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the TradeExtension
102+
* ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the TradeExtension
103103
*/
104104
function removeExtension() external override {
105-
_removeExtension();
105+
IDelegatedManager delegatedManager = IDelegatedManager(msg.sender);
106+
ISetToken setToken = delegatedManager.setToken();
107+
108+
_removeExtension(setToken, delegatedManager);
106109
}
107110

108111
/**
@@ -132,7 +135,7 @@ contract TradeExtension is BaseGlobalExtension {
132135
onlyAllowedAsset(_setToken, _receiveToken)
133136
{
134137
bytes memory callData = abi.encodeWithSignature(
135-
"trade(address,string,address,uint256,address,uint256,bytes)",
138+
"trade(address,string,address,uint256,address,uint256,bytes)",
136139
_setToken,
137140
_exchangeName,
138141
_sendToken,

0 commit comments

Comments
 (0)