diff --git a/src/RegistryCoordinator.sol b/src/RegistryCoordinator.sol index 33104f5a..01a76f57 100644 --- a/src/RegistryCoordinator.sol +++ b/src/RegistryCoordinator.sol @@ -18,10 +18,11 @@ import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/Ownabl import {RegistryCoordinatorStorage} from "./RegistryCoordinatorStorage.sol"; /** - * @title A `RegistryCoordinator` that has three registries: + * @title A `RegistryCoordinator` that has four registries: * 1) a `StakeRegistry` that keeps track of operators' stakes * 2) a `BLSApkRegistry` that keeps track of operators' BLS public keys and aggregate BLS public keys for each quorum * 3) an `IndexRegistry` that keeps track of an ordered list of operators for each quorum + * 4) a `SocketRegistry` that keeps track of operators' sockets (arbitrary strings) * * @author Layr Labs, Inc. */ diff --git a/src/SlashingRegistryCoordinator.sol b/src/SlashingRegistryCoordinator.sol index 1c34830d..190277b4 100644 --- a/src/SlashingRegistryCoordinator.sol +++ b/src/SlashingRegistryCoordinator.sol @@ -29,10 +29,11 @@ import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable. import {SlashingRegistryCoordinatorStorage} from "./SlashingRegistryCoordinatorStorage.sol"; /** - * @title A `RegistryCoordinator` that has three registries: + * @title A `RegistryCoordinator` that has four registries: * 1) a `StakeRegistry` that keeps track of operators' stakes * 2) a `BLSApkRegistry` that keeps track of operators' BLS public keys and aggregate BLS public keys for each quorum * 3) an `IndexRegistry` that keeps track of an ordered list of operators for each quorum + * 4) a `SocketRegistry` that keeps track of operators' sockets (arbitrary strings) * * @author Layr Labs, Inc. */ @@ -104,10 +105,12 @@ contract SlashingRegistryCoordinator is _setPausedStatus(_initialPausedStatus); _setEjector(_ejector); _setAccountIdentifier(_accountIdentifier); + // Add registry contracts to the registries array registries.push(address(stakeRegistry)); registries.push(address(blsApkRegistry)); registries.push(address(indexRegistry)); + registries.push(address(socketRegistry)); } /// @inheritdoc ISlashingRegistryCoordinator diff --git a/src/SlashingRegistryCoordinatorStorage.sol b/src/SlashingRegistryCoordinatorStorage.sol index 463dd00a..6bad0b4f 100644 --- a/src/SlashingRegistryCoordinatorStorage.sol +++ b/src/SlashingRegistryCoordinatorStorage.sol @@ -41,7 +41,7 @@ abstract contract SlashingRegistryCoordinatorStorage is ISlashingRegistryCoordin /// @notice The maximum number of quorums this contract supports uint8 internal constant MAX_QUORUM_COUNT = 192; - /// @notice + /// @notice the Socket Registry contract that will keep track of operators' sockets (arbitrary strings) ISocketRegistry public immutable socketRegistry; /// @notice the BLS Aggregate Pubkey Registry contract that will keep track of operators' aggregate BLS public keys per quorum IBLSApkRegistry public immutable blsApkRegistry; diff --git a/src/SocketRegistry.sol b/src/SocketRegistry.sol index f8938152..919ee5e5 100644 --- a/src/SocketRegistry.sol +++ b/src/SocketRegistry.sol @@ -7,30 +7,21 @@ import {SocketRegistryStorage} from "./SocketRegistryStorage.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** - * @title A `Registry` that keeps track of operator sockets. + * @title A `Registry` that keeps track of operator sockets (arbitrary strings). * @author Layr Labs, Inc. */ -contract SocketRegistry is ISocketRegistry, SocketRegistryStorage { - /// @notice A modifier that only allows the RegistryCoordinator to call a function +contract SocketRegistry is SocketRegistryStorage { + /// @notice A modifier that only allows the SlashingRegistryCoordinator to call a function modifier onlySlashingRegistryCoordinator() { require(msg.sender == slashingRegistryCoordinator, OnlySlashingRegistryCoordinator()); _; } - /// @notice A modifier that only allows the owner of the SlashingRegistryCoordinator to call a function - modifier onlyCoordinatorOwner() { - require( - msg.sender == Ownable(slashingRegistryCoordinator).owner(), - OnlySlashingRegistryCoordinatorOwner() - ); - _; - } - constructor( ISlashingRegistryCoordinator _slashingRegistryCoordinator ) SocketRegistryStorage(address(_slashingRegistryCoordinator)) {} - /// @notice sets the socket for an operator only callable by the RegistryCoordinator + /// @inheritdoc ISocketRegistry function setOperatorSocket( bytes32 _operatorId, string memory _socket @@ -38,7 +29,7 @@ contract SocketRegistry is ISocketRegistry, SocketRegistryStorage { operatorIdToSocket[_operatorId] = _socket; } - /// @notice gets the stored socket for an operator + /// @inheritdoc ISocketRegistry function getOperatorSocket( bytes32 _operatorId ) external view returns (string memory) { diff --git a/src/SocketRegistryStorage.sol b/src/SocketRegistryStorage.sol index de3d0451..41d7d3b3 100644 --- a/src/SocketRegistryStorage.sol +++ b/src/SocketRegistryStorage.sol @@ -1,14 +1,28 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.12; +import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol"; + /** - * @title Storage contract for SocketRegistry + * @title Storage variables for the `SocketRegistry` contract. * @author Layr Labs, Inc. */ -contract SocketRegistryStorage { - /// @notice The address of the RegistryCoordinator +abstract contract SocketRegistryStorage is ISocketRegistry { + /** + * + * CONSTANTS AND IMMUTABLES + * + */ + + /// @notice The address of the SlashingRegistryCoordinator address public immutable slashingRegistryCoordinator; + /** + * + * STATE + * + */ + /// @notice A mapping from operator IDs to their sockets mapping(bytes32 => string) public operatorIdToSocket; @@ -18,5 +32,5 @@ contract SocketRegistryStorage { slashingRegistryCoordinator = _slashingRegistryCoordinator; } - uint256[48] private __GAP; + uint256[49] private __GAP; } diff --git a/src/interfaces/ISlashingRegistryCoordinator.sol b/src/interfaces/ISlashingRegistryCoordinator.sol index 467b6104..c91fbbce 100644 --- a/src/interfaces/ISlashingRegistryCoordinator.sol +++ b/src/interfaces/ISlashingRegistryCoordinator.sol @@ -10,6 +10,7 @@ import {IAllocationManager} from import {IBLSApkRegistry} from "./IBLSApkRegistry.sol"; import {IStakeRegistry, IStakeRegistryTypes} from "./IStakeRegistry.sol"; import {IIndexRegistry} from "./IIndexRegistry.sol"; +import {ISocketRegistry} from "./ISocketRegistry.sol"; import {BN254} from "../libraries/BN254.sol"; import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol"; @@ -232,6 +233,12 @@ interface ISlashingRegistryCoordinator is */ function allocationManager() external view returns (IAllocationManager); + /** + * @notice Reference to the SocketRegistry contract. + * @return The SocketRegistry contract interface. + */ + function socketRegistry() external view returns (ISocketRegistry); + /// STORAGE /** diff --git a/src/interfaces/ISocketRegistry.sol b/src/interfaces/ISocketRegistry.sol index 3235711a..d94b1dba 100644 --- a/src/interfaces/ISocketRegistry.sol +++ b/src/interfaces/ISocketRegistry.sol @@ -1,18 +1,25 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; interface ISocketRegistryErrors { - /// @notice Thrown when the caller is not the owner of the SlashingRegistryCoordinator - error OnlySlashingRegistryCoordinatorOwner(); /// @notice Thrown when the caller is not the SlashingRegistryCoordinator error OnlySlashingRegistryCoordinator(); } interface ISocketRegistry is ISocketRegistryErrors { - /// @notice sets the socket for an operator only callable by the RegistryCoordinator + /** + * @notice Sets the socket for an operator. + * @param _operatorId The id of the operator to set the socket for. + * @param _socket The socket (any arbitrary string as deemed useful by an AVS) to set. + * @dev Only callable by the SlashingRegistryCoordinator. + */ function setOperatorSocket(bytes32 _operatorId, string memory _socket) external; - /// @notice gets the stored socket for an operator + /** + * @notice Gets the stored socket for an operator. + * @param _operatorId The id of the operator to query. + * @return The stored socket associated with the operator. + */ function getOperatorSocket( bytes32 _operatorId ) external view returns (string memory); diff --git a/test/unit/SocketRegistryUnit.t.sol b/test/unit/SocketRegistryUnit.t.sol index d8b03669..986519d9 100644 --- a/test/unit/SocketRegistryUnit.t.sol +++ b/test/unit/SocketRegistryUnit.t.sol @@ -11,30 +11,11 @@ interface IOwnable { function owner() external view returns (address); } -contract MockSocketRegistry is SocketRegistry { - constructor( - ISlashingRegistryCoordinator _slashingRegistryCoordinator - ) SocketRegistry(_slashingRegistryCoordinator) {} - - function onlyCoordinatorOwnerFn() external view onlyCoordinatorOwner {} -} - contract SocketRegistryUnitTests is MockAVSDeployer { function setUp() public virtual { _deployMockEigenLayerAndAVS(); } - function testFuzz_revert_onlyCoordinatorOwner( - address caller - ) public { - MockSocketRegistry _socketRegistry = new MockSocketRegistry(registryCoordinator); - - vm.prank(caller); - vm.assume(caller != IOwnable(address(registryCoordinator)).owner()); - vm.expectRevert(ISocketRegistryErrors.OnlySlashingRegistryCoordinatorOwner.selector); - _socketRegistry.onlyCoordinatorOwnerFn(); - } - function test_setOperatorSocket() public { vm.startPrank(address(registryCoordinator)); socketRegistry.setOperatorSocket(defaultOperatorId, "testSocket");