Skip to content

Commit bf1d22a

Browse files
committed
Added public functions to check whether shutdown
1 parent bc3d860 commit bf1d22a

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

src/TwabController.sol

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,25 @@ contract TwabController {
171171

172172
/* ============ External Read Functions ============ */
173173

174+
/**
175+
* @notice Returns whether the TwabController has been shutdown at the given timestamp
176+
* If the twab is queried at or after this time, whether an absolute timestamp or time range, it will return 0.
177+
* @dev This function will return true for any timestamp after the lastObservationAt()
178+
* @param timestamp The timestamp to check
179+
* @return True if the TwabController is shutdown at the given timestamp, false otherwise.
180+
*/
181+
function isShutdownAt(uint256 timestamp) external view returns (bool) {
182+
return TwabLib.isShutdownAt(timestamp, PERIOD_OFFSET);
183+
}
184+
185+
/**
186+
* @notice Computes the timestamp after which no more observations will be made.
187+
* @return The largest timestamp at which the TwabController can record a new observation.
188+
*/
189+
function lastObservationAt() external view returns (uint256) {
190+
return TwabLib.lastObservationAt(PERIOD_OFFSET);
191+
}
192+
174193
/**
175194
* @notice Loads the current TWAB Account data for a specific vault stored for a user.
176195
* @dev Note this is a very expensive function

src/libraries/TwabLib.sol

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test/TwabController.t.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,17 @@ contract TwabControllerTest is BaseTest {
145145
vm.stopPrank();
146146
}
147147

148+
function testIsShutdownAt() public {
149+
assertEq(twabController.isShutdownAt(PERIOD_OFFSET), false, "at beginning");
150+
assertEq(twabController.isShutdownAt(PERIOD_OFFSET + PERIOD_LENGTH), false, "after first period");
151+
assertEq(twabController.isShutdownAt(type(uint32).max + uint256(PERIOD_OFFSET)), false, "at end");
152+
assertEq(twabController.isShutdownAt(type(uint32).max + uint256(PERIOD_OFFSET) + 1), true, "after end");
153+
}
154+
155+
function testLastObservationAt() public {
156+
assertEq(twabController.lastObservationAt(), uint256(PERIOD_OFFSET) + type(uint32).max);
157+
}
158+
148159
function testGetBalanceAt_beforeHistoryStarted() public {
149160
// ensure times are finalized
150161
vm.warp(PERIOD_OFFSET + PERIOD_LENGTH);

0 commit comments

Comments
 (0)