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

build: instant profit unlocking #63

Merged
merged 5 commits into from
Aug 31, 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
41 changes: 29 additions & 12 deletions src/TokenizedStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -938,9 +938,11 @@ contract TokenizedStrategy {
// Burn unlocked shares.
_burnUnlockedShares();

// Initialize varaibles needed throughout.
uint256 totalFees;
uint256 protocolFees;
uint256 sharesToLock;
uint256 _profitMaxUnlockTime = S.profitMaxUnlockTime;
// Calculate profit/loss.
if (newTotalAssets > oldTotalAssets) {
// We have a profit.
Expand Down Expand Up @@ -978,13 +980,15 @@ contract TokenizedStrategy {
}
}

// we have a net profit
// lock (profit - fees)
unchecked {
sharesToLock = convertToShares(profit - totalFees);
// we have a net profit. Check if we are locking proifit.
if (_profitMaxUnlockTime != 0) {
// lock (profit - fees)
unchecked {
sharesToLock = convertToShares(profit - totalFees);
}
// Mint the shares to lock the strategy.
_mint(address(this), sharesToLock);
}
// Mint the shares to lock the strategy.
_mint(address(this), sharesToLock);

// Mint fees shares to recipients.
if (performanceFeeShares != 0) {
Expand All @@ -1005,8 +1009,8 @@ contract TokenizedStrategy {
// We will try and burn shares from any pending profit still unlocking
// to offset the loss to prevent any PPS decline post report.
uint256 sharesToBurn = Math.min(
convertToShares(loss),
S.balances[address(this)]
S.balances[address(this)],
convertToShares(loss)
);

// Check if there is anything to burn.
Expand Down Expand Up @@ -1036,7 +1040,7 @@ contract TokenizedStrategy {
// time of the previously locked shares and the profitMaxUnlockTime.
uint256 newProfitLockingPeriod = (previouslyLockedTime +
sharesToLock *
S.profitMaxUnlockTime) / totalLockedShares;
_profitMaxUnlockTime) / totalLockedShares;

// Calculate how many shares unlock per second.
S.profitUnlockingRate =
Expand Down Expand Up @@ -1450,6 +1454,9 @@ contract TokenizedStrategy {
*
* Denominated in seconds and cannot be greater than 1 year.
*
* NOTE: Setting to 0 will cause all currently locked profit
* to be unlocked instantly and should be done with care.
*
* `profitMaxUnlockTime` is stored as a uint32 for packing but can
* be passed in as uint256 for simplicity.
*
Expand All @@ -1458,10 +1465,20 @@ contract TokenizedStrategy {
function setProfitMaxUnlockTime(
uint256 _profitMaxUnlockTime
) external onlyManagement {
// Must be greater than 0, and less than a year.
require(_profitMaxUnlockTime != 0, "too short");
// Must be less than a year.
require(_profitMaxUnlockTime <= SECONDS_PER_YEAR, "too long");
_strategyStorage().profitMaxUnlockTime = uint32(_profitMaxUnlockTime);
StrategyData storage S = _strategyStorage();

// If we are setting to 0 we need to adjust amounts.
if (_profitMaxUnlockTime == 0) {
// Burn all shares if applicable.
_burn(address(this), S.balances[address(this)]);
// Reset unlocking variables
S.profitUnlockingRate = 0;
S.fullProfitUnlockDate = 0;
}

S.profitMaxUnlockTime = uint32(_profitMaxUnlockTime);

emit UpdateProfitMaxUnlockTime(_profitMaxUnlockTime);
}
Expand Down
5 changes: 0 additions & 5 deletions src/test/AccessControl.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,6 @@ contract AccesssControlTest is Setup {
vm.expectRevert("too long");
strategy.setProfitMaxUnlockTime(_badAmount);

// Can't be 0
vm.prank(management);
vm.expectRevert("too short");
strategy.setProfitMaxUnlockTime(0);

assertEq(strategy.profitMaxUnlockTime(), profitMaxUnlockTime);
}

Expand Down
Loading
Loading