Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 55 additions & 10 deletions src/avs/task/TaskAVSRegistrarBase.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import {IAllocationManager} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IPermissionController} from
"eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";
import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol";
import {AVSRegistrarWithSocket} from
"../../middlewareV2/registrar/presets/AVSRegistrarWithSocket.sol";
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";

import {AVSRegistrar} from "../../middlewareV2/registrar/AVSRegistrar.sol";
import {SocketRegistry} from "../../middlewareV2/registrar/modules/SocketRegistry.sol";
import {Allowlist} from "../../middlewareV2/registrar/modules/Allowlist.sol";
import {ITaskAVSRegistrarBase} from "../../interfaces/ITaskAVSRegistrarBase.sol";
import {TaskAVSRegistrarBaseStorage} from "./TaskAVSRegistrarBaseStorage.sol";

Expand All @@ -19,9 +20,9 @@ import {TaskAVSRegistrarBaseStorage} from "./TaskAVSRegistrarBaseStorage.sol";
* @notice Abstract AVS Registrar for task-based AVSs
*/
abstract contract TaskAVSRegistrarBase is
Initializable,
OwnableUpgradeable,
AVSRegistrarWithSocket,
AVSRegistrar,
SocketRegistry,
Allowlist,
TaskAVSRegistrarBaseStorage
{
/**
Expand All @@ -34,7 +35,7 @@ abstract contract TaskAVSRegistrarBase is
IAllocationManager _allocationManager,
IKeyRegistrar _keyRegistrar,
IPermissionController _permissionController
) AVSRegistrarWithSocket(_allocationManager, _keyRegistrar, _permissionController) {
) AVSRegistrar(_allocationManager, _keyRegistrar) SocketRegistry(_permissionController) {
_disableInitializers();
}

Expand All @@ -49,9 +50,9 @@ abstract contract TaskAVSRegistrarBase is
address _owner,
AvsConfig memory _initialConfig
) internal onlyInitializing {
__Allowlist_init(_owner); // initializes Ownable
__AVSRegistrar_init(_avs);
__Ownable_init();
_transferOwnership(_owner);

_setAvsConfig(_initialConfig);
}

Expand Down Expand Up @@ -93,4 +94,48 @@ abstract contract TaskAVSRegistrarBase is
avsConfig = config;
emit AvsConfigSet(config.aggregatorOperatorSetId, config.executorOperatorSetIds);
}

/**
* @notice Before registering operator, check if the operator is in the allowlist for the aggregator operator set
* @dev Only the aggregator operator set requires allowlist validation. Executor operator sets do not require allowlist checks.
* @param operator The address of the operator
* @param operatorSetIds The IDs of the operator sets
* @param data The data passed to the operator
*/
function _beforeRegisterOperator(
address operator,
uint32[] calldata operatorSetIds,
bytes calldata data
) internal override {
super._beforeRegisterOperator(operator, operatorSetIds, data);

for (uint32 i = 0; i < operatorSetIds.length; i++) {
if (operatorSetIds[i] == avsConfig.aggregatorOperatorSetId) {
require(
isOperatorAllowed(OperatorSet({avs: avs, id: operatorSetIds[i]}), operator),
OperatorNotInAllowlist()
);
}
}
}

/**
* @notice Set the socket for the operator
* @dev This function sets the socket even if the operator is already registered
* @dev Operators should make sure to always provide the socket when registering
* @param operator The address of the operator
* @param operatorSetIds The IDs of the operator sets
* @param data The data passed to the operator
*/
function _afterRegisterOperator(
address operator,
uint32[] calldata operatorSetIds,
bytes calldata data
) internal override {
super._afterRegisterOperator(operator, operatorSetIds, data);

// Set operator socket
string memory socket = abi.decode(data, (string));
_setOperatorSocket(operator, socket);
}
}
4 changes: 3 additions & 1 deletion src/interfaces/ITaskAVSRegistrarBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.27;
import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol";
import {IAVSRegistrarInternal} from "./IAVSRegistrarInternal.sol";
import {ISocketRegistryV2} from "./ISocketRegistryV2.sol";
import {IAllowlist} from "./IAllowlist.sol";

/**
* @title ITaskAVSRegistrarBaseTypes
Expand Down Expand Up @@ -59,7 +60,8 @@ interface ITaskAVSRegistrarBase is
ITaskAVSRegistrarBaseEvents,
IAVSRegistrar,
IAVSRegistrarInternal,
ISocketRegistryV2
ISocketRegistryV2,
IAllowlist
{
/**
* @notice Sets the configuration for this AVS
Expand Down
14 changes: 14 additions & 0 deletions test/mocks/AllocationManagerMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -332,4 +332,18 @@ contract AllocationManagerMock is AllocationManagerIntermediate {

return minimumSlashableStake;
}

/**
* @notice Register an operator to an AVS through the AVS registrar
* @dev This function delegates to the appropriate AVS registrar
*/
function registerOperator(
address avs,
address operator,
uint32[] calldata operatorSetIds,
bytes calldata data
) external {
IAVSRegistrar avsRegistrar = IAVSRegistrar(_avsRegistrar[avs]);
avsRegistrar.registerOperator(operator, avs, operatorSetIds, data);
}
}
Loading
Loading