@@ -64,6 +64,13 @@ contract UFragmentsPolicy is Ownable {
64
64
// Block timestamp of last rebase operation
65
65
uint256 public lastRebaseTimestampSec;
66
66
67
+ // The rebase window begins this many seconds into the minRebaseTimeInterval period.
68
+ // For example if minRebaseTimeInterval is 24hrs, it represents the time of day in seconds.
69
+ uint256 public rebaseWindowOffsetSec;
70
+
71
+ // The length of the time window where a rebase operation is allowed to execute, in seconds.
72
+ uint256 public rebaseWindowLengthSec;
73
+
67
74
// The number of rebase cycles since inception
68
75
uint256 public epoch;
69
76
@@ -83,37 +90,41 @@ contract UFragmentsPolicy is Ownable {
83
90
* and targetRate is CpiOracleRate / baseCpi
84
91
*/
85
92
function rebase () external {
93
+ require (inRebaseWindow ());
94
+
86
95
// This comparison also ensures there is no reentrancy.
87
96
require (lastRebaseTimestampSec.add (minRebaseTimeIntervalSec) < now );
88
- lastRebaseTimestampSec = now ;
97
+
98
+ // Snap the rebase time to the start of this window.
99
+ lastRebaseTimestampSec = now .sub (now .mod (minRebaseTimeIntervalSec));
100
+
89
101
epoch = epoch.add (1 );
90
102
91
103
uint256 cpi;
92
104
bool cpiValid;
93
105
(cpi, cpiValid) = cpiOracle.getData ();
106
+ require (cpiValid);
94
107
95
108
uint256 targetRate = cpi.mul (10 ** DECIMALS).div (baseCpi);
96
109
97
110
uint256 exchangeRate;
98
111
bool rateValid;
99
112
(exchangeRate, rateValid) = marketOracle.getData ();
113
+ require (rateValid);
100
114
101
115
if (exchangeRate > MAX_RATE) {
102
116
exchangeRate = MAX_RATE;
103
117
}
104
118
105
- int256 supplyDelta = 0 ;
119
+ int256 supplyDelta = computeSupplyDelta (exchangeRate, targetRate) ;
106
120
107
- if (cpiValid && rateValid) {
108
- supplyDelta = computeSupplyDelta (exchangeRate, targetRate );
121
+ // Apply the Dampening factor.
122
+ supplyDelta = supplyDelta. div (rebaseLag. toInt256Safe () );
109
123
110
- // Apply the Dampening factor.
111
- supplyDelta = supplyDelta.div (rebaseLag.toInt256Safe ());
112
-
113
- if (supplyDelta > 0 && uFrags.totalSupply ().add (uint256 (supplyDelta)) > MAX_SUPPLY) {
114
- supplyDelta = (MAX_SUPPLY.sub (uFrags.totalSupply ())).toInt256Safe ();
115
- }
124
+ if (supplyDelta > 0 && uFrags.totalSupply ().add (uint256 (supplyDelta)) > MAX_SUPPLY) {
125
+ supplyDelta = (MAX_SUPPLY.sub (uFrags.totalSupply ())).toInt256Safe ();
116
126
}
127
+
117
128
uint256 supplyAfterRebase = uFrags.rebase (epoch, supplyDelta);
118
129
assert (supplyAfterRebase <= MAX_SUPPLY);
119
130
emit LogRebase (epoch, exchangeRate, cpi, supplyDelta, lastRebaseTimestampSec);
@@ -154,19 +165,6 @@ contract UFragmentsPolicy is Ownable {
154
165
deviationThreshold = deviationThreshold_;
155
166
}
156
167
157
- /**
158
- * @notice Sets the minimum time period that must elapse between rebase cycles.
159
- * @param minRebaseTimeIntervalSec_ More than this much time must pass between rebase
160
- * operations, in seconds.
161
- */
162
- function setMinRebaseTimeIntervalSec (uint256 minRebaseTimeIntervalSec_ )
163
- external
164
- onlyOwner
165
- {
166
- require (minRebaseTimeIntervalSec_ > 0 );
167
- minRebaseTimeIntervalSec = minRebaseTimeIntervalSec_;
168
- }
169
-
170
168
/**
171
169
* @notice Sets the rebase lag parameter.
172
170
It is used to dampen the applied supply adjustment by 1 / rebaseLag
@@ -183,6 +181,33 @@ contract UFragmentsPolicy is Ownable {
183
181
rebaseLag = rebaseLag_;
184
182
}
185
183
184
+ /**
185
+ * @notice Sets the parameters which control the timing and frequency of
186
+ * rebase operations.
187
+ * a) the minimum time period that must elapse between rebase cycles.
188
+ * b) the rebase window offset parameter.
189
+ * c) the rebase window length parameter.
190
+ * @param minRebaseTimeIntervalSec_ More than this much time must pass between rebase
191
+ * operations, in seconds.
192
+ * @param rebaseWindowOffsetSec_ The number of seconds from the beginning of
193
+ the rebase interval, where the rebase window begins.
194
+ * @param rebaseWindowLengthSec_ The length of the rebase window in seconds.
195
+ */
196
+ function setRebaseTimingParameters (
197
+ uint256 minRebaseTimeIntervalSec_ ,
198
+ uint256 rebaseWindowOffsetSec_ ,
199
+ uint256 rebaseWindowLengthSec_ )
200
+ external
201
+ onlyOwner
202
+ {
203
+ require (minRebaseTimeIntervalSec_ > 0 );
204
+ require (rebaseWindowOffsetSec_ < minRebaseTimeIntervalSec_);
205
+
206
+ minRebaseTimeIntervalSec = minRebaseTimeIntervalSec_;
207
+ rebaseWindowOffsetSec = rebaseWindowOffsetSec_;
208
+ rebaseWindowLengthSec = rebaseWindowLengthSec_;
209
+ }
210
+
186
211
/**
187
212
* @dev ZOS upgradable contract initialization method.
188
213
* It is called at the time of contract creation to invoke parent class initializers and
@@ -199,13 +224,26 @@ contract UFragmentsPolicy is Ownable {
199
224
200
225
rebaseLag = 30 ;
201
226
minRebaseTimeIntervalSec = 1 days ;
227
+ rebaseWindowOffsetSec = 72000 ; // 8PM UTC
228
+ rebaseWindowLengthSec = 15 minutes ;
202
229
lastRebaseTimestampSec = 0 ;
203
230
epoch = 0 ;
204
231
205
232
uFrags = uFrags_;
206
233
baseCpi = baseCpi_;
207
234
}
208
235
236
+ /**
237
+ * @return If the latest block timestamp is within the rebase time window it, returns true.
238
+ * Otherwise, returns false.
239
+ */
240
+ function inRebaseWindow () public view returns (bool ) {
241
+ return (
242
+ now .mod (minRebaseTimeIntervalSec) >= rebaseWindowOffsetSec &&
243
+ now .mod (minRebaseTimeIntervalSec) < (rebaseWindowOffsetSec.add (rebaseWindowLengthSec))
244
+ );
245
+ }
246
+
209
247
/**
210
248
* @return Computes the total supply adjustment in response to the exchange rate
211
249
* and the targetRate.
0 commit comments