@@ -23,22 +23,21 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol";
23
23
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol " ;
24
24
25
25
import { BaseExtension } from "../lib/BaseExtension.sol " ;
26
+ import { IIssuanceModule } from "../interfaces/IIssuanceModule.sol " ;
26
27
import { IBaseManager } from "../interfaces/IBaseManager.sol " ;
27
28
import { ISetToken } from "../interfaces/ISetToken.sol " ;
28
29
import { IStreamingFeeModule } from "../interfaces/IStreamingFeeModule.sol " ;
29
30
import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol " ;
30
31
import { TimeLockUpgrade } from "../lib/TimeLockUpgrade.sol " ;
31
- import { MutualUpgrade } from "../lib/MutualUpgrade.sol " ;
32
32
33
33
34
34
/**
35
- * @title StreamingFeeSplitExtension
35
+ * @title FeeSplitExtension
36
36
* @author Set Protocol
37
37
*
38
- * Smart contract manager extension that allows for splitting and setting streaming fees. Fee splits are updated by operator.
39
- * Any fee updates are timelocked.
38
+ * Smart contract extension that allows for splitting and setting streaming and mint/redeem fees.
40
39
*/
41
- contract StreamingFeeSplitExtension is BaseExtension , TimeLockUpgrade , MutualUpgrade {
40
+ contract FeeSplitExtension is BaseExtension , TimeLockUpgrade {
42
41
using Address for address ;
43
42
using PreciseUnitMath for uint256 ;
44
43
using SafeMath for uint256 ;
@@ -56,6 +55,7 @@ contract StreamingFeeSplitExtension is BaseExtension, TimeLockUpgrade, MutualUpg
56
55
57
56
ISetToken public setToken;
58
57
IStreamingFeeModule public streamingFeeModule;
58
+ IIssuanceModule public issuanceModule;
59
59
60
60
// Percent of fees in precise units (10^16 = 1%) sent to operator, rest to methodologist
61
61
uint256 public operatorFeeSplit;
@@ -68,13 +68,15 @@ contract StreamingFeeSplitExtension is BaseExtension, TimeLockUpgrade, MutualUpg
68
68
constructor (
69
69
IBaseManager _manager ,
70
70
IStreamingFeeModule _streamingFeeModule ,
71
+ IIssuanceModule _issuanceModule ,
71
72
uint256 _operatorFeeSplit ,
72
73
address _operatorFeeRecipient
73
74
)
74
75
public
75
76
BaseExtension (_manager)
76
77
{
77
78
streamingFeeModule = _streamingFeeModule;
79
+ issuanceModule = _issuanceModule;
78
80
operatorFeeSplit = _operatorFeeSplit;
79
81
operatorFeeRecipient = _operatorFeeRecipient;
80
82
setToken = manager.setToken ();
@@ -83,9 +85,10 @@ contract StreamingFeeSplitExtension is BaseExtension, TimeLockUpgrade, MutualUpg
83
85
/* ============ External Functions ============ */
84
86
85
87
/**
86
- * ANYONE CALLABLE: Accrues fees from streaming fee module. Gets resulting balance after fee accrual,
87
- * calculates fees for operator and methodologist, and sends to operatorFeeRecipient and methodologist
88
- * respectively.
88
+ * ANYONE CALLABLE: Accrues fees from streaming fee module. Gets resulting balance after fee accrual, calculates fees for
89
+ * operator and methodologist, and sends to operator fee recipient and methodologist respectively. NOTE: mint/redeem fees
90
+ * will automatically be sent to this address so reading the balance of the SetToken in the contract after accrual is
91
+ * sufficient for accounting for all collected fees.
89
92
*/
90
93
function accrueFeesAndDistribute () public {
91
94
// Emits a FeeActualized event
@@ -110,97 +113,91 @@ contract StreamingFeeSplitExtension is BaseExtension, TimeLockUpgrade, MutualUpg
110
113
}
111
114
112
115
/**
113
- * MUTUAL UPGRADE: Initializes the streaming fee module. Operator and Methodologist must each call
114
- * this function to execute the update .
116
+ * ONLY OPERATOR: Updates streaming fee on StreamingFeeModule.
117
+ * Because the method is timelocked, each party must call it twice: once to set the lock and once to execute .
115
118
*
116
- * This method is called after invoking `replaceProtectedModule` or `emergencyReplaceProtectedModule`
117
- * to configure the replacement streaming fee module's fee settings.
119
+ * Method is timelocked to protect token owners from sudden changes in fee structure which
120
+ * they would rather not bear. The delay gives them a chance to exit their positions without penalty.
121
+ *
122
+ * NOTE: This will accrue streaming fees though not send to operator fee recipient and methodologist.
118
123
*
119
- * @dev FeeState settings encode the following struct
120
- * ```
121
- * struct FeeState {
122
- * address feeRecipient; // Address to accrue fees to
123
- * uint256 maxStreamingFeePercentage; // Max streaming fee maanager commits to using (1% = 1e16, 100% = 1e18)
124
- * uint256 streamingFeePercentage; // Percent of Set accruing to manager annually (1% = 1e16, 100% = 1e18)
125
- * uint256 lastStreamingFeeTimestamp; // Timestamp last streaming fee was accrued
126
- *}
127
- *```
128
- * @param _settings FeeModule.FeeState settings
124
+ * @param _newFee Percent of Set accruing to fee extension annually (1% = 1e16, 100% = 1e18)
129
125
*/
130
- function initializeModule (IStreamingFeeModule.FeeState memory _settings )
126
+ function updateStreamingFee ( uint256 _newFee )
131
127
external
132
- mutualUpgrade (manager.operator (), manager.methodologist ())
128
+ onlyOperator
129
+ timeLockUpgrade
133
130
{
134
- bytes memory callData = abi.encodeWithSelector (
135
- IStreamingFeeModule.initialize.selector ,
136
- manager.setToken (),
137
- _settings
138
- );
139
-
131
+ bytes memory callData = abi.encodeWithSignature ("updateStreamingFee(address,uint256) " , manager.setToken (), _newFee);
140
132
invokeManager (address (streamingFeeModule), callData);
141
133
}
142
134
143
135
/**
144
- * MUTUAL UPGRADE: Updates streaming fee on StreamingFeeModule. Operator and Methodologist must
145
- * each call this function to execute the update. Because the method is timelocked, each party
146
- * must call it twice: once to set the lock and once to execute.
136
+ * ONLY OPERATOR: Updates issue fee on IssuanceModule. Only is executed once time lock has passed.
137
+ * Because the method is timelocked, each party must call it twice: once to set the lock and once to execute.
147
138
*
148
139
* Method is timelocked to protect token owners from sudden changes in fee structure which
149
140
* they would rather not bear. The delay gives them a chance to exit their positions without penalty.
150
141
*
151
- * NOTE: This will accrue streaming fees though not send to operator fee recipient and methodologist.
152
- *
153
- * @param _newFee Percent of Set accruing to fee extension annually (1% = 1e16, 100% = 1e18)
142
+ * @param _newFee New issue fee percentage in precise units (1% = 1e16, 100% = 1e18)
154
143
*/
155
- function updateStreamingFee (uint256 _newFee )
144
+ function updateIssueFee (uint256 _newFee )
156
145
external
157
- mutualUpgrade (manager. operator (), manager. methodologist ())
146
+ onlyOperator
158
147
timeLockUpgrade
159
148
{
160
- bytes memory callData = abi.encodeWithSelector (
161
- IStreamingFeeModule.updateStreamingFee.selector ,
162
- manager.setToken (),
163
- _newFee
164
- );
149
+ bytes memory callData = abi.encodeWithSignature ("updateIssueFee(address,uint256) " , manager.setToken (), _newFee);
150
+ invokeManager (address (issuanceModule), callData);
151
+ }
165
152
166
- invokeManager (address (streamingFeeModule), callData);
153
+ /**
154
+ * ONLY OPERATOR: Updates redeem fee on IssuanceModule. Only is executed once time lock has passed.
155
+ * Because the method is timelocked, each party must call it twice: once to set the lock and once to execute.
156
+ *
157
+ * Method is timelocked to protect token owners from sudden changes in fee structure which
158
+ * they would rather not bear. The delay gives them a chance to exit their positions without penalty.
159
+ *
160
+ * @param _newFee New redeem fee percentage in precise units (1% = 1e16, 100% = 1e18)
161
+ */
162
+ function updateRedeemFee (uint256 _newFee )
163
+ external
164
+ onlyOperator
165
+ timeLockUpgrade
166
+ {
167
+ bytes memory callData = abi.encodeWithSignature ("updateRedeemFee(address,uint256) " , manager.setToken (), _newFee);
168
+ invokeManager (address (issuanceModule), callData);
167
169
}
168
170
169
171
/**
170
- * MUTUAL UPGRADE : Updates fee recipient on streaming fee module .
172
+ * ONLY OPERATOR : Updates fee recipient on both streaming fee and issuance modules .
171
173
*
172
174
* @param _newFeeRecipient Address of new fee recipient. This should be the address of the fee extension itself.
173
175
*/
174
176
function updateFeeRecipient (address _newFeeRecipient )
175
177
external
176
- mutualUpgrade (manager. operator (), manager. methodologist ())
178
+ onlyOperator
177
179
{
178
- bytes memory callData = abi.encodeWithSelector (
179
- IStreamingFeeModule.updateFeeRecipient.selector ,
180
- manager.setToken (),
181
- _newFeeRecipient
182
- );
183
-
180
+ bytes memory callData = abi.encodeWithSignature ("updateFeeRecipient(address,address) " , manager.setToken (), _newFeeRecipient);
184
181
invokeManager (address (streamingFeeModule), callData);
182
+ invokeManager (address (issuanceModule), callData);
185
183
}
186
184
187
185
/**
188
- * MUTUAL UPGRADE: Updates fee split between operator and methodologist. Split defined in precise units (1% = 10^16).
189
- * Fees will be accrued and distributed before the new split goes into effect.
186
+ * ONLY OPERATOR: Updates fee split between operator and methodologist. Split defined in precise units (1% = 10^16).
190
187
*
191
188
* @param _newFeeSplit Percent of fees in precise units (10^16 = 1%) sent to operator, (rest go to the methodologist).
192
189
*/
193
190
function updateFeeSplit (uint256 _newFeeSplit )
194
191
external
195
- mutualUpgrade (manager. operator (), manager. methodologist ())
192
+ onlyOperator
196
193
{
197
194
require (_newFeeSplit <= PreciseUnitMath.preciseUnit (), "Fee must be less than 100% " );
198
195
accrueFeesAndDistribute ();
199
196
operatorFeeSplit = _newFeeSplit;
200
197
}
201
198
202
199
/**
203
- * OPERATOR ONLY: Updates the address that receives the operator's share of the fees (see IIP-72)
200
+ * ONLY OPERATOR : Updates the address that receives the operator's fees (see IIP-72)
204
201
*
205
202
* @param _newOperatorFeeRecipient Address to send operator's fees to.
206
203
*/
@@ -211,4 +208,4 @@ contract StreamingFeeSplitExtension is BaseExtension, TimeLockUpgrade, MutualUpg
211
208
require (_newOperatorFeeRecipient != address (0 ), "Zero address not valid " );
212
209
operatorFeeRecipient = _newOperatorFeeRecipient;
213
210
}
214
- }
211
+ }
0 commit comments