@@ -15,6 +15,7 @@ import {BitmapUtils} from "./libraries/BitmapUtils.sol";
15
15
import {SlashingRegistryCoordinator} from "./SlashingRegistryCoordinator.sol " ;
16
16
import {ISlashingRegistryCoordinator} from "./interfaces/ISlashingRegistryCoordinator.sol " ;
17
17
import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol " ;
18
+ import {RegistryCoordinatorStorage} from "./RegistryCoordinatorStorage.sol " ;
18
19
19
20
/**
20
21
* @title A `RegistryCoordinator` that has three registries:
@@ -24,12 +25,9 @@ import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/Ownabl
24
25
*
25
26
* @author Layr Labs, Inc.
26
27
*/
27
- contract RegistryCoordinator is IRegistryCoordinator , SlashingRegistryCoordinator {
28
+ contract RegistryCoordinator is RegistryCoordinatorStorage {
28
29
using BitmapUtils for * ;
29
30
30
- /// @notice the ServiceManager for this AVS, which forwards calls onto EigenLayer's core contracts
31
- IServiceManager public immutable serviceManager;
32
-
33
31
constructor (
34
32
IServiceManager _serviceManager ,
35
33
IStakeRegistry _stakeRegistry ,
@@ -39,17 +37,16 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
39
37
IAllocationManager _allocationManager ,
40
38
IPauserRegistry _pauserRegistry
41
39
)
42
- SlashingRegistryCoordinator (
40
+ RegistryCoordinatorStorage (
41
+ _serviceManager,
43
42
_stakeRegistry,
44
43
_blsApkRegistry,
45
44
_indexRegistry,
46
45
_socketRegistry,
47
46
_allocationManager,
48
47
_pauserRegistry
49
- )
50
- {
51
- serviceManager = _serviceManager;
52
- }
48
+ )
49
+ {}
53
50
54
51
/**
55
52
*
@@ -64,44 +61,23 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
64
61
IBLSApkRegistryTypes.PubkeyRegistrationParams memory params ,
65
62
SignatureWithSaltAndExpiry memory operatorSignature
66
63
) external onlyWhenNotPaused (PAUSED_REGISTER_OPERATOR) {
67
- require (! m2QuorumsDisabled, M2QuorumsAlreadyDisabled ());
68
- /**
69
- * If the operator has NEVER registered a pubkey before, use `params` to register
70
- * their pubkey in blsApkRegistry
71
- *
72
- * If the operator HAS registered a pubkey, `params` is ignored and the pubkey hash
73
- * (operatorId) is fetched instead
74
- */
75
- bytes32 operatorId = _getOrCreateOperatorId (msg .sender , params);
76
-
77
- // Register the operator in each of the registry contracts and update the operator's
78
- // quorum bitmap and registration status
79
- uint32 [] memory numOperatorsPerQuorum = _registerOperator ({
64
+ require (! isM2QuorumRegistrationDisabled, M2QuorumRegistrationIsDisabled ());
65
+
66
+ // Check if the operator has registered before
67
+ bool operatorRegisteredBefore = _operatorInfo[msg .sender ].status == OperatorStatus.REGISTERED;
68
+
69
+ // register the operator with the registry coordinator
70
+ _registerOperator ({
80
71
operator: msg .sender ,
81
- operatorId: operatorId ,
72
+ operatorId: _getOrCreateOperatorId ( msg . sender , params) ,
82
73
quorumNumbers: quorumNumbers,
83
- socket: socket
84
- }).numOperatorsPerQuorum;
85
-
86
- // For each quorum, validate that the new operator count does not exceed the maximum
87
- // (If it does, an operator needs to be replaced -- see `registerOperatorWithChurn`)
88
- for (uint256 i = 0 ; i < quorumNumbers.length ; i++ ) {
89
- uint8 quorumNumber = uint8 (quorumNumbers[i]);
90
-
91
- require (
92
- numOperatorsPerQuorum[i] <= _quorumParams[quorumNumber].maxOperatorCount,
93
- MaxQuorumsReached ()
94
- );
95
- }
96
-
97
- // If the operator wasn't registered for any quorums, update their status
98
- // and register them with this AVS in EigenLayer core (DelegationManager)
99
- if (_operatorInfo[msg .sender ].status != OperatorStatus.REGISTERED) {
100
- _operatorInfo[msg .sender ] =
101
- OperatorInfo ({operatorId: operatorId, status: OperatorStatus.REGISTERED});
74
+ socket: socket,
75
+ checkMaxOperatorCount: true
76
+ });
102
77
78
+ // If the operator has never registered before, register them with the AVSDirectory
79
+ if (! operatorRegisteredBefore) {
103
80
serviceManager.registerOperatorToAVS (msg .sender , operatorSignature);
104
- emit OperatorRegistered (msg .sender , operatorId);
105
81
}
106
82
}
107
83
@@ -114,34 +90,24 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
114
90
SignatureWithSaltAndExpiry memory churnApproverSignature ,
115
91
SignatureWithSaltAndExpiry memory operatorSignature
116
92
) external onlyWhenNotPaused (PAUSED_REGISTER_OPERATOR) {
117
- require (! m2QuorumsDisabled, M2QuorumsAlreadyDisabled ());
93
+ require (! isM2QuorumRegistrationDisabled, M2QuorumRegistrationIsDisabled ());
118
94
119
- /**
120
- * If the operator has NEVER registered a pubkey before, use `params` to register
121
- * their pubkey in blsApkRegistry
122
- *
123
- * If the operator HAS registered a pubkey, `params` is ignored and the pubkey hash
124
- * (operatorId) is fetched instead
125
- */
126
- bytes32 operatorId = _getOrCreateOperatorId (msg .sender , params);
95
+ // Check if the operator has registered before
96
+ bool operatorRegisteredBefore = _operatorInfo[msg .sender ].status == OperatorStatus.REGISTERED;
127
97
98
+ // register the operator with the registry coordinator with churn
128
99
_registerOperatorWithChurn ({
129
100
operator: msg .sender ,
130
- operatorId: operatorId ,
101
+ operatorId: _getOrCreateOperatorId ( msg . sender , params) ,
131
102
quorumNumbers: quorumNumbers,
132
103
socket: socket,
133
104
operatorKickParams: operatorKickParams,
134
105
churnApproverSignature: churnApproverSignature
135
106
});
136
107
137
- // If the operator wasn't registered for any quorums, update their status
138
- // and register them with this AVS in EigenLayer core (DelegationManager)
139
- if (_operatorInfo[msg .sender ].status != OperatorStatus.REGISTERED) {
140
- _operatorInfo[msg .sender ] =
141
- OperatorInfo ({operatorId: operatorId, status: OperatorStatus.REGISTERED});
142
-
108
+ // If the operator has never registered before, register them with the AVSDirectory
109
+ if (! operatorRegisteredBefore) {
143
110
serviceManager.registerOperatorToAVS (msg .sender , operatorSignature);
144
- emit OperatorRegistered (msg .sender , operatorId);
145
111
}
146
112
}
147
113
@@ -163,7 +129,7 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
163
129
require (! operatorSetsEnabled, OperatorSetsAlreadyEnabled ());
164
130
165
131
// Set the bitmap for M2 quorums
166
- M2quorumBitmap = _getQuorumBitmap (quorumCount);
132
+ m2QuorumBitmap = _getQuorumBitmap (quorumCount);
167
133
168
134
// Enable operator sets mode
169
135
operatorSetsEnabled = true ;
@@ -175,9 +141,27 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
175
141
function disableM2QuorumRegistration () external onlyOwner {
176
142
require (operatorSetsEnabled, OperatorSetsNotEnabled ());
177
143
178
- m2QuorumsDisabled = true ;
144
+ isM2QuorumRegistrationDisabled = true ;
145
+
146
+ emit M2QuorumRegistrationDisabled ();
147
+ }
179
148
180
- emit M2QuorumsDisabled ();
149
+ /**
150
+ *
151
+ * INTERNAL FUNCTIONS
152
+ *
153
+ */
154
+
155
+ /// @dev override the _forceDeregisterOperator function to handle M2 quorum deregistration
156
+ function _forceDeregisterOperator (address operator , bytes memory quorumNumbers ) internal virtual override {
157
+ if (operatorSetsEnabled) {
158
+ // filter out M2 quorums from the quorum numbers
159
+ uint256 operatorSetBitmap = quorumNumbers.orderedBytesArrayToBitmap ().minus (m2QuorumBitmap);
160
+ if (! operatorSetBitmap.isEmpty ()) {
161
+ // call the parent _forceDeregisterOperator function for operator sets quorums
162
+ super ._forceDeregisterOperator (operator, operatorSetBitmap.bitmapToBytesArray ());
163
+ }
164
+ }
181
165
}
182
166
183
167
/// @dev Hook to allow for any post-deregister logic
@@ -187,7 +171,7 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
187
171
bytes memory quorumNumbers ,
188
172
uint192 newBitmap
189
173
) internal virtual override {
190
- uint256 operatorM2QuorumBitmap = newBitmap.minus (M2quorumBitmap );
174
+ uint256 operatorM2QuorumBitmap = newBitmap.minus (m2QuorumBitmap );
191
175
// If the operator is no longer registered for any M2 quorums, update their status and deregister
192
176
// them from the AVS via the EigenLayer core contracts
193
177
if (operatorM2QuorumBitmap.isEmpty ()) {
@@ -208,13 +192,24 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
208
192
return (1 << quorumCount) - 1 ;
209
193
}
210
194
211
- /// @dev need to override function here since its defined in both these contracts
212
- function owner ()
213
- public
214
- view
215
- override (SlashingRegistryCoordinator, ISlashingRegistryCoordinator)
216
- returns (address )
217
- {
218
- return OwnableUpgradeable.owner ();
195
+ /// @notice Returns true if the quorum number is an M2 quorum
196
+ /// @dev We use bitwise and to check if the quorum number is an M2 quorum
197
+ function _isM2Quorum (
198
+ uint8 quorumNumber
199
+ ) internal view returns (bool ) {
200
+ return m2QuorumBitmap.isSet (quorumNumber);
201
+ }
202
+
203
+ /**
204
+ *
205
+ * VIEW FUNCTIONS
206
+ *
207
+ */
208
+
209
+ /// @notice Returns true if the quorum number is an M2 quorum
210
+ function isM2Quorum (
211
+ uint8 quorumNumber
212
+ ) external view returns (bool ) {
213
+ return _isM2Quorum (quorumNumber);
219
214
}
220
215
}
0 commit comments