Skip to content

Commit

Permalink
feat: add ejector support for operator sets
Browse files Browse the repository at this point in the history
  • Loading branch information
stevennevins committed Jan 22, 2025
1 parent 42d2d20 commit 603e95e
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 15 deletions.
23 changes: 23 additions & 0 deletions src/RegistryCoordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,29 @@ contract RegistryCoordinator is
operatorInfo.status == OperatorStatus.REGISTERED && !quorumsToRemove.isEmpty()
&& quorumsToRemove.isSubsetOf(currentBitmap)
) {
// If using operator sets, check for non-M2 quorums
if (isUsingOperatorSets()) {
uint32[] memory nonM2OperatorSetIds = new uint32[](quorumNumbers.length);
uint256 numNonM2Quorums;

// Check each quorum's stake type
for (uint256 i = 0; i < quorumNumbers.length; i++) {
uint8 quorumNumber = uint8(quorumNumbers[i]);
if (isM2Quorum[quorumNumber]) {
nonM2OperatorSetIds[numNonM2Quorums++] = quorumNumber;
}
}

// If any non-M2 quorums found, deregister from AVS
if (numNonM2Quorums > 0) {
// Resize array to exact size needed
assembly {
mstore(nonM2OperatorSetIds, numNonM2Quorums)
}
serviceManager.deregisterOperatorFromOperatorSets(operator, nonM2OperatorSetIds);
}
}

_deregisterOperator({operator: operator, quorumNumbers: quorumNumbers});
}
}
Expand Down
27 changes: 20 additions & 7 deletions src/ServiceManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSD
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IRewardsCoordinator} from
"eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IAllocationManager, IAllocationManagerTypes} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IPermissionController} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";

import {ServiceManagerBaseStorage} from "./ServiceManagerBaseStorage.sol";
Expand Down Expand Up @@ -45,14 +47,16 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
IRewardsCoordinator __rewardsCoordinator,
IRegistryCoordinator __registryCoordinator,
IStakeRegistry __stakeRegistry,
IPermissionController __permissionController
IPermissionController __permissionController,
IAllocationManager __allocationManager
)
ServiceManagerBaseStorage(
__avsDirectory,
__rewardsCoordinator,
__registryCoordinator,
__stakeRegistry,
__permissionController
__permissionController,
__allocationManager
)
{
_disableInitializers();
Expand All @@ -77,15 +81,15 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
/// @inheritdoc IServiceManager
function removePendingAdmin(address pendingAdmin) external onlyOwner {
_permissionController.removePendingAdmin({
account: address(this),
account: address(this),
admin: pendingAdmin
});
}

/// @inheritdoc IServiceManager
function removeAdmin(address admin) external onlyOwner {
_permissionController.removeAdmin({
account: address(this),
account: address(this),
admin: admin
});
}
Expand All @@ -97,9 +101,9 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
bytes4 selector
) external onlyOwner {
_permissionController.setAppointee({
account: address(this),
appointee: appointee,
target: target,
account: address(this),
appointee: appointee,
target: target,
selector: selector
});
}
Expand Down Expand Up @@ -177,6 +181,15 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
_avsDirectory.deregisterOperatorFromAVS(operator);
}

function deregisterOperatorFromOperatorSets(address operator, uint32[] memory operatorSetIds) public virtual onlyRegistryCoordinator {
IAllocationManager.DeregisterParams memory params = IAllocationManagerTypes.DeregisterParams({
operator: operator,
avs: address(this),
operatorSetIds: operatorSetIds
});
_allocationManager.deregisterFromOperatorSets(params);
}

/**
* @notice Sets the rewards initiator address
* @param newRewardsInitiator The new rewards initiator address
Expand Down
6 changes: 5 additions & 1 deletion src/ServiceManagerBaseStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";

import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IPermissionController} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";
Expand All @@ -24,6 +25,7 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
*
*/
IAVSDirectory internal immutable _avsDirectory;
IAllocationManager internal immutable _allocationManager;
IRewardsCoordinator internal immutable _rewardsCoordinator;
IRegistryCoordinator internal immutable _registryCoordinator;
IStakeRegistry internal immutable _stakeRegistry;
Expand Down Expand Up @@ -56,13 +58,15 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
IRewardsCoordinator __rewardsCoordinator,
IRegistryCoordinator __registryCoordinator,
IStakeRegistry __stakeRegistry,
IPermissionController __permissionController
IPermissionController __permissionController,
IAllocationManager __allocationManager
) {
_avsDirectory = __avsDirectory;
_rewardsCoordinator = __rewardsCoordinator;
_registryCoordinator = __registryCoordinator;
_stakeRegistry = __stakeRegistry;
_permissionController = __permissionController;
_allocationManager = __allocationManager;
}

// storage gap for upgradeability
Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/IServiceManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,12 @@ interface IServiceManager is IServiceManagerUI, IServiceManagerErrors {
address target,
bytes4 selector
) external;

/**
* @notice Deregisters an operator from specified operator sets
* @param operator The address of the operator to deregister
* @param operatorSetIds The IDs of the operator sets to deregister from
* @dev Only callable by the RegistryCoordinator
*/
function deregisterOperatorFromOperatorSets(address operator, uint32[] memory operatorSetIds) external;
}
3 changes: 2 additions & 1 deletion test/integration/CoreRegistration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ contract Test_CoreRegistration is MockAVSDeployer {
rewardsCoordinatorMock,
registryCoordinator,
stakeRegistry,
permissionController
permissionController,
allocationManager
);

registryCoordinatorImplementation = new RegistryCoordinatorHarness(
Expand Down
3 changes: 2 additions & 1 deletion test/integration/IntegrationDeployer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ abstract contract IntegrationDeployer is Test, IUserDeployer {
rewardsCoordinator,
IRegistryCoordinator(registryCoordinator),
stakeRegistry,
permissionController
permissionController,
allocationManager
);

proxyAdmin.upgrade(
Expand Down
2 changes: 2 additions & 0 deletions test/mocks/ECDSAServiceManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ contract ECDSAServiceManagerMock is ECDSAServiceManagerBase {
address target,
bytes4 selector
) external {}

function deregisterOperatorFromOperatorSets(address operator, uint32[] memory operatorSetIds) external {}
}
6 changes: 4 additions & 2 deletions test/mocks/ServiceManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ contract ServiceManagerMock is ServiceManagerBase {
IRewardsCoordinator _rewardsCoordinator,
IRegistryCoordinator _registryCoordinator,
IStakeRegistry _stakeRegistry,
IPermissionController _permissionController
IPermissionController _permissionController,
IAllocationManager _allocationManager
)
ServiceManagerBase(
_avsDirectory,
_rewardsCoordinator,
_registryCoordinator,
_stakeRegistry,
_permissionController
_permissionController,
_allocationManager
)
{}

Expand Down
3 changes: 2 additions & 1 deletion test/unit/ServiceManagerBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ contract ServiceManagerBase_UnitTests is MockAVSDeployer, IServiceManagerBaseEve
rewardsCoordinator,
registryCoordinatorImplementation,
stakeRegistryImplementation,
permissionControllerMock
permissionControllerMock,
allocationManagerMock
);

serviceManager = ServiceManagerMock(
Expand Down
3 changes: 2 additions & 1 deletion test/unit/ServiceManagerRouter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ contract ServiceManagerRouter_UnitTests is MockAVSDeployer {
rewardsCoordinatorImplementation,
registryCoordinatorImplementation,
stakeRegistryImplementation,
permissionControllerMock
permissionControllerMock,
allocationManagerMock
);

_registerOperatorWithCoordinator(defaultOperator, MAX_QUORUM_BITMAP, defaultPubKey);
Expand Down
3 changes: 2 additions & 1 deletion test/utils/MockAVSDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ contract MockAVSDeployer is Test {
IRewardsCoordinator(address(rewardsCoordinatorMock)),
registryCoordinator,
stakeRegistry,
permissionControllerMock
permissionControllerMock,
allocationManagerMock
);
proxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(serviceManager))),
Expand Down

0 comments on commit 603e95e

Please sign in to comment.