@@ -109,7 +109,7 @@ library TwabLib {
109109 // record a new observation if the delegateAmount is non-zero and time has not overflowed.
110110 isObservationRecorded =
111111 _delegateAmount != uint96 (0 ) &&
112- ( block .timestamp - PERIOD_OFFSET) <= type ( uint32 ).max ;
112+ block .timestamp <= lastObservationAt (PERIOD_OFFSET) ;
113113
114114 accountDetails.balance += _amount;
115115 accountDetails.delegateBalance += _delegateAmount;
@@ -172,7 +172,7 @@ library TwabLib {
172172 // record a new observation if the delegateAmount is non-zero and time has not overflowed.
173173 isObservationRecorded =
174174 _delegateAmount != uint96 (0 ) &&
175- ( block .timestamp - PERIOD_OFFSET) <= type ( uint32 ).max ;
175+ block .timestamp <= lastObservationAt (PERIOD_OFFSET) ;
176176
177177 unchecked {
178178 accountDetails.balance -= _amount;
@@ -250,19 +250,43 @@ library TwabLib {
250250 if (_targetTime < PERIOD_OFFSET) {
251251 return 0 ;
252252 }
253- uint256 offsetTargetTime = _targetTime - PERIOD_OFFSET;
254253 // if this is for an overflowed time period, return 0
255- if (offsetTargetTime > type ( uint32 ).max ) {
254+ if (isShutdownAt (_targetTime, PERIOD_OFFSET) ) {
256255 return 0 ;
257256 }
258257 ObservationLib.Observation memory prevOrAtObservation = _getPreviousOrAtObservation (
259258 _observations,
260259 _accountDetails,
261- PeriodOffsetRelativeTimestamp.wrap (uint32 (offsetTargetTime ))
260+ PeriodOffsetRelativeTimestamp.wrap (uint32 (_targetTime - PERIOD_OFFSET ))
262261 );
263262 return prevOrAtObservation.balance;
264263 }
265264
265+ /**
266+ * @notice Returns whether the TwabController has been shutdown at the given timestamp
267+ * If the twab is queried at or after this time, whether an absolute timestamp or time range, it will return 0.
268+ * @param timestamp The timestamp to check
269+ * @param PERIOD_OFFSET The offset of the first period
270+ * @return True if the TwabController is shutdown at the given timestamp, false otherwise.
271+ */
272+ function isShutdownAt (
273+ uint256 timestamp ,
274+ uint32 PERIOD_OFFSET
275+ ) internal pure returns (bool ) {
276+ return timestamp > lastObservationAt (PERIOD_OFFSET);
277+ }
278+
279+ /**
280+ * @notice Computes the largest timestamp at which the TwabController can record a new observation.
281+ * @param PERIOD_OFFSET The offset of the first period
282+ * @return The largest timestamp at which the TwabController can record a new observation.
283+ */
284+ function lastObservationAt (
285+ uint32 PERIOD_OFFSET
286+ ) internal pure returns (uint256 ) {
287+ return uint256 (PERIOD_OFFSET) + type (uint32 ).max;
288+ }
289+
266290 /**
267291 * @notice Looks up a users TWAB for a time range. The time must be before the current overwrite period.
268292 * @dev If the timestamps in the range are not exact matches of observations, the balance is extrapolated using the previous observation.
@@ -289,8 +313,8 @@ library TwabLib {
289313 uint256 offsetStartTime = _startTime - PERIOD_OFFSET;
290314 uint256 offsetEndTime = _endTime - PERIOD_OFFSET;
291315
292- // if the either time has overflowed, then return 0.
293- if (offsetStartTime > type ( uint32 ).max || offsetEndTime > type ( uint32 ).max ) {
316+ // if the range extends into the shutdown period, return 0
317+ if (isShutdownAt (_endTime, PERIOD_OFFSET) ) {
294318 return 0 ;
295319 }
296320
0 commit comments