Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added public functions to check whether shutdown #30

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/TwabController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,25 @@ contract TwabController {

/* ============ External Read Functions ============ */

/**
* @notice Returns whether the TwabController has been shutdown at the given timestamp
* If the twab is queried at or after this time, whether an absolute timestamp or time range, it will return 0.
* @dev This function will return true for any timestamp after the lastObservationAt()
* @param timestamp The timestamp to check
* @return True if the TwabController is shutdown at the given timestamp, false otherwise.
*/
function isShutdownAt(uint256 timestamp) external view returns (bool) {
return TwabLib.isShutdownAt(timestamp, PERIOD_OFFSET);
}

/**
* @notice Computes the timestamp after which no more observations will be made.
* @return The largest timestamp at which the TwabController can record a new observation.
*/
function lastObservationAt() external view returns (uint256) {
return TwabLib.lastObservationAt(PERIOD_OFFSET);
}

/**
* @notice Loads the current TWAB Account data for a specific vault stored for a user.
* @dev Note this is a very expensive function
Expand Down
38 changes: 31 additions & 7 deletions src/libraries/TwabLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ library TwabLib {
// record a new observation if the delegateAmount is non-zero and time has not overflowed.
isObservationRecorded =
_delegateAmount != uint96(0) &&
(block.timestamp - PERIOD_OFFSET) <= type(uint32).max;
block.timestamp <= lastObservationAt(PERIOD_OFFSET);

accountDetails.balance += _amount;
accountDetails.delegateBalance += _delegateAmount;
Expand Down Expand Up @@ -172,7 +172,7 @@ library TwabLib {
// record a new observation if the delegateAmount is non-zero and time has not overflowed.
isObservationRecorded =
_delegateAmount != uint96(0) &&
(block.timestamp - PERIOD_OFFSET) <= type(uint32).max;
block.timestamp <= lastObservationAt(PERIOD_OFFSET);

unchecked {
accountDetails.balance -= _amount;
Expand Down Expand Up @@ -250,19 +250,43 @@ library TwabLib {
if (_targetTime < PERIOD_OFFSET) {
return 0;
}
uint256 offsetTargetTime = _targetTime - PERIOD_OFFSET;
// if this is for an overflowed time period, return 0
if (offsetTargetTime > type(uint32).max) {
if (isShutdownAt(_targetTime, PERIOD_OFFSET)) {
return 0;
}
ObservationLib.Observation memory prevOrAtObservation = _getPreviousOrAtObservation(
_observations,
_accountDetails,
PeriodOffsetRelativeTimestamp.wrap(uint32(offsetTargetTime))
PeriodOffsetRelativeTimestamp.wrap(uint32(_targetTime - PERIOD_OFFSET))
);
return prevOrAtObservation.balance;
}

/**
* @notice Returns whether the TwabController has been shutdown at the given timestamp
* If the twab is queried at or after this time, whether an absolute timestamp or time range, it will return 0.
* @param timestamp The timestamp to check
* @param PERIOD_OFFSET The offset of the first period
* @return True if the TwabController is shutdown at the given timestamp, false otherwise.
*/
function isShutdownAt(
uint256 timestamp,
uint32 PERIOD_OFFSET
) internal pure returns (bool) {
return timestamp > lastObservationAt(PERIOD_OFFSET);
}

/**
* @notice Computes the largest timestamp at which the TwabController can record a new observation.
* @param PERIOD_OFFSET The offset of the first period
* @return The largest timestamp at which the TwabController can record a new observation.
*/
function lastObservationAt(
uint32 PERIOD_OFFSET
) internal pure returns (uint256) {
return uint256(PERIOD_OFFSET) + type(uint32).max;
}

/**
* @notice Looks up a users TWAB for a time range. The time must be before the current overwrite period.
* @dev If the timestamps in the range are not exact matches of observations, the balance is extrapolated using the previous observation.
Expand All @@ -289,8 +313,8 @@ library TwabLib {
uint256 offsetStartTime = _startTime - PERIOD_OFFSET;
uint256 offsetEndTime = _endTime - PERIOD_OFFSET;

// if the either time has overflowed, then return 0.
if (offsetStartTime > type(uint32).max || offsetEndTime > type(uint32).max) {
// if the range extends into the shutdown period, return 0
if (isShutdownAt(_endTime, PERIOD_OFFSET)) {
return 0;
}
Comment on lines +313 to 316
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(optional) could move this before line 313


Expand Down
11 changes: 11 additions & 0 deletions test/TwabController.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ contract TwabControllerTest is BaseTest {
vm.stopPrank();
}

function testIsShutdownAt() public {
assertEq(twabController.isShutdownAt(PERIOD_OFFSET), false, "at beginning");
assertEq(twabController.isShutdownAt(PERIOD_OFFSET + PERIOD_LENGTH), false, "after first period");
assertEq(twabController.isShutdownAt(type(uint32).max + uint256(PERIOD_OFFSET)), false, "at end");
assertEq(twabController.isShutdownAt(type(uint32).max + uint256(PERIOD_OFFSET) + 1), true, "after end");
}

function testLastObservationAt() public {
assertEq(twabController.lastObservationAt(), uint256(PERIOD_OFFSET) + type(uint32).max);
}

function testGetBalanceAt_beforeHistoryStarted() public {
// ensure times are finalized
vm.warp(PERIOD_OFFSET + PERIOD_LENGTH);
Expand Down
Loading