@@ -144,26 +144,47 @@ contract SlashingRegistryCoordinator is
144
144
bytes calldata data
145
145
) external override onlyAllocationManager onlyWhenNotPaused (PAUSED_REGISTER_OPERATOR) {
146
146
require (isOperatorSetAVS, OperatorSetsNotEnabled ());
147
- for (uint256 i = 0 ; i < operatorSetIds.length ; i++ ) {
148
- require (! isM2Quorum[uint8 (operatorSetIds[i])], OperatorSetsNotSupported ());
149
- }
150
- bytes memory quorumNumbers = new bytes (operatorSetIds.length );
151
- for (uint256 i = 0 ; i < operatorSetIds.length ; i++ ) {
152
- quorumNumbers[i] = bytes1 (uint8 (operatorSetIds[i]));
153
- }
147
+ bytes memory quorumNumbers = _getQuorumNumbers (operatorSetIds);
148
+
149
+ (
150
+ RegistrationType registrationType ,
151
+ string memory socket ,
152
+ IBLSApkRegistry.PubkeyRegistrationParams memory params
153
+ ) = abi.decode (data, (RegistrationType, string , IBLSApkRegistry.PubkeyRegistrationParams));
154
+
155
+ /**
156
+ * If the operator has NEVER registered a pubkey before, use `params` to register
157
+ * their pubkey in blsApkRegistry
158
+ *
159
+ * If the operator HAS registered a pubkey, `params` is ignored and the pubkey hash
160
+ * (operatorId) is fetched instead
161
+ */
162
+ bytes32 operatorId = _getOrCreateOperatorId (operator, params);
154
163
155
- // Handle churn or normal registration based on first byte in `data`
156
- RegistrationType registrationType = RegistrationType (uint8 (bytes1 (data[0 :1 ])));
157
164
if (registrationType == RegistrationType.NORMAL) {
158
- (, string memory socket , IBLSApkRegistry.PubkeyRegistrationParams memory params ) = abi.decode (data, (RegistrationType, string , IBLSApkRegistry.PubkeyRegistrationParams));
159
- bytes32 operatorId = _getOrCreateOperatorId (operator, params);
160
- _registerOperatorToOperatorSet (operator, operatorId, quorumNumbers, socket);
165
+ uint32 [] memory numOperatorsPerQuorum = _registerOperator ({
166
+ operator: operator,
167
+ operatorId: operatorId,
168
+ quorumNumbers: quorumNumbers,
169
+ socket: socket
170
+ }).numOperatorsPerQuorum;
171
+
172
+ // For each quorum, validate that the new operator count does not exceed the maximum
173
+ // (If it does, an operator needs to be replaced -- see `registerOperatorWithChurn`)
174
+ for (uint256 i = 0 ; i < quorumNumbers.length ; i++ ) {
175
+ uint8 quorumNumber = uint8 (quorumNumbers[i]);
176
+
177
+ require (
178
+ numOperatorsPerQuorum[i] <= _quorumParams[quorumNumber].maxOperatorCount,
179
+ MaxQuorumsReached ()
180
+ );
181
+ }
161
182
} else if (registrationType == RegistrationType.CHURN) {
162
183
// Decode registration data from bytes
163
184
(
164
185
,
165
- string memory socket ,
166
- IBLSApkRegistry.PubkeyRegistrationParams memory params ,
186
+ ,
187
+ ,
167
188
OperatorKickParam[] memory operatorKickParams ,
168
189
SignatureWithSaltAndExpiry memory churnApproverSignature
169
190
) = abi.decode (
@@ -176,26 +197,31 @@ contract SlashingRegistryCoordinator is
176
197
SignatureWithSaltAndExpiry
177
198
)
178
199
);
179
-
180
- _registerOperatorWithChurn (operator, quorumNumbers, socket, params, operatorKickParams, churnApproverSignature);
200
+ _registerOperatorWithChurn ({
201
+ operator: operator,
202
+ operatorId: operatorId,
203
+ quorumNumbers: quorumNumbers,
204
+ socket: socket,
205
+ operatorKickParams: operatorKickParams,
206
+ churnApproverSignature: churnApproverSignature
207
+ });
181
208
} else {
182
209
revert InvalidRegistrationType ();
183
210
}
211
+
212
+ // If the operator wasn't registered for any quorums, update their status
213
+ // and register them with this AVS in EigenLayer core (DelegationManager)
214
+ if (_operatorInfo[operator].status != OperatorStatus.REGISTERED) {
215
+ _operatorInfo[operator] = OperatorInfo (operatorId, OperatorStatus.REGISTERED);
216
+ }
184
217
}
185
218
186
219
function deregisterOperator (
187
220
address operator ,
188
221
uint32 [] memory operatorSetIds
189
- ) external override onlyAllocationManager onlyWhenNotPaused (PAUSED_REGISTER_OPERATOR ) {
222
+ ) external override onlyAllocationManager onlyWhenNotPaused (PAUSED_DEREGISTER_OPERATOR ) {
190
223
require (isOperatorSetAVS, OperatorSetsNotEnabled ());
191
- for (uint256 i = 0 ; i < operatorSetIds.length ; i++ ) {
192
- require (! isM2Quorum[uint8 (operatorSetIds[i])], OperatorSetsNotSupported ());
193
- }
194
- bytes memory quorumNumbers = new bytes (operatorSetIds.length );
195
- for (uint256 i = 0 ; i < operatorSetIds.length ; i++ ) {
196
- quorumNumbers[i] = bytes1 (uint8 (operatorSetIds[i]));
197
- }
198
-
224
+ bytes memory quorumNumbers = _getQuorumNumbers (operatorSetIds);
199
225
_deregisterOperator (operator, quorumNumbers);
200
226
}
201
227
@@ -408,7 +434,7 @@ contract SlashingRegistryCoordinator is
408
434
* @notice Register the operator for one or more quorums. This method updates the
409
435
* operator's quorum bitmap, socket, and status, then registers them with each registry.
410
436
*/
411
- function _registerOperatorToOperatorSet (
437
+ function _registerOperator (
412
438
address operator ,
413
439
bytes32 operatorId ,
414
440
bytes memory quorumNumbers ,
@@ -451,12 +477,6 @@ contract SlashingRegistryCoordinator is
451
477
452
478
emit OperatorSocketUpdate (operatorId, socket);
453
479
454
- // If the operator wasn't registered for any quorums, update their status
455
- // and register them with this AVS in EigenLayer core (DelegationManager)
456
- if (_operatorInfo[operator].status != OperatorStatus.REGISTERED) {
457
- _operatorInfo[operator] = OperatorInfo (operatorId, OperatorStatus.REGISTERED);
458
- }
459
-
460
480
// Register the operator with the BLSApkRegistry, StakeRegistry, and IndexRegistry
461
481
blsApkRegistry.registerOperator (operator, quorumNumbers);
462
482
(results.operatorStakes, results.totalStakes) =
@@ -471,23 +491,14 @@ contract SlashingRegistryCoordinator is
471
491
472
492
function _registerOperatorWithChurn (
473
493
address operator ,
494
+ bytes32 operatorId ,
474
495
bytes memory quorumNumbers ,
475
496
string memory socket ,
476
- IBLSApkRegistry.PubkeyRegistrationParams memory params ,
477
497
OperatorKickParam[] memory operatorKickParams ,
478
498
SignatureWithSaltAndExpiry memory churnApproverSignature
479
499
) internal virtual {
480
500
require (operatorKickParams.length == quorumNumbers.length , InputLengthMismatch ());
481
501
482
- /**
483
- * If the operator has NEVER registered a pubkey before, use `params` to register
484
- * their pubkey in blsApkRegistry
485
- *
486
- * If the operator HAS registered a pubkey, `params` is ignored and the pubkey hash
487
- * (operatorId) is fetched instead
488
- */
489
- bytes32 operatorId = _getOrCreateOperatorId (operator, params);
490
-
491
502
// Verify the churn approver's signature for the registering operator and kick params
492
503
_verifyChurnApproverSignature ({
493
504
registeringOperator: operator,
@@ -498,7 +509,7 @@ contract SlashingRegistryCoordinator is
498
509
499
510
// Register the operator in each of the registry contracts and update the operator's
500
511
// quorum bitmap and registration status
501
- RegisterResults memory results = _registerOperatorToOperatorSet (operator, operatorId, quorumNumbers, socket);
512
+ RegisterResults memory results = _registerOperator (operator, operatorId, quorumNumbers, socket);
502
513
503
514
// Check that each quorum's operator count is below the configured maximum. If the max
504
515
// is exceeded, use `operatorKickParams` to deregister an existing operator to make space
@@ -878,6 +889,16 @@ contract SlashingRegistryCoordinator is
878
889
return QuorumBitmapHistoryLib.getQuorumBitmapIndexAtBlockNumber (_operatorBitmapHistory,blockNumber, operatorId);
879
890
}
880
891
892
+ /// @notice Returns the quorum numbers for the provided `OperatorSetIds`
893
+ /// OperatorSetIds are used in the AllocationManager to identify operator sets for a given AVS
894
+ function _getQuorumNumbers (uint32 [] memory operatorSetIds ) internal pure returns (bytes memory ) {
895
+ bytes memory quorumNumbers = new bytes (operatorSetIds.length );
896
+ for (uint256 i = 0 ; i < operatorSetIds.length ; i++ ) {
897
+ quorumNumbers[i] = bytes1 (uint8 (operatorSetIds[i]));
898
+ }
899
+ return quorumNumbers;
900
+ }
901
+
881
902
function _setOperatorSetParams (
882
903
uint8 quorumNumber ,
883
904
OperatorSetParam memory operatorSetParams
@@ -900,10 +921,10 @@ contract SlashingRegistryCoordinator is
900
921
accountIdentifier = _accountIdentifier;
901
922
}
902
923
903
- /// @dev Hook to allow for any pre-register logic in `_registerOperatorToOperatorSet `
924
+ /// @dev Hook to allow for any pre-register logic in `_registerOperator `
904
925
function _beforeRegisterOperator (address operator , bytes32 operatorId , bytes memory quorumNumbers , uint192 currentBitmap ) internal virtual {}
905
926
906
- /// @dev Hook to allow for any post-register logic in `_registerOperatorToOperatorSet `
927
+ /// @dev Hook to allow for any post-register logic in `_registerOperator `
907
928
function _afterRegisterOperator (address operator , bytes32 operatorId , bytes memory quorumNumbers , uint192 newBitmap ) internal virtual {}
908
929
909
930
/// @dev Hook to allow for any pre-deregister logic in `_deregisterOperator`
0 commit comments