Skip to content

Commit

Permalink
Merge pull request #25 from euler-xyz/update-performance-fee
Browse files Browse the repository at this point in the history
Feat:accrue performance fee in underlying asset
  • Loading branch information
haythemsellami authored Jun 14, 2024
2 parents b0232f3 + 82d3431 commit 46fc6e9
Show file tree
Hide file tree
Showing 2 changed files with 25 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
11 changes: 9 additions & 2 deletions test/e2e/PerformanceFeeE2ETest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,20 @@ contract PerformanceFeeE2ETest is FourSixTwoSixAggBase {
}

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

FourSixTwoSixAgg.Strategy memory strategyBeforeHarvest = fourSixTwoSixAgg.getStrategy(address(eTST));
uint256 totalAllocatedBefore = fourSixTwoSixAgg.totalAllocated();

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

assertEq(fourSixTwoSixAgg.balanceOf(feeRecipient), expectedPerformanceFeeShares);
assertEq(assetTST.balanceOf(feeRecipient), expectedPerformanceFee);
assertEq(
fourSixTwoSixAgg.getStrategy(address(eTST)).allocated,
strategyBeforeHarvest.allocated + yield - expectedPerformanceFee
);
assertEq(fourSixTwoSixAgg.totalAllocated(), totalAllocatedBefore + yield - expectedPerformanceFee);

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

0 comments on commit 46fc6e9

Please sign in to comment.