Skip to content

Commit ef90199

Browse files
committed
test: integration with slashingRegistryCoordinator
1 parent 292d340 commit ef90199

13 files changed

+610
-109
lines changed

src/RegistryCoordinator.sol

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ contract RegistryCoordinator is RegistryCoordinatorStorage {
131131
OnlyM2QuorumsAllowed()
132132
);
133133

134-
_deregisterOperator({operator: msg.sender, quorumNumbers: quorumNumbers});
134+
_deregisterOperator({
135+
operator: msg.sender,
136+
quorumNumbers: quorumNumbers,
137+
shouldForceDeregister: false
138+
});
135139
}
136140

137141
/// @inheritdoc IRegistryCoordinator

src/SlashingRegistryCoordinator.sol

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ contract SlashingRegistryCoordinator is
222222
uint32[] memory operatorSetIds
223223
) external override onlyAllocationManager onlyWhenNotPaused(PAUSED_DEREGISTER_OPERATOR) {
224224
bytes memory quorumNumbers = _getQuorumNumbers(operatorSetIds);
225-
_deregisterOperator(operator, quorumNumbers);
225+
_deregisterOperator({
226+
operator: operator,
227+
quorumNumbers: quorumNumbers,
228+
shouldForceDeregister: false
229+
});
226230
}
227231

228232
/// @inheritdoc ISlashingRegistryCoordinator
@@ -248,7 +252,11 @@ contract SlashingRegistryCoordinator is
248252
if (shouldBeDeregistered[0]) {
249253
bytes memory singleQuorumNumber = new bytes(1);
250254
singleQuorumNumber[0] = quorumNumbers[j];
251-
_deregisterOperator(operators[i], singleQuorumNumber);
255+
_deregisterOperator({
256+
operator: operators[i],
257+
quorumNumbers: singleQuorumNumber,
258+
shouldForceDeregister: true
259+
});
252260
}
253261
}
254262
}
@@ -304,7 +312,11 @@ contract SlashingRegistryCoordinator is
304312
stakeRegistry.updateOperatorsStake(currQuorumOperators, operatorIds, quorumNumber);
305313
for (uint256 j = 0; j < currQuorumOperators.length; ++j) {
306314
if (shouldBeDeregistered[j]) {
307-
_deregisterOperator(currQuorumOperators[j], quorumNumbers[i:i + 1]);
315+
_deregisterOperator({
316+
operator: currQuorumOperators[j],
317+
quorumNumbers: quorumNumbers[i:i + 1],
318+
shouldForceDeregister: true
319+
});
308320
}
309321
}
310322

@@ -341,7 +353,11 @@ contract SlashingRegistryCoordinator is
341353
operatorInfo.status == OperatorStatus.REGISTERED && !quorumsToRemove.isEmpty()
342354
&& quorumsToRemove.isSubsetOf(currentBitmap)
343355
) {
344-
_deregisterOperator({operator: operator, quorumNumbers: quorumNumbers});
356+
_deregisterOperator({
357+
operator: operator,
358+
quorumNumbers: quorumNumbers,
359+
shouldForceDeregister: true
360+
});
345361
}
346362
}
347363

@@ -519,7 +535,11 @@ contract SlashingRegistryCoordinator is
519535

520536
bytes memory singleQuorumNumber = new bytes(1);
521537
singleQuorumNumber[0] = quorumNumbers[i];
522-
_deregisterOperator(operatorKickParams[i].operator, singleQuorumNumber);
538+
_deregisterOperator({
539+
operator: operatorKickParams[i].operator,
540+
quorumNumbers: singleQuorumNumber,
541+
shouldForceDeregister: true
542+
});
523543
}
524544
}
525545
}
@@ -528,8 +548,16 @@ contract SlashingRegistryCoordinator is
528548
* @dev Deregister the operator from one or more quorums
529549
* This method updates the operator's quorum bitmap and status, then deregisters
530550
* the operator with the BLSApkRegistry, IndexRegistry, and StakeRegistry
551+
* @param operator the operator to deregister
552+
* @param quorumNumbers the quorum numbers to deregister from
553+
* @param shouldForceDeregister whether the operator needs to be deregistered from the OperatorSets of
554+
* the core EigenLayer contract AllocationManager
531555
*/
532-
function _deregisterOperator(address operator, bytes memory quorumNumbers) internal virtual {
556+
function _deregisterOperator(
557+
address operator,
558+
bytes memory quorumNumbers,
559+
bool shouldForceDeregister
560+
) internal virtual {
533561
// Fetch the operator's info and ensure they are registered
534562
OperatorInfo storage operatorInfo = _operatorInfo[operator];
535563
bytes32 operatorId = operatorInfo.operatorId;
@@ -568,8 +596,9 @@ contract SlashingRegistryCoordinator is
568596
stakeRegistry.deregisterOperator(operatorId, quorumNumbers);
569597
indexRegistry.deregisterOperator(operatorId, quorumNumbers);
570598

571-
// If the caller is not the allocationManager, then this is a force deregistration not consented by the operator
572-
if (msg.sender != address(allocationManager)) {
599+
// If the operator is not deregistered from the EigenLayer core protocol, then we need to force deregister them
600+
// from their respective OperatorSets in the AllocationManager
601+
if (shouldForceDeregister) {
573602
_forceDeregisterOperator(operator, quorumNumbers);
574603
}
575604

test/ffi/UpdateOperators.t.sol

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,8 @@ contract Integration_AVS_Sync_GasCosts_FFI is IntegrationChecks {
10771077
numQuorums: ONE,
10781078
numStrategies: TWENTYFIVE,
10791079
minimumStake: NO_MINIMUM,
1080-
fillTypes: FULL
1080+
fillTypes: FULL,
1081+
quorumType: DELEGATED_STAKE
10811082
})
10821083
});
10831084
_updateOperators_SingleQuorum();
@@ -1093,7 +1094,8 @@ contract Integration_AVS_Sync_GasCosts_FFI is IntegrationChecks {
10931094
numQuorums: ONE,
10941095
numStrategies: TWENTY,
10951096
minimumStake: NO_MINIMUM,
1096-
fillTypes: FULL
1097+
fillTypes: FULL,
1098+
quorumType: DELEGATED_STAKE
10971099
})
10981100
});
10991101

@@ -1109,7 +1111,8 @@ contract Integration_AVS_Sync_GasCosts_FFI is IntegrationChecks {
11091111
numQuorums: ONE,
11101112
numStrategies: FIFTEEN,
11111113
minimumStake: NO_MINIMUM,
1112-
fillTypes: FULL
1114+
fillTypes: FULL,
1115+
quorumType: DELEGATED_STAKE
11131116
})
11141117
});
11151118
_updateOperators_SingleQuorum();

test/harnesses/RegistryCoordinatorHarness.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ contract RegistryCoordinatorHarness is RegistryCoordinator, Test {
6060

6161
// @notice exposes the internal `_deregisterOperator` function, overriding all access controls
6262
function _deregisterOperatorExternal(address operator, bytes calldata quorumNumbers) external {
63-
_deregisterOperator(operator, quorumNumbers);
63+
_deregisterOperator(operator, quorumNumbers, false);
6464
}
6565

6666
// @notice exposes the internal `_updateOperatorBitmap` function, overriding all access controls

test/integration/IntegrationBase.t.sol

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ abstract contract IntegrationBase is IntegrationConfig {
2222

2323
function assert_HasOperatorInfoWithId(User user, string memory err) internal {
2424
bytes32 expectedId = user.operatorId();
25-
bytes32 actualId = registryCoordinator.getOperatorId(address(user));
25+
bytes32 actualId = slashingRegistryCoordinator.getOperatorId(address(user));
2626

2727
assertEq(expectedId, actualId, err);
2828
}
@@ -39,20 +39,20 @@ abstract contract IntegrationBase is IntegrationConfig {
3939

4040
function assert_HasRegisteredStatus(User user, string memory err) internal {
4141
ISlashingRegistryCoordinatorTypes.OperatorStatus status =
42-
registryCoordinator.getOperatorStatus(address(user));
42+
slashingRegistryCoordinator.getOperatorStatus(address(user));
4343

4444
assertTrue(status == ISlashingRegistryCoordinatorTypes.OperatorStatus.REGISTERED, err);
4545
}
4646

4747
function assert_HasDeregisteredStatus(User user, string memory err) internal {
4848
ISlashingRegistryCoordinatorTypes.OperatorStatus status =
49-
registryCoordinator.getOperatorStatus(address(user));
49+
slashingRegistryCoordinator.getOperatorStatus(address(user));
5050

5151
assertTrue(status == ISlashingRegistryCoordinatorTypes.OperatorStatus.DEREGISTERED, err);
5252
}
5353

5454
function assert_EmptyQuorumBitmap(User user, string memory err) internal {
55-
uint192 bitmap = registryCoordinator.getCurrentQuorumBitmap(user.operatorId());
55+
uint192 bitmap = slashingRegistryCoordinator.getCurrentQuorumBitmap(user.operatorId());
5656

5757
assertTrue(bitmap == 0, err);
5858
}
@@ -62,7 +62,7 @@ abstract contract IntegrationBase is IntegrationConfig {
6262
bytes memory quorums,
6363
string memory err
6464
) internal {
65-
uint192 bitmap = registryCoordinator.getCurrentQuorumBitmap(user.operatorId());
65+
uint192 bitmap = slashingRegistryCoordinator.getCurrentQuorumBitmap(user.operatorId());
6666

6767
for (uint256 i = 0; i < quorums.length; i++) {
6868
uint8 quorum = uint8(quorums[i]);
@@ -77,15 +77,30 @@ abstract contract IntegrationBase is IntegrationConfig {
7777
bytes memory quorums,
7878
string memory err
7979
) internal {
80-
uint192 currentBitmap = registryCoordinator.getCurrentQuorumBitmap(user.operatorId());
80+
uint192 currentBitmap =
81+
slashingRegistryCoordinator.getCurrentQuorumBitmap(user.operatorId());
8182
uint192 subsetBitmap = uint192(quorums.orderedBytesArrayToBitmap());
8283

8384
assertTrue(subsetBitmap.isSubsetOf(currentBitmap), err);
8485
}
8586

87+
/// @dev Checks that the user is registered for each of the operator sets in the AllocationManager
88+
function assert_RegisteredForOperatorSets(
89+
User user,
90+
bytes memory operatorSetIds,
91+
string memory err
92+
) internal {
93+
for (uint256 i = 0; i < operatorSetIds.length; i++) {
94+
uint32 operatorSetId = uint32(uint8(operatorSetIds[i]));
95+
OperatorSet memory operatorSet =
96+
OperatorSet({avs: avsAccountIdentifier, id: operatorSetId});
97+
assertTrue(allocationManager.isMemberOfOperatorSet(address(user), operatorSet), err);
98+
}
99+
}
100+
86101
/// @dev Checks whether each of the quorums has been initialized in the RegistryCoordinator
87102
function assert_QuorumsExist(bytes memory quorums, string memory err) internal {
88-
uint8 count = registryCoordinator.quorumCount();
103+
uint8 count = slashingRegistryCoordinator.quorumCount();
89104
for (uint256 i = 0; i < quorums.length; i++) {
90105
uint8 quorum = uint8(quorums[i]);
91106

@@ -176,7 +191,7 @@ abstract contract IntegrationBase is IntegrationConfig {
176191
uint8 quorum = uint8(quorums[i]);
177192

178193
uint32 maxOperatorCount =
179-
registryCoordinator.getOperatorSetParams(quorum).maxOperatorCount;
194+
slashingRegistryCoordinator.getOperatorSetParams(quorum).maxOperatorCount;
180195
uint32 curOperatorCount = indexRegistry.totalOperatorsForQuorum(quorum);
181196

182197
assertTrue(curOperatorCount < maxOperatorCount, err);
@@ -244,6 +259,20 @@ abstract contract IntegrationBase is IntegrationConfig {
244259
assertTrue(quorumsRemoved.noBitsInCommon(curBitmap), err);
245260
}
246261

262+
/// @dev Checks that user has deregistered from all operator sets in the AllocationManager
263+
function assert_Snap_Deregistered_FromOperatorSets(
264+
User user,
265+
bytes memory quorums,
266+
string memory err
267+
) internal {
268+
for (uint256 i = 0; i < quorums.length; i++) {
269+
uint32 operatorSetId = uint32(uint8(quorums[i]));
270+
OperatorSet memory operatorSet =
271+
OperatorSet({avs: avsAccountIdentifier, id: operatorSetId});
272+
assertFalse(allocationManager.isMemberOfOperatorSet(address(user), operatorSet), err);
273+
}
274+
}
275+
247276
function assert_Snap_Unchanged_OperatorInfo(User user, string memory err) internal {
248277
ISlashingRegistryCoordinatorTypes.OperatorInfo memory curInfo = _getOperatorInfo(user);
249278
ISlashingRegistryCoordinatorTypes.OperatorInfo memory prevInfo = _getPrevOperatorInfo(user);
@@ -869,7 +898,7 @@ abstract contract IntegrationBase is IntegrationConfig {
869898
function _getOperatorInfo(
870899
User user
871900
) internal view returns (ISlashingRegistryCoordinatorTypes.OperatorInfo memory) {
872-
return registryCoordinator.getOperator(address(user));
901+
return slashingRegistryCoordinator.getOperator(address(user));
873902
}
874903

875904
function _getPrevOperatorInfo(
@@ -881,7 +910,7 @@ abstract contract IntegrationBase is IntegrationConfig {
881910
function _getQuorumBitmap(
882911
bytes32 operatorId
883912
) internal view returns (uint192) {
884-
return registryCoordinator.getCurrentQuorumBitmap(operatorId);
913+
return slashingRegistryCoordinator.getCurrentQuorumBitmap(operatorId);
885914
}
886915

887916
function _getPrevQuorumBitmap(

test/integration/IntegrationChecks.t.sol

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ contract IntegrationChecks is IntegrationBase {
3939
function check_Register_State(User operator, bytes memory quorums) internal {
4040
_log("check_Register_State", operator);
4141

42+
// AllocationManager
43+
assert_RegisteredForOperatorSets(
44+
operator, quorums, "operator did not register for all operator sets"
45+
);
46+
4247
// RegistryCoordinator
4348
assert_HasOperatorInfoWithId(operator, "operatorInfo should have operatorId");
4449
assert_HasRegisteredStatus(operator, "operatorInfo status should be REGISTERED");
@@ -74,7 +79,7 @@ contract IntegrationChecks is IntegrationBase {
7479
);
7580

7681
// AVSDirectory
77-
assert_IsRegisteredToAVS(operator, "operator should be registered to AVS");
82+
// assert_IsRegisteredToAVS(operator, "operator should be registered to AVS");
7883
}
7984

8085
/// @dev Combines many checks of check_Register_State and check_Deregister_State
@@ -153,7 +158,7 @@ contract IntegrationChecks is IntegrationBase {
153158
);
154159

155160
// AVSDirectory
156-
assert_IsRegisteredToAVS(incomingOperator, "operator should be registered to AVS");
161+
// assert_IsRegisteredToAVS(incomingOperator, "operator should be registered to AVS");
157162

158163
// Check that churnedOperators are deregistered from churnedQuorums
159164
for (uint256 i = 0; i < churnedOperators.length; i++) {
@@ -177,6 +182,13 @@ contract IntegrationChecks is IntegrationBase {
177182
"churned operator did not deregister from churned quorum"
178183
);
179184

185+
// AllocationManager
186+
assert_Snap_Deregistered_FromOperatorSets(
187+
churnedOperator,
188+
churnedQuorum,
189+
"churned operator did not deregister from operatorSets"
190+
);
191+
180192
// BLSApkRegistry
181193
assert_HasRegisteredPubkey(
182194
churnedOperator, "churned operator should still have a registered pubkey"
@@ -276,7 +288,7 @@ contract IntegrationChecks is IntegrationBase {
276288
);
277289

278290
// AVSDirectory
279-
assert_IsRegisteredToAVS(operator, "operator should be registered to AVS");
291+
// assert_IsRegisteredToAVS(operator, "operator should be registered to AVS");
280292
}
281293

282294
/// @dev Validate state directly after the operator exits from Eigenlayer core (by queuing withdrawals)
@@ -320,6 +332,11 @@ contract IntegrationChecks is IntegrationBase {
320332
function check_WithdrawUpdate_State(User operator, bytes memory quorums) internal {
321333
_log("check_WithdrawUpdate_State", operator);
322334

335+
// AllocationManager
336+
assert_Snap_Deregistered_FromOperatorSets(
337+
operator, quorums, "operator did not deregister from all operator sets"
338+
);
339+
323340
// RegistryCoordinator
324341
assert_HasOperatorInfoWithId(operator, "operatorInfo should still have operatorId");
325342
assert_EmptyQuorumBitmap(operator, "operator should not have any bits in bitmap");
@@ -393,6 +410,11 @@ contract IntegrationChecks is IntegrationBase {
393410
function check_Deregister_State(User operator, bytes memory quorums) internal {
394411
_log("check_Deregister_State", operator);
395412

413+
// AllocationManager
414+
assert_Snap_Deregistered_FromOperatorSets(
415+
operator, quorums, "operator did not deregister from all operator sets"
416+
);
417+
396418
// RegistryCoordinator
397419
assert_HasOperatorInfoWithId(operator, "operatorInfo should still have operatorId");
398420
assert_NotRegisteredForQuorums(

0 commit comments

Comments
 (0)