Skip to content

Commit

Permalink
Merge pull request #31 from GenerationSoftware/gen-1136-double-check-…
Browse files Browse the repository at this point in the history
…that-twabcontroller-lastobservationat-is

Fixed bug in last observation timestamp
  • Loading branch information
asselstine authored Mar 22, 2024
2 parents 258ab89 + ffc19c3 commit 817ca2d
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/TwabController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,15 @@ contract TwabController {
* @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);
return TwabLib.isShutdownAt(timestamp, PERIOD_LENGTH, 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);
return TwabLib.lastObservationAt(PERIOD_LENGTH, PERIOD_OFFSET);
}

/**
Expand Down
14 changes: 8 additions & 6 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 <= lastObservationAt(PERIOD_OFFSET);
block.timestamp <= lastObservationAt(PERIOD_LENGTH, 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 <= lastObservationAt(PERIOD_OFFSET);
block.timestamp <= lastObservationAt(PERIOD_LENGTH, PERIOD_OFFSET);

unchecked {
accountDetails.balance -= _amount;
Expand Down Expand Up @@ -251,7 +251,7 @@ library TwabLib {
return 0;
}
// if this is for an overflowed time period, return 0
if (isShutdownAt(_targetTime, PERIOD_OFFSET)) {
if (isShutdownAt(_targetTime, PERIOD_LENGTH, PERIOD_OFFSET)) {
return 0;
}
ObservationLib.Observation memory prevOrAtObservation = _getPreviousOrAtObservation(
Expand All @@ -271,9 +271,10 @@ library TwabLib {
*/
function isShutdownAt(
uint256 timestamp,
uint32 PERIOD_LENGTH,
uint32 PERIOD_OFFSET
) internal pure returns (bool) {
return timestamp > lastObservationAt(PERIOD_OFFSET);
return timestamp > lastObservationAt(PERIOD_LENGTH, PERIOD_OFFSET);
}

/**
Expand All @@ -282,9 +283,10 @@ library TwabLib {
* @return The largest timestamp at which the TwabController can record a new observation.
*/
function lastObservationAt(
uint32 PERIOD_LENGTH,
uint32 PERIOD_OFFSET
) internal pure returns (uint256) {
return uint256(PERIOD_OFFSET) + type(uint32).max;
return uint256(PERIOD_OFFSET) + (type(uint32).max / PERIOD_LENGTH) * PERIOD_LENGTH;
}

/**
Expand All @@ -311,7 +313,7 @@ library TwabLib {
}

// if the range extends into the shutdown period, return 0
if (isShutdownAt(_endTime, PERIOD_OFFSET)) {
if (isShutdownAt(_endTime, PERIOD_LENGTH, PERIOD_OFFSET)) {
return 0;
}

Expand Down
17 changes: 15 additions & 2 deletions test/TwabController.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,13 @@ contract TwabControllerTest is BaseTest {
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/PERIOD_LENGTH)*PERIOD_LENGTH + uint256(PERIOD_OFFSET)), false, "at end of last period");
assertEq(twabController.isShutdownAt(type(uint32).max + uint256(PERIOD_OFFSET)), true, "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);
assertEq(twabController.lastObservationAt(), uint256(PERIOD_OFFSET) + (type(uint32).max/PERIOD_LENGTH)*PERIOD_LENGTH);
}

function testGetBalanceAt_beforeHistoryStarted() public {
Expand Down Expand Up @@ -948,6 +949,18 @@ contract TwabControllerTest is BaseTest {
assertEq(twabController.delegateOf(mockVault, alice), bob);
}

function testMint_lastObservation() public {
vm.startPrank(mockVault);
uint96 _amount = 1000e18;
uint lastAt = twabController.lastObservationAt();
console2.log("LAST AT", lastAt);
vm.warp(lastAt);
twabController.mint(alice, _amount);
vm.warp(lastAt + PERIOD_LENGTH);
assertEq(twabController.getBalanceAt(mockVault, alice, lastAt), _amount);
vm.stopPrank();
}

function testMint_toZero() public {
vm.startPrank(mockVault);

Expand Down
6 changes: 3 additions & 3 deletions test/TwabLib.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ contract TwabLibTest is BaseTest {
/* ============ increaseBalances ============ */

function testIncreaseBalance_endOfTimerange() public {
uint256 timestamp = PERIOD_OFFSET + uint256(type(uint32).max);
uint256 timestamp = twabLibMock.lastObservationAt();
vm.warp(timestamp);
twabLibMock.increaseBalances(1000e18, 1000e18);
vm.warp(uint256(type(uint48).max));
Expand All @@ -45,7 +45,7 @@ contract TwabLibTest is BaseTest {
function testDecreaseBalance_endOfTimerange() public {
vm.warp(PERIOD_OFFSET);
twabLibMock.increaseBalances(1000e18, 1000e18);
uint256 timestamp = PERIOD_OFFSET + uint256(type(uint32).max);
uint256 timestamp = twabLibMock.lastObservationAt();
vm.warp(timestamp);
twabLibMock.decreaseBalances(100e18, 100e18, "revert message");
vm.warp(uint256(type(uint48).max));
Expand Down Expand Up @@ -734,7 +734,7 @@ contract TwabLibTest is BaseTest {
function testGetBalanceAt_endOfTimerange() public {
twabLibMock.increaseBalances(0, 1e18);
vm.warp(type(uint48).max);
assertEq(twabLibMock.getBalanceAt(PERIOD_OFFSET + uint256(type(uint32).max)), 1e18);
assertEq(twabLibMock.getBalanceAt(twabLibMock.lastObservationAt()), 1e18);
}

function testGetBalanceAt_outOfTimerange() public {
Expand Down
1 change: 0 additions & 1 deletion test/invariants/handlers/TwabControllerHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ contract TwabControllerHandler is CommonBase, StdCheats, StdUtils {
function reduceFullRangeTwabs() external view returns (uint256, uint256) {
uint256 vaultAcc = 0;
uint256 actorAcc = 0;
ObservationLib.Observation memory newestActorObservation;
ObservationLib.Observation memory newestObservation;

// For Each Vault
Expand Down
5 changes: 5 additions & 0 deletions test/mocks/TwabLibMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,9 @@ contract TwabLibMock {
bool isSafe = TwabLib.hasFinalized(PERIOD_LENGTH, PERIOD_OFFSET, _timestamp);
return isSafe;
}

function lastObservationAt() external view returns (uint) {
uint result = TwabLib.lastObservationAt(PERIOD_LENGTH, PERIOD_OFFSET);
return result;
}
}

0 comments on commit 817ca2d

Please sign in to comment.