Skip to content

Commit 18e8d80

Browse files
committed
chore: resolve merge conflicts
2 parents 558613b + 2475ab8 commit 18e8d80

16 files changed

+427
-56
lines changed
482 KB
Binary file not shown.

src/EjectionManager.sol

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,38 +51,49 @@ contract EjectionManager is OwnableUpgradeable, EjectionManagerStorage {
5151
uint32 ejectedOperators;
5252

5353
bool ratelimitHit;
54-
for (uint8 j = 0; j < operatorIds[i].length; ++j) {
55-
uint256 operatorStake =
56-
stakeRegistry.getCurrentStake(operatorIds[i][j], quorumNumber);
57-
58-
//if caller is ejector enforce ratelimit
59-
if (
60-
isEjector[msg.sender] && quorumEjectionParams[quorumNumber].rateLimitWindow > 0
61-
&& stakeForEjection + operatorStake > amountEjectable
62-
) {
63-
stakeEjectedForQuorum[quorumNumber].push(
64-
StakeEjection({timestamp: block.timestamp, stakeEjected: stakeForEjection})
65-
);
66-
ratelimitHit = true;
67-
break;
68-
}
54+
if(amountEjectable > 0 || msg.sender == owner()){
55+
for(uint8 j = 0; j < operatorIds[i].length; ++j) {
56+
uint256 operatorStake = stakeRegistry.getCurrentStake(operatorIds[i][j], quorumNumber);
57+
58+
//if caller is ejector enforce ratelimit
59+
if(
60+
isEjector[msg.sender] &&
61+
quorumEjectionParams[quorumNumber].rateLimitWindow > 0 &&
62+
stakeForEjection + operatorStake > amountEjectable
63+
){
64+
ratelimitHit = true;
65+
66+
stakeForEjection += operatorStake;
67+
++ejectedOperators;
68+
69+
registryCoordinator.ejectOperator(
70+
registryCoordinator.getOperatorFromId(operatorIds[i][j]),
71+
abi.encodePacked(quorumNumber)
72+
);
6973

70-
stakeForEjection += operatorStake;
71-
++ejectedOperators;
74+
emit OperatorEjected(operatorIds[i][j], quorumNumber);
7275

73-
registryCoordinator.ejectOperator(
74-
registryCoordinator.getOperatorFromId(operatorIds[i][j]),
75-
abi.encodePacked(quorumNumber)
76-
);
76+
break;
77+
}
7778

78-
emit OperatorEjected(operatorIds[i][j], quorumNumber);
79+
stakeForEjection += operatorStake;
80+
++ejectedOperators;
81+
82+
registryCoordinator.ejectOperator(
83+
registryCoordinator.getOperatorFromId(operatorIds[i][j]),
84+
abi.encodePacked(quorumNumber)
85+
);
86+
87+
emit OperatorEjected(operatorIds[i][j], quorumNumber);
88+
}
7989
}
8090

8191
//record the stake ejected if ejector and ratelimit enforced
82-
if (!ratelimitHit && isEjector[msg.sender]) {
83-
stakeEjectedForQuorum[quorumNumber].push(
84-
StakeEjection({timestamp: block.timestamp, stakeEjected: stakeForEjection})
85-
);
92+
if(isEjector[msg.sender] && stakeForEjection > 0){
93+
stakeEjectedForQuorum[quorumNumber].push(StakeEjection({
94+
timestamp: block.timestamp,
95+
stakeEjected: stakeForEjection
96+
}));
8697
}
8798

8899
emit QuorumEjection(ejectedOperators, ratelimitHit);
@@ -151,4 +162,4 @@ contract EjectionManager is OwnableUpgradeable, EjectionManagerStorage {
151162
}
152163
return totalEjectable - totalEjected;
153164
}
154-
}
165+
}

src/RegistryCoordinator.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol";
99
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
1010
import {IServiceManager} from "./interfaces/IServiceManager.sol";
1111
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
12+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
13+
1214

1315
import {BitmapUtils} from "./libraries/BitmapUtils.sol";
1416
import {SlashingRegistryCoordinator} from "./SlashingRegistryCoordinator.sol";
@@ -34,13 +36,15 @@ contract RegistryCoordinator is IRegistryCoordinator, SlashingRegistryCoordinato
3436
IStakeRegistry _stakeRegistry,
3537
IBLSApkRegistry _blsApkRegistry,
3638
IIndexRegistry _indexRegistry,
39+
ISocketRegistry _socketRegistry,
3740
IAllocationManager _allocationManager,
3841
IPauserRegistry _pauserRegistry
3942
)
4043
SlashingRegistryCoordinator(
4144
_stakeRegistry,
4245
_blsApkRegistry,
4346
_indexRegistry,
47+
_socketRegistry,
4448
_allocationManager,
4549
_pauserRegistry
4650
)

src/ServiceManagerBase.sol

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
pragma solidity ^0.8.27;
33

44
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
5+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
57
import {ISignatureUtils} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol";
68
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
79
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
@@ -30,6 +32,7 @@ import {LibMergeSort} from "./libraries/LibMergeSort.sol";
3032
* @author Layr Labs, Inc.
3133
*/
3234
abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
35+
using SafeERC20 for IERC20;
3336
using BitmapUtils for *;
3437

3538
uint256 public constant SLASHER_PROPOSAL_DELAY = 7 days;
@@ -141,26 +144,93 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
141144
* @dev Strategies must be in ascending order of addresses to check for duplicates
142145
* @dev This function will revert if the `rewardsSubmission` is malformed,
143146
* e.g. if the `strategies` and `weights` arrays are of non-equal lengths
147+
* @dev This function may fail to execute with a large number of submissions due to gas limits. Use a
148+
* smaller array of submissions if necessary.
144149
*/
145150
function createAVSRewardsSubmission(
146151
IRewardsCoordinator.RewardsSubmission[] calldata rewardsSubmissions
147152
) public virtual onlyRewardsInitiator {
148153
for (uint256 i = 0; i < rewardsSubmissions.length; ++i) {
149154
// transfer token to ServiceManager and approve RewardsCoordinator to transfer again
150155
// in createAVSRewardsSubmission() call
151-
rewardsSubmissions[i].token.transferFrom(
152-
msg.sender, address(this), rewardsSubmissions[i].amount
156+
rewardsSubmissions[i].token.safeTransferFrom(
157+
msg.sender,
158+
address(this),
159+
rewardsSubmissions[i].amount
153160
);
154-
uint256 allowance =
155-
rewardsSubmissions[i].token.allowance(address(this), address(_rewardsCoordinator));
156-
rewardsSubmissions[i].token.approve(
157-
address(_rewardsCoordinator), rewardsSubmissions[i].amount + allowance
161+
rewardsSubmissions[i].token.safeIncreaseAllowance(
162+
address(_rewardsCoordinator),
163+
rewardsSubmissions[i].amount
158164
);
159165
}
160166

161167
_rewardsCoordinator.createAVSRewardsSubmission(rewardsSubmissions);
162168
}
163169

170+
/**
171+
* @notice Creates a new operator-directed rewards submission, to be split amongst the operators and
172+
* set of stakers delegated to operators who are registered to this `avs`.
173+
* @param operatorDirectedRewardsSubmissions The operator-directed rewards submissions being created.
174+
* @dev Only callable by the permissioned rewardsInitiator address
175+
* @dev The duration of the `rewardsSubmission` cannot exceed `MAX_REWARDS_DURATION`
176+
* @dev The tokens are sent to the `RewardsCoordinator` contract
177+
* @dev This contract needs a token approval of sum of all `operatorRewards` in the `operatorDirectedRewardsSubmissions`, before calling this function.
178+
* @dev Strategies must be in ascending order of addresses to check for duplicates
179+
* @dev Operators must be in ascending order of addresses to check for duplicates.
180+
* @dev This function will revert if the `operatorDirectedRewardsSubmissions` is malformed.
181+
* @dev This function may fail to execute with a large number of submissions due to gas limits. Use a
182+
* smaller array of submissions if necessary.
183+
*/
184+
function createOperatorDirectedAVSRewardsSubmission(
185+
IRewardsCoordinator.OperatorDirectedRewardsSubmission[]
186+
calldata operatorDirectedRewardsSubmissions
187+
) public virtual onlyRewardsInitiator {
188+
for (
189+
uint256 i = 0;
190+
i < operatorDirectedRewardsSubmissions.length;
191+
++i
192+
) {
193+
// Calculate total amount of token to transfer
194+
uint256 totalAmount = 0;
195+
for (
196+
uint256 j = 0;
197+
j <
198+
operatorDirectedRewardsSubmissions[i].operatorRewards.length;
199+
++j
200+
) {
201+
totalAmount += operatorDirectedRewardsSubmissions[i]
202+
.operatorRewards[j]
203+
.amount;
204+
}
205+
206+
// Transfer token to ServiceManager and approve RewardsCoordinator to transfer again
207+
// in createOperatorDirectedAVSRewardsSubmission() call
208+
operatorDirectedRewardsSubmissions[i].token.safeTransferFrom(
209+
msg.sender,
210+
address(this),
211+
totalAmount
212+
);
213+
operatorDirectedRewardsSubmissions[i].token.safeIncreaseAllowance(
214+
address(_rewardsCoordinator),
215+
totalAmount
216+
);
217+
}
218+
219+
_rewardsCoordinator.createOperatorDirectedAVSRewardsSubmission(
220+
address(this),
221+
operatorDirectedRewardsSubmissions
222+
);
223+
}
224+
225+
/**
226+
* @notice Forwards a call to Eigenlayer's RewardsCoordinator contract to set the address of the entity that can call `processClaim` on behalf of this contract.
227+
* @param claimer The address of the entity that can call `processClaim` on behalf of the earner
228+
* @dev Only callable by the owner.
229+
*/
230+
function setClaimerFor(address claimer) public virtual onlyOwner {
231+
_rewardsCoordinator.setClaimerFor(claimer);
232+
}
233+
164234
/**
165235
* @notice Forwards a call to EigenLayer's AVSDirectory contract to confirm operator registration with the AVS
166236
* @param operator The address of the operator to register.
@@ -219,7 +289,12 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
219289
* @dev No guarantee is made on uniqueness of each element in the returned array.
220290
* The off-chain service should do that validation separately
221291
*/
222-
function getRestakeableStrategies() external view virtual returns (address[] memory) {
292+
function getRestakeableStrategies()
293+
external
294+
view
295+
virtual
296+
returns (address[] memory)
297+
{
223298
uint256 quorumCount = _registryCoordinator.quorumCount();
224299

225300
if (quorumCount == 0) {
@@ -234,10 +309,13 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
234309
address[] memory restakedStrategies = new address[](strategyCount);
235310
uint256 index = 0;
236311
for (uint256 i = 0; i < _registryCoordinator.quorumCount(); i++) {
237-
uint256 strategyParamsLength = _stakeRegistry.strategyParamsLength(uint8(i));
312+
uint256 strategyParamsLength = _stakeRegistry.strategyParamsLength(
313+
uint8(i)
314+
);
238315
for (uint256 j = 0; j < strategyParamsLength; j++) {
239-
restakedStrategies[index] =
240-
address(_stakeRegistry.strategyParamsByIndex(uint8(i), j).strategy);
316+
restakedStrategies[index] = address(
317+
_stakeRegistry.strategyParamsByIndex(uint8(i), j).strategy
318+
);
241319
index++;
242320
}
243321
}
@@ -255,28 +333,37 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage {
255333
address operator
256334
) external view virtual returns (address[] memory) {
257335
bytes32 operatorId = _registryCoordinator.getOperatorId(operator);
258-
uint192 operatorBitmap = _registryCoordinator.getCurrentQuorumBitmap(operatorId);
336+
uint192 operatorBitmap = _registryCoordinator.getCurrentQuorumBitmap(
337+
operatorId
338+
);
259339

260340
if (operatorBitmap == 0 || _registryCoordinator.quorumCount() == 0) {
261341
return new address[](0);
262342
}
263343

264344
// Get number of strategies for each quorum in operator bitmap
265-
bytes memory operatorRestakedQuorums = BitmapUtils.bitmapToBytesArray(operatorBitmap);
345+
bytes memory operatorRestakedQuorums = BitmapUtils.bitmapToBytesArray(
346+
operatorBitmap
347+
);
266348
uint256 strategyCount;
267349
for (uint256 i = 0; i < operatorRestakedQuorums.length; i++) {
268-
strategyCount += _stakeRegistry.strategyParamsLength(uint8(operatorRestakedQuorums[i]));
350+
strategyCount += _stakeRegistry.strategyParamsLength(
351+
uint8(operatorRestakedQuorums[i])
352+
);
269353
}
270354

271355
// Get strategies for each quorum in operator bitmap
272356
address[] memory restakedStrategies = new address[](strategyCount);
273357
uint256 index = 0;
274358
for (uint256 i = 0; i < operatorRestakedQuorums.length; i++) {
275359
uint8 quorum = uint8(operatorRestakedQuorums[i]);
276-
uint256 strategyParamsLength = _stakeRegistry.strategyParamsLength(quorum);
360+
uint256 strategyParamsLength = _stakeRegistry.strategyParamsLength(
361+
quorum
362+
);
277363
for (uint256 j = 0; j < strategyParamsLength; j++) {
278-
restakedStrategies[index] =
279-
address(_stakeRegistry.strategyParamsByIndex(quorum, j).strategy);
364+
restakedStrategies[index] = address(
365+
_stakeRegistry.strategyParamsByIndex(quorum, j).strategy
366+
);
280367
index++;
281368
}
282369
}

src/SlashingRegistryCoordinator.sol

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {IBLSApkRegistry, IBLSApkRegistryTypes} from "./interfaces/IBLSApkRegistr
1414
import {IStakeRegistry, IStakeRegistryTypes} from "./interfaces/IStakeRegistry.sol";
1515
import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol";
1616
import {ISlashingRegistryCoordinator} from "./interfaces/ISlashingRegistryCoordinator.sol";
17+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
18+
1719

1820
import {BitmapUtils} from "./libraries/BitmapUtils.sol";
1921
import {BN254} from "./libraries/BN254.sol";
@@ -69,13 +71,15 @@ contract SlashingRegistryCoordinator is
6971
IStakeRegistry _stakeRegistry,
7072
IBLSApkRegistry _blsApkRegistry,
7173
IIndexRegistry _indexRegistry,
74+
ISocketRegistry _socketRegistry,
7275
IAllocationManager _allocationManager,
7376
IPauserRegistry _pauserRegistry
7477
)
7578
SlashingRegistryCoordinatorStorage(
7679
_stakeRegistry,
7780
_blsApkRegistry,
7881
_indexRegistry,
82+
_socketRegistry,
7983
_allocationManager
8084
)
8185
EIP712("AVSRegistryCoordinator", "v0.0.1")
@@ -337,11 +341,9 @@ contract SlashingRegistryCoordinator is
337341
* @notice Updates the socket of the msg.sender given they are a registered operator
338342
* @param socket is the new socket of the operator
339343
*/
340-
function updateSocket(
341-
string memory socket
342-
) external {
344+
function updateSocket(string memory socket) external {
343345
require(_operatorInfo[msg.sender].status == OperatorStatus.REGISTERED, NotRegistered());
344-
emit OperatorSocketUpdate(_operatorInfo[msg.sender].operatorId, socket);
346+
_setOperatorSocket(_operatorInfo[msg.sender].operatorId, socket);
345347
}
346348

347349
/**
@@ -773,6 +775,17 @@ contract SlashingRegistryCoordinator is
773775
return totalStake * setParams.kickBIPsOfTotalStake / BIPS_DENOMINATOR;
774776
}
775777

778+
/**
779+
* @notice Updates an operator's socket address in the SocketRegistry
780+
* @param operatorId The unique identifier of the operator
781+
* @param socket The new socket address to set for the operator
782+
* @dev Emits an OperatorSocketUpdate event after updating
783+
*/
784+
function _setOperatorSocket(bytes32 operatorId, string memory socket) internal {
785+
socketRegistry.setOperatorSocket(operatorId, socket);
786+
emit OperatorSocketUpdate(operatorId, socket);
787+
}
788+
776789
/// @notice verifies churnApprover's signature on operator churn approval and increments the churnApprover nonce
777790
function _verifyChurnApproverSignature(
778791
address registeringOperator,

src/SlashingRegistryCoordinatorStorage.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
IAllocationManagerTypes
1313
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
1414
import {ISlashingRegistryCoordinator} from "./interfaces/ISlashingRegistryCoordinator.sol";
15+
import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol";
1516

1617
abstract contract SlashingRegistryCoordinatorStorage is ISlashingRegistryCoordinator {
1718
/**
@@ -40,6 +41,8 @@ abstract contract SlashingRegistryCoordinatorStorage is ISlashingRegistryCoordin
4041
/// @notice The maximum number of quorums this contract supports
4142
uint8 internal constant MAX_QUORUM_COUNT = 192;
4243

44+
/// @notice
45+
ISocketRegistry public immutable socketRegistry;
4346
/// @notice the BLS Aggregate Pubkey Registry contract that will keep track of operators' aggregate BLS public keys per quorum
4447
IBLSApkRegistry public immutable blsApkRegistry;
4548
/// @notice the Stake Registry contract that will keep track of operators' stakes
@@ -103,11 +106,13 @@ abstract contract SlashingRegistryCoordinatorStorage is ISlashingRegistryCoordin
103106
IStakeRegistry _stakeRegistry,
104107
IBLSApkRegistry _blsApkRegistry,
105108
IIndexRegistry _indexRegistry,
109+
ISocketRegistry _socketRegistry,
106110
IAllocationManager _allocationManager
107111
) {
108112
stakeRegistry = _stakeRegistry;
109113
blsApkRegistry = _blsApkRegistry;
110114
indexRegistry = _indexRegistry;
115+
socketRegistry = _socketRegistry;
111116
allocationManager = _allocationManager;
112117
}
113118

0 commit comments

Comments
 (0)