Skip to content

Commit

Permalink
Merge pull request #30 from euler-xyz/improve/harvest
Browse files Browse the repository at this point in the history
Feat: net yield/loss
  • Loading branch information
haythemsellami authored Jun 27, 2024
2 parents 5c726a5 + 293dc42 commit 1c6f7ff
Show file tree
Hide file tree
Showing 26 changed files with 663 additions and 369 deletions.
279 changes: 136 additions & 143 deletions src/AggregationLayerVault.sol

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions src/AggregationLayerVaultFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import {Rewards} from "./module/Rewards.sol";
import {Hooks} from "./module/Hooks.sol";
import {Fee} from "./module/Fee.sol";
import {WithdrawalQueue} from "./plugin/WithdrawalQueue.sol";
import {AggregationLayerVault} from "./AggregationLayerVault.sol";
import {AggregationLayerVault, IAggregationLayerVault} from "./AggregationLayerVault.sol";
// libs
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";

/// @title AggregationLayerVaultFactory contract
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
contract AggregationLayerVaultFactory {
/// core dependencies
address public immutable evc;
Expand All @@ -25,6 +28,7 @@ contract AggregationLayerVaultFactory {
/// @dev WithdrawalQueue plugin implementation address, need to be deployed per aggregation vault
address public immutable withdrawalQueueImpl;

/// @dev Init params struct.
struct FactoryParams {
address evc;
address balanceTracker;
Expand All @@ -36,6 +40,8 @@ contract AggregationLayerVaultFactory {
address withdrawalQueueImpl;
}

/// @notice Constructor.
/// @param _factoryParams FactoryParams struct.
constructor(FactoryParams memory _factoryParams) {
evc = _factoryParams.evc;
balanceTracker = _factoryParams.balanceTracker;
Expand All @@ -48,6 +54,15 @@ contract AggregationLayerVaultFactory {
withdrawalQueueImpl = _factoryParams.withdrawalQueueImpl;
}

/// @notice Deploy a new aggregation layer vault.
/// @dev This will clone a new WithdrawalQueue plugin instance for the aggregation layer vault.
/// @dev This will use the defaut Rebalancer plugin configured in this factory.
/// @dev Both plugins are possible to change by the aggregation layer vault manager.
/// @param _asset Aggreation layer vault' asset address.
/// @param _name Vaut name.
/// @param _symbol Vault symbol.
/// @param _initialCashAllocationPoints The amount of points to initally allocate for cash reserve.
/// @return aggregationLayerVault The address of the new deployed aggregation layer vault.
function deployEulerAggregationLayer(
address _asset,
string memory _name,
Expand All @@ -67,7 +82,7 @@ contract AggregationLayerVaultFactory {
AggregationLayerVault aggregationLayerVault =
new AggregationLayerVault(rewardsModuleAddr, hooksModuleAddr, feeModuleAddr, allocationpointsModuleAddr);

AggregationLayerVault.InitParams memory aggregationVaultInitParams = AggregationLayerVault.InitParams({
IAggregationLayerVault.InitParams memory aggregationVaultInitParams = IAggregationLayerVault.InitParams({
evc: evc,
balanceTracker: balanceTracker,
withdrawalQueuePeriphery: address(withdrawalQueue),
Expand Down
5 changes: 5 additions & 0 deletions src/Dispatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import {Shared} from "./Shared.sol";
import {HooksModule} from "./module/Hooks.sol";
import {RewardsModule} from "./module/Rewards.sol";

/// @title Dispatch contract
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @dev This contract implement the modifier to use for forwarding calls to a specific module using delegateCall.
/// @dev Copied from https://github.com/euler-xyz/euler-vault-kit/blob/55d1a1fd7d572372f1c8b9f58aba0604bda3ca4f/src/EVault/Dispatch.sol.
abstract contract Dispatch is RewardsModule, HooksModule {
address public immutable MODULE_REWARDS;
address public immutable MODULE_HOOKS;
Expand Down
15 changes: 9 additions & 6 deletions src/Shared.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {IEVC} from "ethereum-vault-connector/utils/EVCUtil.sol";
import {IHookTarget} from "evk/src/interfaces/IHookTarget.sol";
// libs
import {StorageLib, AggregationVaultStorage} from "./lib/StorageLib.sol";
import {ErrorsLib} from "./lib/ErrorsLib.sol";
import {HooksLib} from "./lib/HooksLib.sol";
import {ErrorsLib as Errors} from "./lib/ErrorsLib.sol";

/// @title Shared contract
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
contract Shared {
using HooksLib for uint32;

Expand All @@ -28,7 +31,7 @@ contract Shared {
modifier nonReentrant() {
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

if ($.locked == REENTRANCYLOCK__LOCKED) revert ErrorsLib.Reentrancy();
if ($.locked == REENTRANCYLOCK__LOCKED) revert Errors.Reentrancy();

$.locked = REENTRANCYLOCK__LOCKED;
_;
Expand All @@ -49,12 +52,12 @@ contract Shared {
function _setHooksConfig(address _hooksTarget, uint32 _hookedFns) internal {
if (_hooksTarget != address(0) && IHookTarget(_hooksTarget).isHookTarget() != IHookTarget.isHookTarget.selector)
{
revert ErrorsLib.NotHooksContract();
revert Errors.NotHooksContract();
}
if (_hookedFns != 0 && _hooksTarget == address(0)) {
revert ErrorsLib.InvalidHooksTarget();
revert Errors.InvalidHooksTarget();
}
if (_hookedFns >= ACTIONS_COUNTER) revert ErrorsLib.InvalidHookedFns();
if (_hookedFns >= ACTIONS_COUNTER) revert Errors.InvalidHookedFns();

AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();
$.hooksConfig = (uint256(uint160(_hooksTarget)) << 32) | uint256(_hookedFns);
Expand Down Expand Up @@ -91,6 +94,6 @@ contract Shared {
}
}

revert ErrorsLib.EmptyError();
revert Errors.EmptyError();
}
}
58 changes: 58 additions & 0 deletions src/interface/IAggregationLayerVault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IAggregationLayerVault {
/// @dev Struct to pass init() call params.
struct InitParams {
address evc;
address balanceTracker;
address withdrawalQueuePeriphery;
address rebalancerPerihpery;
address aggregationVaultOwner;
address asset;
string name;
string symbol;
uint256 initialCashAllocationPoints;
}

/// @dev A struct that hold a strategy allocation's config
/// allocated: amount of asset deposited into strategy
/// allocationPoints: number of points allocated to this strategy
/// active: a boolean to indice if this strategy is active or not
/// cap: an optional cap in terms of deposited underlying asset. By default, it is set to 0(not activated)
struct Strategy {
uint120 allocated;
uint120 allocationPoints;
bool active;
uint120 cap;
}

/// @dev Euler saving rate struct
/// @dev Based on https://github.com/euler-xyz/euler-vault-kit/blob/master/src/Synths/EulerSavingsRate.sol
/// lastInterestUpdate: last timestamo where interest was updated.
/// interestSmearEnd: timestamp when the smearing of interest end.
/// interestLeft: amount of interest left to smear.
/// locked: if locked or not for update.
struct AggregationVaultSavingRate {
uint40 lastInterestUpdate;
uint40 interestSmearEnd;
uint168 interestLeft;
uint8 locked;
}

function rebalance(address _strategy, uint256 _amountToRebalance, bool _isDeposit) external;
function gulp() external;
function harvest() external;
function executeStrategyWithdraw(address _strategy, uint256 _withdrawAmount) external;
function executeAggregationVaultWithdraw(
address caller,
address receiver,
address owner,
uint256 assets,
uint256 shares
) external;
function getStrategy(address _strategy) external view returns (Strategy memory);
function totalAllocationPoints() external view returns (uint256);
function totalAllocated() external view returns (uint256);
function totalAssetsAllocatable() external view returns (uint256);
}
22 changes: 0 additions & 22 deletions src/interface/IFourSixTwoSixAgg.sol

This file was deleted.

6 changes: 3 additions & 3 deletions src/interface/IWithdrawalQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ interface IWithdrawalQueue {
address owner,
uint256 assets,
uint256 shares,
uint256 availableAssets,
bool _isRedeem
) external returns (uint256, uint256);
uint256 availableAssets
) external;
function reorderWithdrawalQueue(uint8 _index1, uint8 _index2) external;

function withdrawalQueueLength() external view returns (uint256);
function getWithdrawalQueueArray() external view returns (address[] memory, uint256);
}
3 changes: 2 additions & 1 deletion src/lib/EventsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ pragma solidity ^0.8.0;
library EventsLib {
/// @dev AggregationLayerVault events
event Gulp(uint256 interestLeft, uint256 interestSmearEnd);
event Harvest(address indexed strategy, uint256 strategyBalanceAmount, uint256 strategyAllocatedAmount);
event AccruePerformanceFee(address indexed feeRecipient, uint256 yield, uint256 feeAssets);
event Rebalance(address indexed strategy, uint256 amountToRebalance, bool isDeposit);
event ExecuteHarvest(address indexed strategy, uint256 strategyBalanceAmount, uint256 strategyAllocatedAmount);
event Harvest(uint256 totalAllocated, uint256 totlaYield, uint256 totalLoss);

/// @dev Allocationpoints events
event AdjustAllocationPoints(address indexed strategy, uint256 oldPoints, uint256 newPoints);
Expand Down
37 changes: 15 additions & 22 deletions src/lib/StorageLib.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

// interfaces
import {IAggregationLayerVault} from "../interface/IAggregationLayerVault.sol";

/// @custom:storage-location erc7201:euler_aggregation_vault.storage.AggregationVault
struct AggregationVaultStorage {
/// @dev EVC address
/// EVC address
address evc;
/// @dev Total amount of _asset deposited into AggregationLayerVault contract
/// Total amount of _asset deposited into AggregationLayerVault contract
uint256 totalAssetsDeposited;
/// @dev Total amount of _asset deposited across all strategies.
/// Total amount of _asset deposited across all strategies.
uint256 totalAllocated;
/// @dev Total amount of allocation points across all strategies including the cash reserve.
/// Total amount of allocation points across all strategies including the cash reserve.
uint256 totalAllocationPoints;
/// @dev fee rate
/// fee rate
uint256 performanceFee;
/// @dev fee recipient address
/// fee recipient address
address feeRecipient;
/// @dev Withdrawal queue contract's address
/// Withdrawal queue contract's address
address withdrawalQueue;
/// @dev Mapping between strategy address and it's allocation config
mapping(address => Strategy) strategies;
/// Mapping between strategy address and it's allocation config
mapping(address => IAggregationLayerVault.Strategy) strategies;


/// lastInterestUpdate: last timestamo where interest was updated.
Expand All @@ -30,32 +33,22 @@ struct AggregationVaultStorage {
/// locked: if locked or not for update.
uint8 locked;


/// Address of balance tracker contract for reward streams integration.
address balanceTracker;
/// A mapping to check if a user address enabled balance forwarding for reward streams integration.
mapping(address => bool) isBalanceForwarderEnabled;


/// @dev storing the hooks target and kooked functions.
uint256 hooksConfig;
}

/// @dev A struct that hold a strategy allocation's config
/// allocated: amount of asset deposited into strategy
/// allocationPoints: number of points allocated to this strategy
/// active: a boolean to indice if this strategy is active or not
/// cap: an optional cap in terms of deposited underlying asset. By default, it is set to 0(not activated)
struct Strategy {
uint120 allocated;
uint120 allocationPoints;
bool active;
uint120 cap;
}

library StorageLib {
// keccak256(abi.encode(uint256(keccak256("euler_aggregation_vault.storage.AggregationVault")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AggregationVaultStorageLocation =
0x7da5ece5aff94f3377324d715703a012d3253da37511270103c646f171c0aa00;

/// @dev A function to return a pointer for the AggregationVaultStorageLocation.
function _getAggregationVaultStorage() internal pure returns (AggregationVaultStorage storage $) {
assembly {
$.slot := AggregationVaultStorageLocation
Expand Down
Loading

0 comments on commit 1c6f7ff

Please sign in to comment.