Skip to content

Commit 4f3852a

Browse files
committed
fix: forcederegistration try catch edge cases
1 parent ef90199 commit 4f3852a

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

src/SlashingRegistryCoordinator.sol

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,24 @@ contract SlashingRegistryCoordinator is
249249
singleOperator, singleOperatorId, quorumNumber
250250
);
251251

252-
if (shouldBeDeregistered[0]) {
252+
// whether the operator is registered in the core EigenLayer contract AllocationManager
253+
bool registeredInCore = allocationManager.isMemberOfOperatorSet(
254+
operators[i], OperatorSet({avs: accountIdentifier, id: uint32(quorumNumber)})
255+
);
256+
257+
// If the operator does not have the minimum stake, they need to be force deregistered.
258+
// Additionally, it is possible for an operator to have deregistered from an OperatorSet
259+
// in the core EigenLayer contract AllocationManager but not have the deregistration
260+
// callback succeed here in `deregisterOperator` due to out of gas errors. If that is the case,
261+
// we need to deregister the operator from the OperatorSet in this contract
262+
if (shouldBeDeregistered[0] || !registeredInCore) {
263+
// The operator should be deregistered from this quorum
253264
bytes memory singleQuorumNumber = new bytes(1);
254265
singleQuorumNumber[0] = quorumNumbers[j];
255266
_deregisterOperator({
256267
operator: operators[i],
257268
quorumNumbers: singleQuorumNumber,
258-
shouldForceDeregister: true
269+
shouldForceDeregister: registeredInCore
259270
});
260271
}
261272
}
@@ -609,13 +620,35 @@ contract SlashingRegistryCoordinator is
609620
/**
610621
* @notice Helper function to handle operator set deregistration for OperatorSets quorums. This is used
611622
* when an operator is force-deregistered from a set of quorums.
623+
* Due to deregistration being possible in the AllocationManager but not in the AVS as a result of the
624+
* try/catch in `AllocationManager.deregisterFromOperatorSets`, we need to first check that the operator
625+
* is not already deregistered from the OperatorSet in the AllocationManager.
612626
* @param operator The operator to deregister
613627
* @param quorumNumbers The quorum numbers the operator is force-deregistered from
614628
*/
615629
function _forceDeregisterOperator(
616630
address operator,
617631
bytes memory quorumNumbers
618632
) internal virtual {
633+
uint32[] memory operatorSetIds = new uint32[](quorumNumbers.length);
634+
uint256 numDeregister = 0;
635+
for (uint256 i = 0; i < quorumNumbers.length; ++i) {
636+
uint32 operatorSetId = uint32(uint8(quorumNumbers[i]));
637+
if (
638+
allocationManager.isMemberOfOperatorSet(
639+
operator, OperatorSet({avs: accountIdentifier, id: operatorSetId})
640+
)
641+
) {
642+
operatorSetIds[numDeregister] = operatorSetId;
643+
numDeregister++;
644+
}
645+
}
646+
647+
// resize operatorSetIds array length to numDeregister
648+
assembly {
649+
mstore(operatorSetIds, numDeregister)
650+
}
651+
619652
allocationManager.deregisterFromOperatorSets(
620653
IAllocationManagerTypes.DeregisterParams({
621654
operator: operator,

0 commit comments

Comments
 (0)