diff --git a/docs/core/DurationVaultStrategy.md b/docs/core/DurationVaultStrategy.md index 35d0f1b4ac..2d0a7a19ed 100644 --- a/docs/core/DurationVaultStrategy.md +++ b/docs/core/DurationVaultStrategy.md @@ -83,7 +83,7 @@ flowchart TB ### Vault as Operator -The vault registers itself as an EigenLayer operator on initialization. Stakers must delegate to the vault before depositing. The vault allocates its own magnitude to the configured AVS operator set and sets operator reward split to 0% so 100% of rewards goes to its stakers. +The vault registers itself as an EigenLayer operator on initialization. Stakers must delegate to the vault before depositing. The vault allocates its own magnitude to the configured AVS operator set and sets operator reward splits (operator AVS split, operatorSet split, and PI split) to 0% so 100% of rewards goes to its stakers. ### Strategy Hooks diff --git a/src/contracts/strategies/DurationVaultStrategy.sol b/src/contracts/strategies/DurationVaultStrategy.sol index 2730c6c5ab..0d052a271b 100644 --- a/src/contracts/strategies/DurationVaultStrategy.sol +++ b/src/contracts/strategies/DurationVaultStrategy.sol @@ -322,6 +322,8 @@ contract DurationVaultStrategy is DurationVaultStrategyStorage, StrategyBase { allocationManager.registerForOperatorSets(address(this), params); // Set operator splits to 0 (100% of rewards go to stakers). + // Note: rewards can be configured at the AVS-level and operatorSet-level, so we set both. + rewardsCoordinator.setOperatorAVSSplit(address(this), config.operatorSet.avs, 0); rewardsCoordinator.setOperatorSetSplit(address(this), config.operatorSet, 0); rewardsCoordinator.setOperatorPISplit(address(this), 0); } diff --git a/src/test/mocks/RewardsCoordinatorMock.sol b/src/test/mocks/RewardsCoordinatorMock.sol index 2ed1390638..df115985ed 100644 --- a/src/test/mocks/RewardsCoordinatorMock.sol +++ b/src/test/mocks/RewardsCoordinatorMock.sol @@ -10,20 +10,37 @@ contract RewardsCoordinatorMock is Test { receive() external payable {} fallback() external payable {} + struct SetOperatorAVSSplitCall { + address operator; + address avs; + uint16 split; + } + struct SetOperatorSetSplitCall { address operator; OperatorSet operatorSet; uint16 split; } + SetOperatorAVSSplitCall internal _lastSetOperatorAVSSplitCall; SetOperatorSetSplitCall internal _lastSetOperatorSetSplitCall; + uint public setOperatorAVSSplitCallCount; uint public setOperatorSetSplitCallCount; + function setOperatorAVSSplit(address operator, address avs, uint16 split) external { + setOperatorAVSSplitCallCount++; + _lastSetOperatorAVSSplitCall = SetOperatorAVSSplitCall({operator: operator, avs: avs, split: split}); + } + function setOperatorSetSplit(address operator, OperatorSet calldata operatorSet, uint16 split) external { setOperatorSetSplitCallCount++; _lastSetOperatorSetSplitCall = SetOperatorSetSplitCall({operator: operator, operatorSet: operatorSet, split: split}); } + function lastSetOperatorAVSSplitCall() external view returns (SetOperatorAVSSplitCall memory) { + return _lastSetOperatorAVSSplitCall; + } + function lastSetOperatorSetSplitCall() external view returns (SetOperatorSetSplitCall memory) { return _lastSetOperatorSetSplitCall; } diff --git a/src/test/unit/DurationVaultStrategyUnit.t.sol b/src/test/unit/DurationVaultStrategyUnit.t.sol index acea433c48..1cbf2f8cc7 100644 --- a/src/test/unit/DurationVaultStrategyUnit.t.sol +++ b/src/test/unit/DurationVaultStrategyUnit.t.sol @@ -106,6 +106,12 @@ contract DurationVaultStrategyUnitTests is StrategyBaseUnitTests { assertEq(address(durationVault.rewardsCoordinator()), address(rewardsCoordinatorMock), "rewards coordinator mismatch"); assertTrue(durationVault.operatorSetRegistered(), "operator set should be registered"); + // Verify operator AVS rewards split is set to 0 (100% to stakers). + RewardsCoordinatorMock.SetOperatorAVSSplitCall memory avsSplitCall = rewardsCoordinatorMock.lastSetOperatorAVSSplitCall(); + assertEq(avsSplitCall.operator, address(durationVault), "avs split operator mismatch"); + assertEq(avsSplitCall.avs, OPERATOR_SET_AVS, "avs split AVS mismatch"); + assertEq(avsSplitCall.split, 0, "operator AVS split should be 0 for 100% to stakers"); + // Verify rewards split is set to 0 (100% to stakers). RewardsCoordinatorMock.SetOperatorSetSplitCall memory splitCall = rewardsCoordinatorMock.lastSetOperatorSetSplitCall(); assertEq(splitCall.operator, address(durationVault), "split operator mismatch");