diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 16f20b19..751c33a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: version: nightly - name: Run foundry build - run: forge build --sizes + run: forge build --force --sizes - name: Run foundry fmt check run: forge fmt --check diff --git a/foundry.toml b/foundry.toml index 32d5e99e..401821aa 100644 --- a/foundry.toml +++ b/foundry.toml @@ -18,7 +18,7 @@ quote_style = "double" number_underscore = "preserve" override_spacing = true ignore = [ - "src/lib/StorageLib.sol" + "src/core/lib/StorageLib.sol" ] [profile.test] diff --git a/src/core/EulerAggregationLayer.sol b/src/core/EulerAggregationLayer.sol index fc108298..2828e288 100644 --- a/src/core/EulerAggregationLayer.sol +++ b/src/core/EulerAggregationLayer.sol @@ -47,10 +47,8 @@ contract EulerAggregationLayer is bytes32 public constant STRATEGY_ADDER_ADMIN = keccak256("STRATEGY_ADDER_ADMIN"); bytes32 public constant STRATEGY_REMOVER = keccak256("STRATEGY_REMOVER"); bytes32 public constant STRATEGY_REMOVER_ADMIN = keccak256("STRATEGY_REMOVER_ADMIN"); - bytes32 public constant AGGREGATION_VAULT_MANAGER = keccak256("AGGREGATION_VAULT_MANAGER"); - bytes32 public constant AGGREGATION_VAULT_MANAGER_ADMIN = keccak256("AGGREGATION_VAULT_MANAGER_ADMIN"); - bytes32 public constant REBALANCER = keccak256("REBALANCER"); - bytes32 public constant REBALANCER_ADMIN = keccak256("REBALANCER_ADMIN"); + bytes32 public constant AGGREGATION_LAYER_MANAGER = keccak256("AGGREGATION_LAYER_MANAGER"); + bytes32 public constant AGGREGATION_LAYER_MANAGER_ADMIN = keccak256("AGGREGATION_LAYER_MANAGER_ADMIN"); /// @dev interest rate smearing period uint256 public constant INTEREST_SMEAR = 2 weeks; @@ -70,6 +68,7 @@ contract EulerAggregationLayer is AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); $.locked = REENTRANCYLOCK__UNLOCKED; $.withdrawalQueue = _initParams.withdrawalQueuePlugin; + $.rebalancer = _initParams.rebalancerPlugin; $.strategies[address(0)] = IEulerAggregationLayer.Strategy({ allocated: 0, allocationPoints: _initParams.initialCashAllocationPoints.toUint120(), @@ -80,30 +79,26 @@ contract EulerAggregationLayer is $.balanceTracker = _initParams.balanceTracker; // Setup DEFAULT_ADMIN - _grantRole(DEFAULT_ADMIN_ROLE, _initParams.aggregationVaultOwner); + _grantRole(DEFAULT_ADMIN_ROLE, _initParams.aggregationLayerOwner); // Setup role admins _setRoleAdmin(ALLOCATIONS_MANAGER, ALLOCATIONS_MANAGER_ADMIN); _setRoleAdmin(STRATEGY_ADDER, STRATEGY_ADDER_ADMIN); _setRoleAdmin(STRATEGY_REMOVER, STRATEGY_REMOVER_ADMIN); - _setRoleAdmin(AGGREGATION_VAULT_MANAGER, AGGREGATION_VAULT_MANAGER_ADMIN); - _setRoleAdmin(REBALANCER, REBALANCER_ADMIN); - - // By default, the Rebalancer contract is assigned the REBALANCER role - _grantRole(REBALANCER, _initParams.rebalancerPlugin); + _setRoleAdmin(AGGREGATION_LAYER_MANAGER, AGGREGATION_LAYER_MANAGER_ADMIN); } /// @dev See {FeeModule-setFeeRecipient}. - function setFeeRecipient(address _newFeeRecipient) external onlyRole(AGGREGATION_VAULT_MANAGER) use(MODULE_FEE) {} + function setFeeRecipient(address _newFeeRecipient) external onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_FEE) {} /// @dev See {FeeModule-setPerformanceFee}. - function setPerformanceFee(uint256 _newFee) external onlyRole(AGGREGATION_VAULT_MANAGER) use(MODULE_FEE) {} + function setPerformanceFee(uint256 _newFee) external onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_FEE) {} /// @dev See {RewardsModule-optInStrategyRewards}. function optInStrategyRewards(address _strategy) external override - onlyRole(AGGREGATION_VAULT_MANAGER) + onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_REWARDS) {} @@ -111,7 +106,7 @@ contract EulerAggregationLayer is function optOutStrategyRewards(address _strategy) external override - onlyRole(AGGREGATION_VAULT_MANAGER) + onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_REWARDS) {} @@ -119,7 +114,7 @@ contract EulerAggregationLayer is function enableRewardForStrategy(address _strategy, address _reward) external override - onlyRole(AGGREGATION_VAULT_MANAGER) + onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_REWARDS) {} @@ -127,7 +122,7 @@ contract EulerAggregationLayer is function disableRewardForStrategy(address _strategy, address _reward, bool _forfeitRecentReward) external override - onlyRole(AGGREGATION_VAULT_MANAGER) + onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_REWARDS) {} @@ -135,15 +130,17 @@ contract EulerAggregationLayer is function claimStrategyReward(address _strategy, address _reward, address _recipient, bool _forfeitRecentReward) external override - onlyRole(AGGREGATION_VAULT_MANAGER) + onlyRole(AGGREGATION_LAYER_MANAGER) use(MODULE_REWARDS) {} - /// @dev See {RewardsModule-enableBalanceForwarder}. - function enableBalanceForwarder() external override use(MODULE_REWARDS) {} - - /// @dev See {RewardsModule-disableBalanceForwarder}. - function disableBalanceForwarder() external override use(MODULE_REWARDS) {} + /// @dev See {HooksModule-setHooksConfig}. + function setHooksConfig(address _hooksTarget, uint32 _hookedFns) + external + override + onlyRole(AGGREGATION_LAYER_MANAGER) + use(MODULE_HOOKS) + {} /// @dev See {AllocationPointsModule-adjustAllocationPoints}. function adjustAllocationPoints(address _strategy, uint256 _newPoints) @@ -169,26 +166,48 @@ contract EulerAggregationLayer is /// @dev See {AllocationPointsModule-removeStrategy}. function removeStrategy(address _strategy) external use(MODULE_ALLOCATION_POINTS) onlyRole(STRATEGY_REMOVER) {} - /// @dev See {HooksModule-setHooksConfig}. - function setHooksConfig(address _hooksTarget, uint32 _hookedFns) - external - override - onlyRole(AGGREGATION_VAULT_MANAGER) - use(MODULE_HOOKS) - {} + /// @dev See {RewardsModule-enableBalanceForwarder}. + function enableBalanceForwarder() external override use(MODULE_REWARDS) {} + + /// @dev See {RewardsModule-disableBalanceForwarder}. + function disableBalanceForwarder() external override use(MODULE_REWARDS) {} + + /// @notice Set a new address for WithdrawalQueue plugin. + /// @dev Can only be called by an address with the `AGGREGATION_LAYER_MANAGER` role. + /// @param _withdrawalQueue New WithdrawalQueue contract address. + function setWithdrawalQueue(address _withdrawalQueue) external onlyRole(AGGREGATION_LAYER_MANAGER) { + if (_withdrawalQueue == address(0)) revert Errors.InvalidPlugin(); + + AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); + + emit Events.SetWithdrawalQueue($.withdrawalQueue, _withdrawalQueue); + + $.withdrawalQueue = _withdrawalQueue; + } + + /// @notice Set a new address for Rebalancer plugin. + /// @dev Can only be called by an address with the `AGGREGATION_LAYER_MANAGER` role. + /// @param _rebalancer New Rebalancer contract address. + function setRebalancer(address _rebalancer) external onlyRole(AGGREGATION_LAYER_MANAGER) { + if (_rebalancer == address(0)) revert Errors.InvalidPlugin(); + + AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); + + emit Events.SetRebalancer($.rebalancer, _rebalancer); + + $.rebalancer = _rebalancer; + } /// @notice Rebalance strategy by depositing or withdrawing the amount to rebalance to hit target allocation. - /// @dev Can only be called by an address that hold the REBALANCER role. + /// @dev Can only be called only by the WithdrawalQueue plugin. /// @param _strategy Strategy address. /// @param _amountToRebalance Amount to deposit or withdraw. /// @param _isDeposit bool to indicate if it is a deposit or a withdraw. - function rebalance(address _strategy, uint256 _amountToRebalance, bool _isDeposit) - external - nonReentrant - onlyRole(REBALANCER) - { + function rebalance(address _strategy, uint256 _amountToRebalance, bool _isDeposit) external nonReentrant { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); + if (_msgSender() != $.rebalancer) revert Errors.NotRebalancer(); + IEulerAggregationLayer.Strategy memory strategyData = $.strategies[_strategy]; if (_isDeposit) { @@ -295,30 +314,49 @@ contract EulerAggregationLayer is return avsr; } + /// @notice Get the total allocated amount. + /// @return uint256 Total allocated. function totalAllocated() external view returns (uint256) { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); return $.totalAllocated; } + /// @notice Get the total allocation points. + /// @return uint256 Total allocation points. function totalAllocationPoints() external view returns (uint256) { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); return $.totalAllocationPoints; } + /// @notice Get the total assets deposited into the aggregation layer. + /// @return uint256 Total assets deposited. function totalAssetsDeposited() external view returns (uint256) { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); return $.totalAssetsDeposited; } + /// @notice Get the WithdrawalQueue plugin address. + /// @return address Withdrawal queue address. function withdrawalQueue() external view returns (address) { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); return $.withdrawalQueue; } + /// @notice Get the Rebalancer plugin address. + /// @return address Rebalancer address. + function rebalancer() external view returns (address) { + AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); + + return $.rebalancer; + } + + /// @notice Get the performance fee config. + /// @return adddress Fee recipient. + /// @return uint256 Fee percentage. function performanceFeeConfig() external view returns (address, uint256) { AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage(); diff --git a/src/core/EulerAggregationLayerFactory.sol b/src/core/EulerAggregationLayerFactory.sol index 83ea71b3..b32b454c 100644 --- a/src/core/EulerAggregationLayerFactory.sol +++ b/src/core/EulerAggregationLayerFactory.sol @@ -83,7 +83,7 @@ contract EulerAggregationLayerFactory { balanceTracker: balanceTracker, withdrawalQueuePlugin: address(withdrawalQueue), rebalancerPlugin: rebalancer, - aggregationVaultOwner: msg.sender, + aggregationLayerOwner: msg.sender, asset: _asset, name: _name, symbol: _symbol, diff --git a/src/core/interface/IEulerAggregationLayer.sol b/src/core/interface/IEulerAggregationLayer.sol index f516bee5..9d0d2287 100644 --- a/src/core/interface/IEulerAggregationLayer.sol +++ b/src/core/interface/IEulerAggregationLayer.sol @@ -7,7 +7,7 @@ interface IEulerAggregationLayer { address balanceTracker; address withdrawalQueuePlugin; address rebalancerPlugin; - address aggregationVaultOwner; + address aggregationLayerOwner; address asset; string name; string symbol; diff --git a/src/core/lib/ErrorsLib.sol b/src/core/lib/ErrorsLib.sol index b7ed440b..2f08f156 100644 --- a/src/core/lib/ErrorsLib.sol +++ b/src/core/lib/ErrorsLib.sol @@ -24,4 +24,6 @@ library ErrorsLib { error InvalidHookedFns(); error EmptyError(); error NotWithdrawaQueue(); + error InvalidPlugin(); + error NotRebalancer(); } diff --git a/src/core/lib/EventsLib.sol b/src/core/lib/EventsLib.sol index 024b6915..7c4df926 100644 --- a/src/core/lib/EventsLib.sol +++ b/src/core/lib/EventsLib.sol @@ -8,6 +8,8 @@ library EventsLib { 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); + event SetWithdrawalQueue(address _oldWithdrawalQueuePlugin, address _newWithdrawalQueuePlugin); + event SetRebalancer(address _oldRebalancer, address _newRebalancer); /// @dev Allocationpoints events event AdjustAllocationPoints(address indexed strategy, uint256 oldPoints, uint256 newPoints); diff --git a/src/core/lib/StorageLib.sol b/src/core/lib/StorageLib.sol index 9bc480d8..21fcd2e2 100644 --- a/src/core/lib/StorageLib.sol +++ b/src/core/lib/StorageLib.sol @@ -16,8 +16,10 @@ struct AggregationVaultStorage { uint256 performanceFee; /// fee recipient address address feeRecipient; - /// Withdrawal queue contract's address + /// WithdrawalQueue plugin address address withdrawalQueue; + /// Rebalancer plugin address + address rebalancer; /// Mapping between strategy address and it's allocation config mapping(address => IEulerAggregationLayer.Strategy) strategies; /// lastInterestUpdate: last timestamo where interest was updated. @@ -28,10 +30,14 @@ struct AggregationVaultStorage { uint168 interestLeft; /// 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; } diff --git a/src/plugin/Rebalancer.sol b/src/plugin/Rebalancer.sol index 57fea7d8..cef89eec 100644 --- a/src/plugin/Rebalancer.sol +++ b/src/plugin/Rebalancer.sol @@ -9,7 +9,6 @@ import {IERC4626} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.s /// @custom:security-contact security@euler.xyz /// @author Euler Labs (https://www.eulerlabs.com/) /// @notice A contract to execute rebalance() on the EulerAggregationLayer. -/// @dev Usually this contract will hold the `REBALANCER` role. contract Rebalancer { event ExecuteRebalance( address indexed curatedVault, diff --git a/test/common/EulerAggregationLayerBase.t.sol b/test/common/EulerAggregationLayerBase.t.sol index 159a85ef..5c43c086 100644 --- a/test/common/EulerAggregationLayerBase.t.sol +++ b/test/common/EulerAggregationLayerBase.t.sol @@ -76,15 +76,14 @@ contract EulerAggregationLayerBase is EVaultTestBase { eulerAggregationLayer.grantRole(eulerAggregationLayer.ALLOCATIONS_MANAGER_ADMIN(), deployer); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_ADDER_ADMIN(), deployer); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_REMOVER_ADMIN(), deployer); - eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER_ADMIN(), deployer); - eulerAggregationLayer.grantRole(eulerAggregationLayer.REBALANCER_ADMIN(), deployer); + eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER_ADMIN(), deployer); withdrawalQueue.grantRole(withdrawalQueue.WITHDRAW_QUEUE_MANAGER_ADMIN(), deployer); // grant roles to manager eulerAggregationLayer.grantRole(eulerAggregationLayer.ALLOCATIONS_MANAGER(), manager); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_ADDER(), manager); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_REMOVER(), manager); - eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER(), manager); + eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER(), manager); withdrawalQueue.grantRole(withdrawalQueue.WITHDRAW_QUEUE_MANAGER(), manager); vm.stopPrank(); @@ -110,8 +109,8 @@ contract EulerAggregationLayerBase is EVaultTestBase { eulerAggregationLayer.STRATEGY_REMOVER_ADMIN() ); assertEq( - eulerAggregationLayer.getRoleAdmin(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER()), - eulerAggregationLayer.AGGREGATION_VAULT_MANAGER_ADMIN() + eulerAggregationLayer.getRoleAdmin(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER()), + eulerAggregationLayer.AGGREGATION_LAYER_MANAGER_ADMIN() ); assertEq( withdrawalQueue.getRoleAdmin(withdrawalQueue.WITHDRAW_QUEUE_MANAGER()), @@ -121,13 +120,13 @@ contract EulerAggregationLayerBase is EVaultTestBase { assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.ALLOCATIONS_MANAGER_ADMIN(), deployer)); assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.STRATEGY_ADDER_ADMIN(), deployer)); assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.STRATEGY_REMOVER_ADMIN(), deployer)); - assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER_ADMIN(), deployer)); + assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER_ADMIN(), deployer)); assertTrue(withdrawalQueue.hasRole(withdrawalQueue.WITHDRAW_QUEUE_MANAGER_ADMIN(), deployer)); assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.ALLOCATIONS_MANAGER(), manager)); assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.STRATEGY_ADDER(), manager)); assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.STRATEGY_REMOVER(), manager)); - assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER(), manager)); + assertTrue(eulerAggregationLayer.hasRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER(), manager)); assertTrue(withdrawalQueue.hasRole(withdrawalQueue.WITHDRAW_QUEUE_MANAGER(), manager)); } diff --git a/test/e2e/BalanceForwarderE2ETest.t.sol b/test/e2e/BalanceForwarderE2ETest.t.sol index 58537e3d..63bf1521 100644 --- a/test/e2e/BalanceForwarderE2ETest.t.sol +++ b/test/e2e/BalanceForwarderE2ETest.t.sol @@ -46,14 +46,14 @@ contract BalanceForwarderE2ETest is EulerAggregationLayerBase { // eulerAggregationLayer.grantRole(eulerAggregationLayer.WITHDRAW_QUEUE_MANAGER_ADMIN(), deployer); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_ADDER_ADMIN(), deployer); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_REMOVER_ADMIN(), deployer); - eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER_ADMIN(), deployer); + eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER_ADMIN(), deployer); // grant roles to manager eulerAggregationLayer.grantRole(eulerAggregationLayer.ALLOCATIONS_MANAGER(), manager); // eulerAggregationLayer.grantRole(eulerAggregationLayer.WITHDRAW_QUEUE_MANAGER(), manager); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_ADDER(), manager); eulerAggregationLayer.grantRole(eulerAggregationLayer.STRATEGY_REMOVER(), manager); - eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_VAULT_MANAGER(), manager); + eulerAggregationLayer.grantRole(eulerAggregationLayer.AGGREGATION_LAYER_MANAGER(), manager); vm.stopPrank(); uint256 initialStrategyAllocationPoints = 500e18; diff --git a/test/unit/RebalanceTest.t.sol b/test/unit/RebalanceTest.t.sol index 4f7cb421..1206633e 100644 --- a/test/unit/RebalanceTest.t.sol +++ b/test/unit/RebalanceTest.t.sol @@ -9,7 +9,8 @@ import { IEVault, IRMTestDefault, TestERC20, - IEulerAggregationLayer + IEulerAggregationLayer, + ErrorsLib } from "../common/EulerAggregationLayerBase.t.sol"; contract RebalanceTest is EulerAggregationLayerBase { @@ -346,4 +347,11 @@ contract RebalanceTest is EulerAggregationLayerBase { // ); // assertEq((eulerAggregationLayer.getStrategy(address(eTST))).allocated, strategyBefore.allocated - eTSTMaxWithdraw); } + + function testRebalanceFromRandomSender() public { + vm.startPrank(user1); + vm.expectRevert(ErrorsLib.NotRebalancer.selector); + eulerAggregationLayer.rebalance(address(eTST), 1, true); + vm.stopPrank(); + } } diff --git a/test/unit/SetRebalancerTest.t.sol b/test/unit/SetRebalancerTest.t.sol new file mode 100644 index 00000000..6073582d --- /dev/null +++ b/test/unit/SetRebalancerTest.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +import {EulerAggregationLayerBase, EulerAggregationLayer, ErrorsLib} from "../common/EulerAggregationLayerBase.t.sol"; + +contract SetRebalancerTest is EulerAggregationLayerBase { + function setUp() public virtual override { + super.setUp(); + } + + function testSetInvalidRebalancer() public { + vm.startPrank(manager); + vm.expectRevert(ErrorsLib.InvalidPlugin.selector); + eulerAggregationLayer.setRebalancer(address(0)); + } + + function testSetRebalancer() public { + address newRebalancer = makeAddr("Rebalancer"); + + vm.prank(manager); + eulerAggregationLayer.setRebalancer(newRebalancer); + + assertEq(eulerAggregationLayer.rebalancer(), newRebalancer); + } +} diff --git a/test/unit/SetWithdrawalQueueTest.t.sol b/test/unit/SetWithdrawalQueueTest.t.sol new file mode 100644 index 00000000..f0011142 --- /dev/null +++ b/test/unit/SetWithdrawalQueueTest.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +import {EulerAggregationLayerBase, EulerAggregationLayer, ErrorsLib} from "../common/EulerAggregationLayerBase.t.sol"; + +contract SetWithdrawalQueueTest is EulerAggregationLayerBase { + function setUp() public virtual override { + super.setUp(); + } + + function testSetInvalidWithdrawalQueue() public { + vm.startPrank(manager); + vm.expectRevert(ErrorsLib.InvalidPlugin.selector); + eulerAggregationLayer.setWithdrawalQueue(address(0)); + } + + function testSetWithdrawalQueue() public { + address newWithdrawalQueue = makeAddr("WITHDRAWAL_QUEUE"); + + vm.prank(manager); + eulerAggregationLayer.setWithdrawalQueue(newWithdrawalQueue); + + assertEq(eulerAggregationLayer.withdrawalQueue(), newWithdrawalQueue); + } +}