Skip to content

Commit

Permalink
feat(licenses): update license and G9 Software name
Browse files Browse the repository at this point in the history
  • Loading branch information
PierrickGT committed Oct 17, 2023
1 parent 15d4fdf commit 061cb4c
Show file tree
Hide file tree
Showing 19 changed files with 239 additions and 172 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Generation Software
Copyright (c) 2023 G9 Software Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion lib/ring-buffer-lib
Submodule ring-buffer-lib updated 1 files
+1 −1 .gitmodules
32 changes: 8 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@pooltogether/foundry-template",
"name": "@generationsoftware/pt-v5-twab-controller",
"version": "1.0.0",
"description": "Template to kickstart a Foundry project",
"description": "PoolTogether V5 TWAB Controller contracts",
"author": {
"name": "PoolTogether Inc.",
"url": "https://github.com/pooltogether"
"name": "G9 Software Inc.",
"url": "https://github.com/generationsoftware"
},
"repository": {
"type": "git",
"url": "git+https://github.com/pooltogether/foundry-template.git"
"url": "git+https://github.com/generationsoftware/pt-v5-twab-controller.git"
},
"scripts": {
"clean": "forge clean",
Expand All @@ -25,7 +25,7 @@
"devDependencies": {
"husky": "8.0.3",
"lint-staged": "14.0.1",
"prettier": "3.0.3",
"prettier": "2.8.8",
"prettier-plugin-solidity": "1.1.3",
"solhint": "3.6.2",
"solhint-plugin-prettier": "0.0.5"
Expand Down
11 changes: 3 additions & 8 deletions src/TwabController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ uint32 constant MINIMUM_PERIOD_LENGTH = 1 hours;
address constant SPONSORSHIP_ADDRESS = address(1);

/**
* @title Time-Weighted Average Balance Controller
* @author PoolTogether Inc.
* @title PoolTogether V5 Time-Weighted Average Balance Controller
* @author PoolTogether Inc. & G9 Software Inc.
* @dev Time-Weighted Average Balance Controller for ERC20 tokens.
* @notice This TwabController uses the TwabLib to provide token balances and on-chain historical
lookups to a user(s) time-weighted average balance. Each user is mapped to an
Expand Down Expand Up @@ -366,12 +366,7 @@ contract TwabController {
return _timestamp;
}
uint256 period = TwabLib.getTimestampPeriod(PERIOD_LENGTH, PERIOD_OFFSET, _timestamp);
return
TwabLib.getPeriodEndTime(
PERIOD_LENGTH,
PERIOD_OFFSET,
period
);
return TwabLib.getPeriodEndTime(PERIOD_LENGTH, PERIOD_OFFSET, period);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/ObservationLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import "ring-buffer-lib/RingBufferLib.sol";
uint16 constant MAX_CARDINALITY = 17520; // with min period of 1 hour, this allows for minimum two years of history

/**
* @title Observation Library
* @title PoolTogether V5 Observation Library
* @author PoolTogether Inc. & G9 Software Inc.
* @notice This library allows one to store an array of timestamped values and efficiently search them.
* @dev Largely pulled from Uniswap V3 Oracle.sol: https://github.com/Uniswap/v3-core/blob/c05a0e2c8c08c460fb4d05cfdda30b3ad8deeaac/contracts/libraries/Oracle.sol
* @author PoolTogether Inc.
*/
library ObservationLib {
/**
Expand Down
95 changes: 62 additions & 33 deletions src/libraries/TwabLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ error InvalidTimeRange(uint256 start, uint256 end);
/// @notice Emitted when there is insufficient history to lookup a twab time range
/// @param requestedTimestamp The timestamp requested
/// @param oldestTimestamp The oldest timestamp that can be read
error InsufficientHistory(PeriodOffsetRelativeTimestamp requestedTimestamp, PeriodOffsetRelativeTimestamp oldestTimestamp);
error InsufficientHistory(
PeriodOffsetRelativeTimestamp requestedTimestamp,
PeriodOffsetRelativeTimestamp oldestTimestamp
);

/**
* @title PoolTogether V5 TwabLib (Library)
* @author PoolTogether Inc Team
* @author PoolTogether Inc. & G9 Software Inc.
* @dev Time-Weighted Average Balance Library for ERC20 tokens.
* @notice This TwabLib adds on-chain historical lookups to a user(s) time-weighted average balance.
* Each user is mapped to an Account struct containing the TWAB history (ring buffer) and
Expand Down Expand Up @@ -104,7 +107,9 @@ library TwabLib {
{
accountDetails = _account.details;
// 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;
isObservationRecorded =
_delegateAmount != uint96(0) &&
(block.timestamp - PERIOD_OFFSET) <= type(uint32).max;

accountDetails.balance += _amount;
accountDetails.delegateBalance += _delegateAmount;
Expand Down Expand Up @@ -165,7 +170,9 @@ 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;
isObservationRecorded =
_delegateAmount != uint96(0) &&
(block.timestamp - PERIOD_OFFSET) <= type(uint32).max;

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

Expand Down Expand Up @@ -279,18 +290,25 @@ library TwabLib {
uint256 offsetEndTime = _endTime - PERIOD_OFFSET;

// if the either time has overflowed, then return 0.
if (offsetStartTime > type(uint32).max ||
offsetEndTime > type(uint32).max) {
if (offsetStartTime > type(uint32).max || offsetEndTime > type(uint32).max) {
return 0;
}

ObservationLib.Observation memory endObservation = _getPreviousOrAtObservation(_observations, _accountDetails, PeriodOffsetRelativeTimestamp.wrap(uint32(offsetEndTime)));
ObservationLib.Observation memory endObservation = _getPreviousOrAtObservation(
_observations,
_accountDetails,
PeriodOffsetRelativeTimestamp.wrap(uint32(offsetEndTime))
);

if (offsetStartTime == offsetEndTime) {
return endObservation.balance;
}

ObservationLib.Observation memory startObservation = _getPreviousOrAtObservation(_observations, _accountDetails, PeriodOffsetRelativeTimestamp.wrap(uint32(offsetStartTime)));
ObservationLib.Observation memory startObservation = _getPreviousOrAtObservation(
_observations,
_accountDetails,
PeriodOffsetRelativeTimestamp.wrap(uint32(offsetStartTime))
);

if (startObservation.timestamp != offsetStartTime) {
startObservation = _calculateTemporaryObservation(
Expand Down Expand Up @@ -335,7 +353,9 @@ library TwabLib {
AccountDetails memory newAccountDetails
)
{
PeriodOffsetRelativeTimestamp currentTime = PeriodOffsetRelativeTimestamp.wrap(uint32(block.timestamp - PERIOD_OFFSET));
PeriodOffsetRelativeTimestamp currentTime = PeriodOffsetRelativeTimestamp.wrap(
uint32(block.timestamp - PERIOD_OFFSET)
);

uint16 nextIndex;
ObservationLib.Observation memory newestObservation;
Expand Down Expand Up @@ -363,10 +383,7 @@ library TwabLib {
}

observation = ObservationLib.Observation({
cumulativeBalance: _extrapolateFromBalance(
newestObservation,
currentTime
),
cumulativeBalance: _extrapolateFromBalance(newestObservation, currentTime),
balance: _accountDetails.delegateBalance,
timestamp: PeriodOffsetRelativeTimestamp.unwrap(currentTime)
});
Expand Down Expand Up @@ -411,15 +428,15 @@ library TwabLib {
uint32 PERIOD_OFFSET,
ObservationLib.Observation[MAX_CARDINALITY] storage _observations,
AccountDetails memory _accountDetails
) private view returns (uint16 index, ObservationLib.Observation memory newestObservation, bool isNew) {
)
private
view
returns (uint16 index, ObservationLib.Observation memory newestObservation, bool isNew)
{
uint16 newestIndex;
(newestIndex, newestObservation) = getNewestObservation(_observations, _accountDetails);

uint256 currentPeriod = getTimestampPeriod(
PERIOD_LENGTH,
PERIOD_OFFSET,
block.timestamp
);
uint256 currentPeriod = getTimestampPeriod(PERIOD_LENGTH, PERIOD_OFFSET, block.timestamp);

uint256 newestObservationPeriod = getTimestampPeriod(
PERIOD_LENGTH,
Expand Down Expand Up @@ -462,9 +479,12 @@ library TwabLib {
) private pure returns (uint128) {
// new cumulative balance = provided cumulative balance (or zero) + (current balance * elapsed seconds)
unchecked {
return uint128(
uint256(_observation.cumulativeBalance) + uint256(_observation.balance) * (PeriodOffsetRelativeTimestamp.unwrap(_offsetTimestamp) - _observation.timestamp)
);
return
uint128(
uint256(_observation.cumulativeBalance) +
uint256(_observation.balance) *
(PeriodOffsetRelativeTimestamp.unwrap(_offsetTimestamp) - _observation.timestamp)
);
}
}

Expand Down Expand Up @@ -549,9 +569,14 @@ library TwabLib {
return ObservationLib.Observation({ cumulativeBalance: 0, balance: 0, timestamp: 0 });
}
uint256 offsetTargetTime = _targetTime - PERIOD_OFFSET;
// if this is for an overflowed time period, return 0
// if this is for an overflowed time period, return 0
if (offsetTargetTime > type(uint32).max) {
return ObservationLib.Observation({ cumulativeBalance: 0, balance: 0, timestamp: type(uint32).max });
return
ObservationLib.Observation({
cumulativeBalance: 0,
balance: 0,
timestamp: type(uint32).max
});
}
prevOrAtObservation = _getPreviousOrAtObservation(
_observations,
Expand All @@ -572,11 +597,7 @@ library TwabLib {
ObservationLib.Observation[MAX_CARDINALITY] storage _observations,
AccountDetails memory _accountDetails,
PeriodOffsetRelativeTimestamp _offsetTargetTime
)
private
view
returns (ObservationLib.Observation memory prevOrAtObservation)
{
) private view returns (ObservationLib.Observation memory prevOrAtObservation) {
// If there are no observations, return a zeroed observation
if (_accountDetails.cardinality == 0) {
return ObservationLib.Observation({ cumulativeBalance: 0, balance: 0, timestamp: 0 });
Expand All @@ -590,10 +611,18 @@ library TwabLib {
if (PeriodOffsetRelativeTimestamp.unwrap(_offsetTargetTime) < prevOrAtObservation.timestamp) {
// if the user didn't have any activity prior to the oldest observation, then we know they had a zero balance
if (_accountDetails.cardinality < MAX_CARDINALITY) {
return ObservationLib.Observation({ cumulativeBalance: 0, balance: 0, timestamp: PeriodOffsetRelativeTimestamp.unwrap(_offsetTargetTime) });
return
ObservationLib.Observation({
cumulativeBalance: 0,
balance: 0,
timestamp: PeriodOffsetRelativeTimestamp.unwrap(_offsetTargetTime)
});
} else {
// if we are missing their history, we must revert
revert InsufficientHistory(_offsetTargetTime, PeriodOffsetRelativeTimestamp.wrap(prevOrAtObservation.timestamp));
revert InsufficientHistory(
_offsetTargetTime,
PeriodOffsetRelativeTimestamp.wrap(prevOrAtObservation.timestamp)
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/ObservationLib.t.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-3.0
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { ObservationLib, MAX_CARDINALITY } from "../src/libraries/ObservationLib.sol";
Expand Down

0 comments on commit 061cb4c

Please sign in to comment.