Skip to content

Commit b42aa0b

Browse files
authored
onchain socket (#307)
* feat: onchain socket moves sockets onchain to SM * feat: socket registry - move storage to new registry - leave event in RegCoord - trim bytecode from error strings * fix: internal function internal function to update socket
1 parent cb2b334 commit b42aa0b

15 files changed

+192
-95
lines changed

src/RegistryCoordinator.sol

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ pragma solidity ^0.8.12;
33

44
import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol";
55
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
6-
import {ISocketUpdater} from "./interfaces/ISocketUpdater.sol";
76
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
87
import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
98
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
109
import {IServiceManager} from "./interfaces/IServiceManager.sol";
1110
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
11+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
1212

1313
import {EIP1271SignatureUtils} from "eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol";
1414
import {BitmapUtils} from "./libraries/BitmapUtils.sol";
@@ -35,7 +35,6 @@ contract RegistryCoordinator is
3535
Pausable,
3636
OwnableUpgradeable,
3737
RegistryCoordinatorStorage,
38-
ISocketUpdater,
3938
ISignatureUtils
4039
{
4140
using BitmapUtils for *;
@@ -57,9 +56,10 @@ contract RegistryCoordinator is
5756
IServiceManager _serviceManager,
5857
IStakeRegistry _stakeRegistry,
5958
IBLSApkRegistry _blsApkRegistry,
60-
IIndexRegistry _indexRegistry
59+
IIndexRegistry _indexRegistry,
60+
ISocketRegistry _socketRegistry
6161
)
62-
RegistryCoordinatorStorage(_serviceManager, _stakeRegistry, _blsApkRegistry, _indexRegistry)
62+
RegistryCoordinatorStorage(_serviceManager, _stakeRegistry, _blsApkRegistry, _indexRegistry, _socketRegistry)
6363
EIP712("AVSRegistryCoordinator", "v0.0.1")
6464
{
6565
_disableInitializers();
@@ -88,7 +88,7 @@ contract RegistryCoordinator is
8888
) external initializer {
8989
require(
9090
_operatorSetParams.length == _minimumStakes.length && _minimumStakes.length == _strategyParams.length,
91-
"RegistryCoordinator.initialize: input length mismatch"
91+
"RegCoord.initialize: input length mismatch"
9292
);
9393

9494
// Initialize roles
@@ -154,7 +154,7 @@ contract RegistryCoordinator is
154154

155155
require(
156156
numOperatorsPerQuorum[i] <= _quorumParams[quorumNumber].maxOperatorCount,
157-
"RegistryCoordinator.registerOperator: operator count exceeds maximum"
157+
"RegCoord.registerOperator: operator count exceeds maximum"
158158
);
159159
}
160160
}
@@ -179,7 +179,7 @@ contract RegistryCoordinator is
179179
SignatureWithSaltAndExpiry memory churnApproverSignature,
180180
SignatureWithSaltAndExpiry memory operatorSignature
181181
) external onlyWhenNotPaused(PAUSED_REGISTER_OPERATOR) {
182-
require(operatorKickParams.length == quorumNumbers.length, "RegistryCoordinator.registerOperatorWithChurn: input length mismatch");
182+
require(operatorKickParams.length == quorumNumbers.length, "RegCoord.registerOperatorWithChurn: input length mismatch");
183183

184184
/**
185185
* If the operator has NEVER registered a pubkey before, use `params` to register
@@ -289,7 +289,7 @@ contract RegistryCoordinator is
289289
uint192 quorumBitmap = uint192(BitmapUtils.orderedBytesArrayToBitmap(quorumNumbers, quorumCount));
290290
require(
291291
operatorsPerQuorum.length == quorumNumbers.length,
292-
"RegistryCoordinator.updateOperatorsForQuorum: input length mismatch"
292+
"RegCoord.updateOperatorsForQuorum: input length mismatch"
293293
);
294294

295295
// For each quorum, update ALL registered operators
@@ -300,7 +300,7 @@ contract RegistryCoordinator is
300300
address[] calldata currQuorumOperators = operatorsPerQuorum[i];
301301
require(
302302
currQuorumOperators.length == indexRegistry.totalOperatorsForQuorum(quorumNumber),
303-
"RegistryCoordinator.updateOperatorsForQuorum: number of updated operators does not match quorum total"
303+
"RegCoord.updateOperatorsForQuorum: number of updated operators does not match quorum total"
304304
);
305305

306306
address prevOperatorAddress = address(0);
@@ -319,12 +319,12 @@ contract RegistryCoordinator is
319319
// Check that the operator is registered
320320
require(
321321
BitmapUtils.isSet(currentBitmap, quorumNumber),
322-
"RegistryCoordinator.updateOperatorsForQuorum: operator not in quorum"
322+
"RegCoord.updateOperatorsForQuorum: operator not in quorum"
323323
);
324324
// Prevent duplicate operators
325325
require(
326326
operator > prevOperatorAddress,
327-
"RegistryCoordinator.updateOperatorsForQuorum: operators array must be sorted in ascending address order"
327+
"RegCoord.updateOperatorsForQuorum: operators array must be sorted in ascending address order"
328328
);
329329
}
330330

@@ -344,8 +344,8 @@ contract RegistryCoordinator is
344344
* @param socket is the new socket of the operator
345345
*/
346346
function updateSocket(string memory socket) external {
347-
require(_operatorInfo[msg.sender].status == OperatorStatus.REGISTERED, "RegistryCoordinator.updateSocket: operator is not registered");
348-
emit OperatorSocketUpdate(_operatorInfo[msg.sender].operatorId, socket);
347+
require(_operatorInfo[msg.sender].status == OperatorStatus.REGISTERED, "RegCoord.updateSocket: operator not registered");
348+
_setOperatorSocket(_operatorInfo[msg.sender].operatorId, socket);
349349
}
350350

351351
/*******************************************************************************
@@ -473,12 +473,12 @@ contract RegistryCoordinator is
473473
*/
474474
uint192 quorumsToAdd = uint192(BitmapUtils.orderedBytesArrayToBitmap(quorumNumbers, quorumCount));
475475
uint192 currentBitmap = _currentOperatorBitmap(operatorId);
476-
require(!quorumsToAdd.isEmpty(), "RegistryCoordinator._registerOperator: bitmap cannot be 0");
477-
require(quorumsToAdd.noBitsInCommon(currentBitmap), "RegistryCoordinator._registerOperator: operator already registered for some quorums being registered for");
476+
require(!quorumsToAdd.isEmpty(), "RegCoord._registerOperator: bitmap cannot be 0");
477+
require(quorumsToAdd.noBitsInCommon(currentBitmap), "RegCoord._registerOperator: operator already registered for some quorums");
478478
uint192 newBitmap = uint192(currentBitmap.plus(quorumsToAdd));
479479

480480
// Check that the operator can reregister if ejected
481-
require(lastEjectionTimestamp[operator] + ejectionCooldown < block.timestamp, "RegistryCoordinator._registerOperator: operator cannot reregister yet");
481+
require(lastEjectionTimestamp[operator] + ejectionCooldown < block.timestamp, "RegCoord._registerOperator: operator cannot reregister yet");
482482

483483
/**
484484
* Update operator's bitmap, socket, and status. Only update operatorInfo if needed:
@@ -489,8 +489,6 @@ contract RegistryCoordinator is
489489
newBitmap: newBitmap
490490
});
491491

492-
emit OperatorSocketUpdate(operatorId, socket);
493-
494492
// If the operator wasn't registered for any quorums, update their status
495493
// and register them with this AVS in EigenLayer core (DelegationManager)
496494
if (_operatorInfo[operator].status != OperatorStatus.REGISTERED) {
@@ -502,6 +500,8 @@ contract RegistryCoordinator is
502500
// Register the operator with the EigenLayer core contracts via this AVS's ServiceManager
503501
serviceManager.registerOperatorToAVS(operator, operatorSignature);
504502

503+
_setOperatorSocket(operatorId, socket);
504+
505505
emit OperatorRegistered(operator, operatorId);
506506
}
507507

@@ -519,7 +519,7 @@ contract RegistryCoordinator is
519519
* @dev Reverts if the caller is not the ejector
520520
*/
521521
function _checkEjector() internal view {
522-
require(msg.sender == ejector, "RegistryCoordinator.onlyEjector: caller is not the ejector");
522+
require(msg.sender == ejector, "RegCoord.onlyEjector: caller is not the ejector");
523523
}
524524

525525
/**
@@ -530,7 +530,7 @@ contract RegistryCoordinator is
530530
function _checkQuorumExists(uint8 quorumNumber) internal view {
531531
require(
532532
quorumNumber < quorumCount,
533-
"RegistryCoordinator.quorumExists: quorum does not exist"
533+
"RegCoord.quorumExists: quorum does not exist"
534534
);
535535
}
536536

@@ -581,18 +581,18 @@ contract RegistryCoordinator is
581581
) internal view {
582582
address operatorToKick = kickParams.operator;
583583
bytes32 idToKick = _operatorInfo[operatorToKick].operatorId;
584-
require(newOperator != operatorToKick, "RegistryCoordinator._validateChurn: cannot churn self");
585-
require(kickParams.quorumNumber == quorumNumber, "RegistryCoordinator._validateChurn: quorumNumber not the same as signed");
584+
require(newOperator != operatorToKick, "RegCoord._validateChurn: cannot churn self");
585+
require(kickParams.quorumNumber == quorumNumber, "RegCoord._validateChurn: quorumNumber not the same as signed");
586586

587587
// Get the target operator's stake and check that it is below the kick thresholds
588588
uint96 operatorToKickStake = stakeRegistry.getCurrentStake(idToKick, quorumNumber);
589589
require(
590590
newOperatorStake > _individualKickThreshold(operatorToKickStake, setParams),
591-
"RegistryCoordinator._validateChurn: incoming operator has insufficient stake for churn"
591+
"RegCoord._validateChurn: incoming operator has insufficient stake for churn"
592592
);
593593
require(
594594
operatorToKickStake < _totalKickThreshold(totalQuorumStake, setParams),
595-
"RegistryCoordinator._validateChurn: cannot kick operator with more than kickBIPsOfTotalStake"
595+
"RegCoord._validateChurn: cannot kick operator with more than kickBIPsOfTotalStake"
596596
);
597597
}
598598

@@ -608,7 +608,7 @@ contract RegistryCoordinator is
608608
// Fetch the operator's info and ensure they are registered
609609
OperatorInfo storage operatorInfo = _operatorInfo[operator];
610610
bytes32 operatorId = operatorInfo.operatorId;
611-
require(operatorInfo.status == OperatorStatus.REGISTERED, "RegistryCoordinator._deregisterOperator: operator is not registered");
611+
require(operatorInfo.status == OperatorStatus.REGISTERED, "RegCoord._deregisterOperator: operator is not registered");
612612

613613
/**
614614
* Get bitmap of quorums to deregister from and operator's current bitmap. Validate that:
@@ -619,8 +619,8 @@ contract RegistryCoordinator is
619619
*/
620620
uint192 quorumsToRemove = uint192(BitmapUtils.orderedBytesArrayToBitmap(quorumNumbers, quorumCount));
621621
uint192 currentBitmap = _currentOperatorBitmap(operatorId);
622-
require(!quorumsToRemove.isEmpty(), "RegistryCoordinator._deregisterOperator: bitmap cannot be 0");
623-
require(quorumsToRemove.isSubsetOf(currentBitmap), "RegistryCoordinator._deregisterOperator: operator is not registered for specified quorums");
622+
require(!quorumsToRemove.isEmpty(), "RegCoord._deregisterOperator: bitmap cannot be 0");
623+
require(quorumsToRemove.isSubsetOf(currentBitmap), "RegCoord._deregisterOperator: operator is not registered for quorums");
624624
uint192 newBitmap = uint192(currentBitmap.minus(quorumsToRemove));
625625

626626
// Update operator's bitmap and status
@@ -692,8 +692,8 @@ contract RegistryCoordinator is
692692
SignatureWithSaltAndExpiry memory churnApproverSignature
693693
) internal {
694694
// make sure the salt hasn't been used already
695-
require(!isChurnApproverSaltUsed[churnApproverSignature.salt], "RegistryCoordinator._verifyChurnApproverSignature: churnApprover salt already used");
696-
require(churnApproverSignature.expiry >= block.timestamp, "RegistryCoordinator._verifyChurnApproverSignature: churnApprover signature expired");
695+
require(!isChurnApproverSaltUsed[churnApproverSignature.salt], "RegCoord._verifyChurnApproverSignature: churnApprover salt already used");
696+
require(churnApproverSignature.expiry >= block.timestamp, "RegCoord._verifyChurnApproverSignature: churnApprover signature expired");
697697

698698
// set salt used to true
699699
isChurnApproverSaltUsed[churnApproverSignature.salt] = true;
@@ -721,7 +721,7 @@ contract RegistryCoordinator is
721721
) internal {
722722
// Increment the total quorum count. Fails if we're already at the max
723723
uint8 prevQuorumCount = quorumCount;
724-
require(prevQuorumCount < MAX_QUORUM_COUNT, "RegistryCoordinator.createQuorum: max quorums reached");
724+
require(prevQuorumCount < MAX_QUORUM_COUNT, "RegCoord.createQuorum: max quorums reached");
725725
quorumCount = prevQuorumCount + 1;
726726

727727
// The previous count is the new quorum's number
@@ -803,7 +803,7 @@ contract RegistryCoordinator is
803803
}
804804

805805
revert(
806-
"RegistryCoordinator.getQuorumBitmapIndexAtBlockNumber: no bitmap update found for operatorId at block number"
806+
"RegCoord.getQuorumBitmapIndexAtBlockNumber: no bitmap update found for operator at blockNumber"
807807
);
808808
}
809809

@@ -822,6 +822,11 @@ contract RegistryCoordinator is
822822
ejector = newEjector;
823823
}
824824

825+
function _setOperatorSocket(bytes32 operatorId, string memory socket) internal {
826+
socketRegistry.setOperatorSocket(operatorId, socket);
827+
emit OperatorSocketUpdate(operatorId, socket);
828+
}
829+
825830
/*******************************************************************************
826831
VIEW FUNCTIONS
827832
*******************************************************************************/
@@ -887,11 +892,11 @@ contract RegistryCoordinator is
887892
*/
888893
require(
889894
blockNumber >= quorumBitmapUpdate.updateBlockNumber,
890-
"RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber"
895+
"RegCoord.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from after blockNumber"
891896
);
892897
require(
893898
quorumBitmapUpdate.nextUpdateBlockNumber == 0 || blockNumber < quorumBitmapUpdate.nextUpdateBlockNumber,
894-
"RegistryCoordinator.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from before blockNumber"
899+
"RegCoord.getQuorumBitmapAtBlockNumberByIndex: quorumBitmapUpdate is from before blockNumber"
895900
);
896901

897902
return quorumBitmapUpdate.quorumBitmap;

src/RegistryCoordinatorStorage.sol

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
66
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
77
import {IServiceManager} from "./interfaces/IServiceManager.sol";
88
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
9+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
910

1011
abstract contract RegistryCoordinatorStorage is IRegistryCoordinator {
1112

@@ -39,6 +40,8 @@ abstract contract RegistryCoordinatorStorage is IRegistryCoordinator {
3940
IStakeRegistry public immutable stakeRegistry;
4041
/// @notice the Index Registry contract that will keep track of operators' indexes
4142
IIndexRegistry public immutable indexRegistry;
43+
/// @notice the Socket Registry contract that will keep track of operators' sockets
44+
ISocketRegistry public immutable socketRegistry;
4245

4346
/*******************************************************************************
4447
STATE
@@ -73,12 +76,14 @@ abstract contract RegistryCoordinatorStorage is IRegistryCoordinator {
7376
IServiceManager _serviceManager,
7477
IStakeRegistry _stakeRegistry,
7578
IBLSApkRegistry _blsApkRegistry,
76-
IIndexRegistry _indexRegistry
79+
IIndexRegistry _indexRegistry,
80+
ISocketRegistry _socketRegistry
7781
) {
7882
serviceManager = _serviceManager;
7983
stakeRegistry = _stakeRegistry;
8084
blsApkRegistry = _blsApkRegistry;
8185
indexRegistry = _indexRegistry;
86+
socketRegistry = _socketRegistry;
8287
}
8388

8489
// storage gap for upgradeability

src/SocketRegistry.sol

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
5+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
6+
7+
/**
8+
* @title A `Registry` that keeps track of operator sockets.
9+
* @author Layr Labs, Inc.
10+
*/
11+
contract SocketRegistry is ISocketRegistry {
12+
13+
/// @notice The address of the RegistryCoordinator
14+
address public immutable registryCoordinator;
15+
16+
/// @notice A mapping from operator IDs to their sockets
17+
mapping(bytes32 => string) public operatorIdToSocket;
18+
19+
/// @notice A modifier that only allows the RegistryCoordinator to call a function
20+
modifier onlyRegistryCoordinator() {
21+
require(msg.sender == address(registryCoordinator), "SocketRegistry.onlyRegistryCoordinator: caller is not the RegistryCoordinator");
22+
_;
23+
}
24+
25+
/// @notice A modifier that only allows the owner of the RegistryCoordinator to call a function
26+
modifier onlyCoordinatorOwner() {
27+
require(msg.sender == IRegistryCoordinator(registryCoordinator).owner(), "SocketRegistry.onlyCoordinatorOwner: caller is not the owner of the registryCoordinator");
28+
_;
29+
}
30+
31+
constructor(IRegistryCoordinator _registryCoordinator) {
32+
registryCoordinator = address(_registryCoordinator);
33+
}
34+
35+
/// @notice sets the socket for an operator only callable by the RegistryCoordinator
36+
function setOperatorSocket(bytes32 _operatorId, string memory _socket) external onlyRegistryCoordinator {
37+
operatorIdToSocket[_operatorId] = _socket;
38+
}
39+
40+
/// @notice migrates the sockets for a list of operators only callable by the owner of the RegistryCoordinator
41+
function migrateOperatorSockets(bytes32[] memory _operatorIds, string[] memory _sockets) external onlyCoordinatorOwner {
42+
for (uint256 i = 0; i < _operatorIds.length; i++) {
43+
operatorIdToSocket[_operatorIds[i]] = _sockets[i];
44+
}
45+
}
46+
47+
/// @notice gets the stored socket for an operator
48+
function getOperatorSocket(bytes32 _operatorId) external view returns (string memory) {
49+
return operatorIdToSocket[_operatorId];
50+
}
51+
52+
}

src/interfaces/IRegistryCoordinator.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ interface IRegistryCoordinator {
2525

2626
event EjectorUpdated(address prevEjector, address newEjector);
2727

28+
event OperatorSocketUpdate(bytes32 indexed operatorId, string socket);
29+
2830
/// @notice emitted when all the operators for a quorum are updated at once
2931
event QuorumBlockNumberUpdated(uint8 indexed quorumNumber, uint256 blocknumber);
3032

@@ -150,4 +152,10 @@ interface IRegistryCoordinator {
150152

151153
/// @notice The owner of the registry coordinator
152154
function owner() external view returns (address);
155+
156+
/**
157+
* @notice Updates the socket of the msg.sender given they are a registered operator
158+
* @param socket is the new socket of the operator
159+
*/
160+
function updateSocket(string memory socket) external;
153161
}

src/interfaces/ISocketRegistry.sol

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
interface ISocketRegistry {
5+
/// @notice sets the socket for an operator only callable by the RegistryCoordinator
6+
function setOperatorSocket(bytes32 _operatorId, string memory _socket) external;
7+
8+
/// @notice gets the stored socket for an operator
9+
function getOperatorSocket(bytes32 _operatorId) external view returns (string memory);
10+
}

src/interfaces/ISocketUpdater.sol

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)