@@ -34,6 +34,7 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
3434 using SlashingLib for * ;
3535 using ArrayLib for * ;
3636 using print for * ;
37+ using EnumerableSet for EnumerableSet.AddressSet;
3738
3839 IStrategy constant beaconChainETHStrategy = IStrategy (0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0 );
3940
@@ -52,6 +53,10 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
5253
5354 string _NAME;
5455
56+ // User's delegated stakers if they are an operator
57+ // create an enumerableSet of stakers that have delegated to this user
58+ EnumerableSet.AddressSet internal delegatedStakers;
59+
5560 // User's EigenPod and each of their validator indices within that pod
5661 EigenPod public pod;
5762 uint40 [] validators;
@@ -208,11 +213,16 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
208213 ISignatureUtilsMixinTypes.SignatureWithExpiry memory emptySig;
209214 delegationManager.delegateTo (address (operator), emptySig, bytes32 (0 ));
210215 print.gasUsed ();
216+
217+ // handle the delegating staker on the operator User contract
218+ // to manage the delegatedStakers enum set
219+ operator.handleDelegatingStakers (address (this ));
211220 }
212221
213222 /// @dev Undelegate from operator
214223 function undelegate () public virtual createSnapshot returns (Withdrawal[] memory ) {
215224 print.method ("undelegate " );
225+ User operator = User (payable (delegationManager.delegatedTo (address (this ))));
216226
217227 Withdrawal[] memory expectedWithdrawals = _getExpectedWithdrawalStructsForStaker (address (this ));
218228 _tryPrankAppointee_DelegationManager (IDelegationManager.undelegate.selector );
@@ -234,6 +244,10 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
234244 );
235245 }
236246
247+ // handle the undelegating staker on the operator User contract
248+ // to manage the delegatedStakers enum set
249+ operator.handleUndelegatingStaker (address (this ));
250+
237251 return expectedWithdrawals;
238252 }
239253
@@ -242,6 +256,8 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
242256 User newOperator
243257 ) public virtual createSnapshot returns (Withdrawal[] memory ) {
244258 print.method ("redelegate " , newOperator.NAME_COLORED ());
259+ User oldOperator = User (payable (delegationManager.delegatedTo (payable (address (this )))));
260+
245261 Withdrawal[] memory expectedWithdrawals = _getExpectedWithdrawalStructsForStaker (address (this ));
246262 ISignatureUtilsMixinTypes.SignatureWithExpiry memory emptySig;
247263 _tryPrankAppointee_DelegationManager (IDelegationManager.redelegate.selector );
@@ -262,6 +278,12 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
262278 expectedWithdrawals[i].scaledShares[0 ]
263279 );
264280 }
281+
282+ // handle the redelegating staker on the operator User contract
283+ // to manage the delegatedStakers enum set
284+ oldOperator.handleUndelegatingStaker (address (this ));
285+ newOperator.handleDelegatingStakers (address (this ));
286+
265287 return expectedWithdrawals;
266288 }
267289
@@ -275,9 +297,35 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
275297 delegationManager.undelegate (address (staker));
276298 print.gasUsed ();
277299
300+ // Operator is calling this function themselves
301+ // handle the undelegating staker on this contract to manage the delegatedStakers enum set
302+ handleUndelegatingStaker (address (staker));
303+
278304 return expectedWithdrawals;
279305 }
280306
307+ /// @dev NOTE: do NOT call this function directly. This is simply implemented to manage the
308+ /// delegatedStakers enum set. This function is only meant to be called on the Operator User contract.
309+ function handleDelegatingStakers (address staker ) public virtual {
310+ // check that the current User is an operator
311+ require (
312+ delegationManager.isOperator (address (this )),
313+ "User is not an operator "
314+ );
315+ delegatedStakers.add (staker);
316+ }
317+
318+ /// @dev NOTE: do NOT call this function directly. This is simply implemented to manage the
319+ /// delegatedStakers enum set. This function is only meant to be called on the Operator User contract.
320+ function handleUndelegatingStaker (address staker ) public virtual {
321+ // check that the current User is an operator
322+ require (
323+ delegationManager.isOperator (address (this )),
324+ "User is not an operator "
325+ );
326+ delegatedStakers.remove (staker);
327+ }
328+
281329 /// @dev Queues a single withdrawal for every share and strategy pair
282330 function queueWithdrawals (
283331 IStrategy[] memory strategies ,
@@ -713,6 +761,15 @@ contract User is Logger, IDelegationManagerTypes, IAllocationManagerTypes {
713761 return activeValidators;
714762 }
715763
764+ function getDelegatedStakers () public view returns (User[] memory ) {
765+ address [] memory stakers = delegatedStakers.values ();
766+ User[] memory users = new User [](stakers.length );
767+ for (uint256 i = 0 ; i < stakers.length ; i++ ) {
768+ users[i] = User (payable (stakers[i]));
769+ }
770+ return users;
771+ }
772+
716773 function _tryPrankAppointee (
717774 address target ,
718775 bytes4 selector
0 commit comments