Skip to content

Commit

Permalink
accrue performance fee in underlying asset
Browse files Browse the repository at this point in the history
  • Loading branch information
haythemsellami committed Jun 14, 2024
1 parent b0232f3 commit 199ca17
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 10 deletions.
24 changes: 16 additions & 8 deletions src/FourSixTwoSixAgg.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ contract FourSixTwoSixAgg is IFourSixTwoSixAgg, BalanceForwarder, EVCUtil, ERC46
event ReorderWithdrawalQueue(uint8 index1, uint8 index2);
event AddStrategy(address indexed strategy, uint256 allocationPoints);
event RemoveStrategy(address indexed _strategy);
event AccruePerformanceFee(address indexed feeRecipient, uint256 performanceFee, uint256 yield, uint256 feeShares);
event AccruePerformanceFee(address indexed feeRecipient, uint256 yield, uint256 feeAssets);
event SetStrategyCap(address indexed strategy, uint256 cap);
event Rebalance(address indexed strategy, uint256 _amountToRebalance, bool _isDeposit);

Expand Down Expand Up @@ -609,10 +609,15 @@ contract FourSixTwoSixAgg is IFourSixTwoSixAgg, BalanceForwarder, EVCUtil, ERC46
} else if (underlyingBalance > strategyAllocatedAmount) {
// There's yield!
uint256 yield = underlyingBalance - strategyAllocatedAmount;
uint120 accruedPerformanceFee = _accruePerformanceFee(_strategy, yield);

if (accruedPerformanceFee != 0) {
underlyingBalance -= accruedPerformanceFee;
yield -= accruedPerformanceFee;
}

strategies[_strategy].allocated = uint120(underlyingBalance);
totalAllocated += yield;

_accruePerformanceFee(yield);
} else {
uint256 loss = strategyAllocatedAmount - underlyingBalance;

Expand All @@ -632,19 +637,22 @@ contract FourSixTwoSixAgg is IFourSixTwoSixAgg, BalanceForwarder, EVCUtil, ERC46
emit Harvest(_strategy, underlyingBalance, strategyAllocatedAmount);
}

function _accruePerformanceFee(uint256 _yield) internal {
function _accruePerformanceFee(address _strategy, uint256 _yield) internal returns (uint120) {
address cachedFeeRecipient = feeRecipient;
uint256 cachedPerformanceFee = performanceFee;

if (cachedFeeRecipient == address(0) || cachedPerformanceFee == 0) return;
if (cachedFeeRecipient == address(0) || cachedPerformanceFee == 0) return 0;

// `feeAssets` will be rounded down to 0 if `yield * performanceFee < 1e18`.
uint256 feeAssets = Math.mulDiv(_yield, cachedPerformanceFee, 1e18, Math.Rounding.Down);
uint256 feeShares = _convertToShares(feeAssets, Math.Rounding.Down);

if (feeShares != 0) _mint(cachedFeeRecipient, feeShares);
if(feeAssets > 0) {
IERC4626(_strategy).withdraw(feeAssets, cachedFeeRecipient, address(this));
}

emit AccruePerformanceFee(cachedFeeRecipient, _yield, feeAssets);

emit AccruePerformanceFee(cachedFeeRecipient, cachedPerformanceFee, _yield, feeShares);
return feeAssets.toUint120();
}

/// @dev Override _afterTokenTransfer hook to call IBalanceTracker.balanceTrackerHook()
Expand Down
3 changes: 1 addition & 2 deletions test/e2e/PerformanceFeeE2ETest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,12 @@ contract PerformanceFeeE2ETest is FourSixTwoSixAggBase {
}

uint256 expectedPerformanceFee = yield * fourSixTwoSixAgg.performanceFee() / 1e18;
uint256 expectedPerformanceFeeShares = fourSixTwoSixAgg.convertToShares(expectedPerformanceFee);

// harvest
vm.prank(user1);
fourSixTwoSixAgg.harvest(address(eTST));

assertEq(fourSixTwoSixAgg.balanceOf(feeRecipient), expectedPerformanceFeeShares);
assertEq(assetTST.balanceOf(feeRecipient), expectedPerformanceFee);

// full withdraw, will have to withdraw from strategy as cash reserve is not enough
{
Expand Down

0 comments on commit 199ca17

Please sign in to comment.