Skip to content

Commit e45028d

Browse files
authored
Feat: opSet -> operators enumerable Set (#714)
* feat: functionality * test: add tests * chore: address comments * chore: bindigns and fmt
1 parent ba0a957 commit e45028d

File tree

9 files changed

+668
-123
lines changed

9 files changed

+668
-123
lines changed

pkg/bindings/AVSDirectory/binding.go

Lines changed: 121 additions & 59 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/bindings/AVSDirectoryStorage/binding.go

Lines changed: 170 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/bindings/IAVSDirectory/binding.go

Lines changed: 187 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/bindings/RewardsCoordinator/binding.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/contracts/core/AVSDirectory.sol

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ contract AVSDirectory is
1717
ReentrancyGuardUpgradeable
1818
{
1919
using EnumerableSet for EnumerableSet.Bytes32Set;
20+
using EnumerableSet for EnumerableSet.AddressSet;
2021

2122
/// @dev Index for flag that pauses operator register/deregister to avs when set.
2223
uint8 internal constant PAUSED_OPERATOR_REGISTER_DEREGISTER_TO_AVS = 0;
@@ -354,10 +355,7 @@ contract AVSDirectory is
354355
);
355356

356357
// Assert that the AVS is not an operator set AVS.
357-
require(
358-
!isOperatorSetAVS[msg.sender],
359-
"AVSDirectory.deregisterOperatorFromAVS: AVS is an operator set AVS"
360-
);
358+
require(!isOperatorSetAVS[msg.sender], "AVSDirectory.deregisterOperatorFromAVS: AVS is an operator set AVS");
361359

362360
// Set the operator as deregistered
363361
avsOperatorStatus[msg.sender][operator] = OperatorAVSRegistrationStatus.UNREGISTERED;
@@ -387,14 +385,14 @@ contract AVSDirectory is
387385
"AVSDirectory._registerOperatorToOperatorSets: invalid operator set"
388386
);
389387

388+
bytes32 encodedOperatorSet = _encodeOperatorSet(operatorSet);
389+
390390
require(
391-
!isMember(operator, operatorSet),
391+
_operatorSetsMemberOf[operator].add(encodedOperatorSet),
392392
"AVSDirectory._registerOperatorToOperatorSets: operator already registered to operator set"
393393
);
394394

395-
++operatorSetMemberCount[avs][operatorSetIds[i]];
396-
397-
_operatorSetsMemberOf[operator].add(_encodeOperatorSet(operatorSet));
395+
_operatorSetMembers[encodedOperatorSet].add(operator);
398396

399397
emit OperatorAddedToOperatorSet(operator, operatorSet);
400398
}
@@ -412,14 +410,14 @@ contract AVSDirectory is
412410
for (uint256 i = 0; i < operatorSetIds.length; ++i) {
413411
OperatorSet memory operatorSet = OperatorSet(avs, operatorSetIds[i]);
414412

413+
bytes32 encodedOperatorSet = _encodeOperatorSet(operatorSet);
414+
415415
require(
416-
isMember(operator, operatorSet),
416+
_operatorSetsMemberOf[operator].remove(encodedOperatorSet),
417417
"AVSDirectory._deregisterOperatorFromOperatorSet: operator not registered for operator set"
418418
);
419419

420-
--operatorSetMemberCount[avs][operatorSetIds[i]];
421-
422-
_operatorSetsMemberOf[operator].remove(_encodeOperatorSet(operatorSet));
420+
_operatorSetMembers[encodedOperatorSet].remove(operator);
423421

424422
emit OperatorRemovedFromOperatorSet(operator, operatorSet);
425423
}
@@ -431,22 +429,35 @@ contract AVSDirectory is
431429
*
432430
*/
433431

434-
/// @notice Returns operator sets an operator is registered to in the order they were registered.
435-
/// @param operator The operator address to query.
436-
/// @param index The index of the enumerated list of operator sets.
437-
function operatorSetsMemberOf(address operator, uint256 index) public view returns (OperatorSet memory) {
432+
/**
433+
* @notice Returns operatorSet an operator is registered to in the order they were registered.
434+
* @param operator The operator address to query.
435+
* @param index The index of the enumerated list of operator sets.
436+
*/
437+
function operatorSetsMemberOfAtIndex(address operator, uint256 index) external view returns (OperatorSet memory) {
438438
return _decodeOperatorSet(_operatorSetsMemberOf[operator].at(index));
439439
}
440440

441-
/// @notice Returns an array of operator sets an operator is registered to.
442-
/// @param operator The operator address to query.
443-
/// @param start The starting index of the array to query.
444-
/// @param length The amount of items of the array to return.
445-
function operatorSetsMemberOf(
441+
/**
442+
* @notice Returns the operator registered to an operatorSet in the order that it was registered.
443+
* @param operatorSet The operatorSet to query.
444+
* @param index The index of the enumerated list of operators.
445+
*/
446+
function operatorSetMemberAtIndex(OperatorSet memory operatorSet, uint256 index) external view returns (address) {
447+
return _operatorSetMembers[_encodeOperatorSet(operatorSet)].at(index);
448+
}
449+
450+
/**
451+
* @notice Returns an array of operator sets an operator is registered to.
452+
* @param operator The operator address to query.
453+
* @param start The starting index of the array to query.
454+
* @param length The amount of items of the array to return.
455+
*/
456+
function getOperatorSetsOfOperator(
446457
address operator,
447458
uint256 start,
448459
uint256 length
449-
) public view returns (OperatorSet[] memory operatorSets) {
460+
) external view returns (OperatorSet[] memory operatorSets) {
450461
uint256 maxLength = _operatorSetsMemberOf[operator].length() - start;
451462
if (length > maxLength) length = maxLength;
452463
operatorSets = new OperatorSet[](length);
@@ -455,15 +466,47 @@ contract AVSDirectory is
455466
}
456467
}
457468

458-
/// @notice Returns the total number of operator sets an operator is registered to.
459-
/// @param operator The operator address to query.
460-
function inTotalOperatorSets(address operator) public view returns (uint256) {
469+
/**
470+
* @notice Returns an array of operators registered to the operatorSet.
471+
* @param operatorSet The operatorSet to query.
472+
* @param start The starting index of the array to query.
473+
* @param length The amount of items of the array to return.
474+
*/
475+
function getOperatorsInOperatorSet(
476+
OperatorSet memory operatorSet,
477+
uint256 start,
478+
uint256 length
479+
) external view returns (address[] memory operators) {
480+
bytes32 encodedOperatorSet = _encodeOperatorSet(operatorSet);
481+
uint256 maxLength = _operatorSetMembers[encodedOperatorSet].length() - start;
482+
if (length > maxLength) length = maxLength;
483+
operators = new address[](length);
484+
for (uint256 i; i < length; ++i) {
485+
operators[i] = _operatorSetMembers[encodedOperatorSet].at(start + i);
486+
}
487+
}
488+
489+
/**
490+
* @notice Returns the number of operators registered to an operatorSet.
491+
* @param operatorSet The operatorSet to get the member count for
492+
*/
493+
function getNumOperatorsInOperatorSet(OperatorSet memory operatorSet) external view returns (uint256) {
494+
return _operatorSetMembers[_encodeOperatorSet(operatorSet)].length();
495+
}
496+
497+
/**
498+
* @notice Returns the total number of operator sets an operator is registered to.
499+
* @param operator The operator address to query.
500+
*/
501+
function inTotalOperatorSets(address operator) external view returns (uint256) {
461502
return _operatorSetsMemberOf[operator].length();
462503
}
463504

464-
/// @notice Returns whether or not an operator is registered to an operator set.
465-
/// @param operator The operator address to query.
466-
/// @param operatorSet The `OperatorSet` to query.
505+
/**
506+
* @notice Returns whether or not an operator is registered to an operator set.
507+
* @param operator The operator address to query.
508+
* @param operatorSet The `OperatorSet` to query.
509+
*/
467510
function isMember(address operator, OperatorSet memory operatorSet) public view returns (bool) {
468511
return _operatorSetsMemberOf[operator].contains(_encodeOperatorSet(operatorSet));
469512
}

src/contracts/core/AVSDirectoryStorage.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import "../interfaces/IDelegationManager.sol";
88

99
abstract contract AVSDirectoryStorage is IAVSDirectory {
1010
using EnumerableSet for EnumerableSet.Bytes32Set;
11+
using EnumerableSet for EnumerableSet.AddressSet;
1112

1213
/// @notice The EIP-712 typehash for the contract's domain
1314
bytes32 public constant DOMAIN_TYPEHASH =
@@ -48,13 +49,14 @@ abstract contract AVSDirectoryStorage is IAVSDirectory {
4849
/// @notice Mapping: avs => operatorSetId => Whether or not an operator set is valid.
4950
mapping(address => mapping(uint32 => bool)) public isOperatorSet;
5051

51-
/// @notice Mapping: avs => operatorSetId => Total operators within the given operator set.
52-
mapping(address => mapping(uint32 => uint256)) public operatorSetMemberCount;
53-
5452
/// @notice Mapping: operator => List of operator sets that operator is registered to.
5553
/// @dev Each item is formatted as such: bytes32(abi.encodePacked(avs, uint96(operatorSetId)))
5654
mapping(address => EnumerableSet.Bytes32Set) internal _operatorSetsMemberOf;
5755

56+
/// @notice Mapping: operatorSet => List of operators that are registered to the operatorSet
57+
/// @dev Each key is formatted as such: bytes32(abi.encodePacked(avs, uint96(operatorSetId)))
58+
mapping(bytes32 => EnumerableSet.AddressSet) internal _operatorSetMembers;
59+
5860
constructor(IDelegationManager _delegation) {
5961
delegation = _delegation;
6062
}

src/contracts/interfaces/IAVSDirectory.sol

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,56 @@ interface IAVSDirectory is ISignatureUtils {
180180

181181
function isOperatorSet(address avs, uint32 operatorSetId) external view returns (bool);
182182

183+
/**
184+
* @notice Returns operator set an operator is registered to in the order they were registered.
185+
* @param operator The operator address to query.
186+
* @param index The index of the enumerated list of operator sets.
187+
*/
188+
function operatorSetsMemberOfAtIndex(address operator, uint256 index) external view returns (OperatorSet memory);
189+
190+
/**
191+
* @notice Retursn the operator registered to an operatorSet in the order that it was registered.
192+
* @param operatorSet The operatorSet to query.
193+
* @param index The index of the enumerated list of operators.
194+
*/
195+
function operatorSetMemberAtIndex(OperatorSet memory operatorSet, uint256 index) external view returns (address);
196+
197+
/**
198+
* @notice Returns an array of operator sets an operator is registered to.
199+
* @param operator The operator address to query.
200+
* @param start The starting index of the array to query.
201+
* @param length The amount of items of the array to return.
202+
*/
203+
function getOperatorSetsOfOperator(
204+
address operator,
205+
uint256 start,
206+
uint256 length
207+
) external view returns (OperatorSet[] memory operatorSets);
208+
209+
/**
210+
* @notice Returns an array of operators registered to the operatorSet.
211+
* @param operatorSet The operatorSet to query.
212+
* @param start The starting index of the array to query.
213+
* @param length The amount of items of the array to return.
214+
*/
215+
function getOperatorsInOperatorSet(
216+
OperatorSet memory operatorSet,
217+
uint256 start,
218+
uint256 length
219+
) external view returns (address[] memory operators);
220+
221+
/**
222+
* @notice Returns the number of operators registered to an operatorSet.
223+
* @param operatorSet The operatorSet to get the member count for
224+
*/
225+
function getNumOperatorsInOperatorSet(OperatorSet memory operatorSet) external view returns (uint256);
226+
227+
/**
228+
* @notice Returns the total number of operator sets an operator is registered to.
229+
* @param operator The operator address to query.
230+
*/
231+
function inTotalOperatorSets(address operator) external view returns (uint256);
232+
183233
/**
184234
* @notice Calculates the digest hash to be signed by an operator to register with an AVS.
185235
*

src/test/mocks/AVSDirectoryMock.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,24 @@ contract AVSDirectoryMock is IAVSDirectory, Test {
8282
function OPERATOR_SET_REGISTRATION_TYPEHASH() external view returns (bytes32) {}
8383

8484
function isMember(address operator, IAVSDirectory.OperatorSet memory operatorSet) external view returns (bool) {}
85+
86+
function operatorSetsMemberOfAtIndex(address operator, uint256 index) external view returns (OperatorSet memory) {}
87+
88+
function operatorSetMemberAtIndex(OperatorSet memory operatorSet, uint256 index) external view returns (address) {}
89+
90+
function getOperatorSetsOfOperator(
91+
address operator,
92+
uint256 start,
93+
uint256 length
94+
) external view returns (OperatorSet[] memory operatorSets) {}
95+
96+
function getOperatorsInOperatorSet(
97+
OperatorSet memory operatorSet,
98+
uint256 start,
99+
uint256 length
100+
) external view returns (address[] memory operators) {}
101+
102+
function getNumOperatorsInOperatorSet(OperatorSet memory operatorSet) external view returns (uint256) {}
103+
104+
function inTotalOperatorSets(address operator) external view returns (uint256) {}
85105
}

0 commit comments

Comments
 (0)