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

feat(licenses): update license and G9 Software name #28

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
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
Loading
Loading