diff --git a/foundry.toml b/foundry.toml index b2e0400a..b5b6c67c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -26,15 +26,15 @@ # Specifies the exact version of Solidity to use, overriding auto-detection. solc_version = '0.8.27' # If enabled, treats Solidity compiler warnings as errors, preventing artifact generation if warnings are present. - deny_warnings = false + deny_warnings = false # If set to true, changes compilation pipeline to go through the new IR optimizer. via_ir = false # Whether or not to enable the Solidity optimizer. optimizer = true - # The number of runs specifies roughly how often each opcode of the deployed code will be executed - # across the life-time of the contract. This means it is a trade-off parameter between code size (deploy cost) + # The number of runs specifies roughly how often each opcode of the deployed code will be executed + # across the life-time of the contract. This means it is a trade-off parameter between code size (deploy cost) # and code execution cost (cost after deployment). - optimizer_runs = 200 + optimizer_runs = 100 # Test Configuration @@ -44,7 +44,7 @@ # - 4 (-vvvv): Stack traces for all tests and setup traces for failing tests are displayed. # - 5 (-vvvvv): Stack and setup traces are always displayed. verbosity = 0 - # Enables the Foreign Function Interface (FFI) cheatcode. + # Enables the Foreign Function Interface (FFI) cheatcode. # WARNING: This allows arbitrary programs to run on your computer, which poses security risks. ffi = true # Contracts to include in gas reports. By default, all contracts are included. @@ -53,7 +53,7 @@ show_progress = true # Sparse mode only compiles files that match certain criteria. sparse_mode = true - + gas_limit = 5000000000 no-match-contract = "FFI" fs_permissions = [{ access = "read-write", path = "./" }] @@ -64,13 +64,13 @@ # Formatting style for long function headers multiline_func_header = "params_first" # Options: "attributes_first", "params_first", "all" # Sort import statements alphabetically - sort_imports = false + sort_imports = false # Maximum line length where formatter will wrap the line line_length = 100 # Default: 120 # Number of spaces per indentation level tab_width = 4 # Default: 4 # Whether to print spaces between brackets - bracket_spacing = false + bracket_spacing = false # Style of uint/int256 types int_types = "long" # Options: "long", "short", "preserve" # Quotation mark style @@ -78,7 +78,7 @@ # Style of underscores in number literals number_underscore = "remove" # Options: "preserve", "thousands", "remove" # Whether or not to wrap comments at line_length - wrap_comments = false + wrap_comments = false # List of files to ignore during formatting (can use glob patterns) # ignore = [ # "./script/**/*", @@ -94,11 +94,13 @@ # ] [profile.ci.fuzz] - optimizer = false + optimizer=true + optimizer_runs = 100 runs = 32 [profile.intense.fuzz] - optimizer = false + optimizer=true + optimizer_runs = 100 runs = 5000 [profile.forktest.fuzz] diff --git a/src/BLSApkRegistry.sol b/src/BLSApkRegistry.sol index abc2c3ce..94ca7aea 100644 --- a/src/BLSApkRegistry.sol +++ b/src/BLSApkRegistry.sol @@ -82,7 +82,7 @@ contract BLSApkRegistry is BLSApkRegistryStorage { address operator, PubkeyRegistrationParams calldata params, BN254.G1Point calldata pubkeyRegistrationMessageHash - ) external onlyRegistryCoordinator returns (bytes32 operatorId) { + ) public onlyRegistryCoordinator returns (bytes32 operatorId) { bytes32 pubkeyHash = BN254.hashG1Point(params.pubkeyG1); require(pubkeyHash != ZERO_PK_HASH, ZeroPubKey()); require(getOperatorId(operator) == bytes32(0), OperatorAlreadyRegistered()); @@ -124,6 +124,19 @@ contract BLSApkRegistry is BLSApkRegistryStorage { return pubkeyHash; } + /// @inheritdoc IBLSApkRegistry + function getOrRegisterOperatorId( + address operator, + PubkeyRegistrationParams calldata params, + BN254.G1Point calldata pubkeyRegistrationMessageHash + ) external onlyRegistryCoordinator returns (bytes32 operatorId) { + operatorId = getOperatorId(operator); + if (operatorId == 0) { + operatorId = registerBLSPublicKey(operator, params, pubkeyRegistrationMessageHash); + } + return operatorId; + } + /// @notice Verifies and registers a G2 public key for an operator that already has a G1 key /// @dev This is meant to be used as a one-time way to add G2 public keys for operators that have G1 keys but no G2 key on chain /// @param operator The address of the operator to register the G2 key for diff --git a/src/RegistryCoordinator.sol b/src/RegistryCoordinator.sol index 052851e3..2f481e09 100644 --- a/src/RegistryCoordinator.sol +++ b/src/RegistryCoordinator.sol @@ -14,7 +14,9 @@ import {IBLSApkRegistry, IBLSApkRegistryTypes} from "./interfaces/IBLSApkRegistr import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol"; import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol"; import {IServiceManager} from "./interfaces/IServiceManager.sol"; -import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol"; +import { + IRegistryCoordinator, IRegistryCoordinatorTypes +} from "./interfaces/IRegistryCoordinator.sol"; import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol"; import {BitmapUtils} from "./libraries/BitmapUtils.sol"; @@ -32,36 +34,21 @@ import {RegistryCoordinatorStorage} from "./RegistryCoordinatorStorage.sol"; * * @author Layr Labs, Inc. */ -contract RegistryCoordinator is RegistryCoordinatorStorage { +contract RegistryCoordinator is RegistryCoordinatorStorage, SlashingRegistryCoordinator { using BitmapUtils for *; constructor( - IServiceManager _serviceManager, - IStakeRegistry _stakeRegistry, - IBLSApkRegistry _blsApkRegistry, - IIndexRegistry _indexRegistry, - ISocketRegistry _socketRegistry, - IAllocationManager _allocationManager, - IPauserRegistry _pauserRegistry, - string memory _version + IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params ) - RegistryCoordinatorStorage( - _serviceManager, - _stakeRegistry, - _blsApkRegistry, - _indexRegistry, - _socketRegistry, - _allocationManager, - _pauserRegistry - ) + RegistryCoordinatorStorage(params.serviceManager) SlashingRegistryCoordinator( - _stakeRegistry, - _blsApkRegistry, - _indexRegistry, - _socketRegistry, - _allocationManager, - _pauserRegistry, - _version + params.slashingParams.stakeRegistry, + params.slashingParams.blsApkRegistry, + params.slashingParams.indexRegistry, + params.slashingParams.socketRegistry, + params.slashingParams.allocationManager, + params.slashingParams.pauserRegistry, + "v0.0.1" ) {} @@ -181,7 +168,7 @@ contract RegistryCoordinator is RegistryCoordinatorStorage { for (uint256 i = 0; i < quorumNumbers.length; i++) { singleQuorumNumber[0] = quorumNumbers[i]; - if (_isM2Quorum(uint8(quorumNumbers[i]))) { + if (isM2Quorum(uint8(quorumNumbers[i]))) { // For M2 quorums, use _deregisterOperator _deregisterOperator({operator: operator, quorumNumbers: singleQuorumNumber}); } else { @@ -283,14 +270,6 @@ contract RegistryCoordinator is RegistryCoordinatorStorage { return (1 << quorumCount) - 1; } - /// @notice Returns true if the quorum number is an M2 quorum - /// @dev We use bitwise and to check if the quorum number is an M2 quorum - function _isM2Quorum( - uint8 quorumNumber - ) internal view returns (bool) { - return m2QuorumBitmap().isSet(quorumNumber); - } - /** * * VIEW FUNCTIONS @@ -311,8 +290,8 @@ contract RegistryCoordinator is RegistryCoordinatorStorage { /// @notice Returns true if the quorum number is an M2 quorum function isM2Quorum( uint8 quorumNumber - ) external view returns (bool) { - return _isM2Quorum(quorumNumber); + ) public view returns (bool) { + return m2QuorumBitmap().isSet(quorumNumber); } /** diff --git a/src/RegistryCoordinatorStorage.sol b/src/RegistryCoordinatorStorage.sol index 840dcbe1..e278d878 100644 --- a/src/RegistryCoordinatorStorage.sol +++ b/src/RegistryCoordinatorStorage.sol @@ -8,15 +8,12 @@ import {IBLSApkRegistry, IBLSApkRegistryTypes} from "./interfaces/IBLSApkRegistr import {IStakeRegistry} from "./interfaces/IStakeRegistry.sol"; import {IIndexRegistry} from "./interfaces/IIndexRegistry.sol"; import {IServiceManager} from "./interfaces/IServiceManager.sol"; -import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol"; +import { + IRegistryCoordinator, IRegistryCoordinatorTypes +} from "./interfaces/IRegistryCoordinator.sol"; import {ISocketRegistry} from "./interfaces/ISocketRegistry.sol"; -import {SlashingRegistryCoordinator} from "./SlashingRegistryCoordinator.sol"; - -abstract contract RegistryCoordinatorStorage is - IRegistryCoordinator, - SlashingRegistryCoordinator -{ +abstract contract RegistryCoordinatorStorage is IRegistryCoordinator { /** * * CONSTANTS AND IMMUTABLES @@ -45,13 +42,7 @@ abstract contract RegistryCoordinatorStorage is uint256 internal _m2QuorumBitmap; constructor( - IServiceManager _serviceManager, - IStakeRegistry _stakeRegistry, - IBLSApkRegistry _blsApkRegistry, - IIndexRegistry _indexRegistry, - ISocketRegistry _socketRegistry, - IAllocationManager _allocationManager, - IPauserRegistry _pauserRegistry + IServiceManager _serviceManager ) { serviceManager = _serviceManager; } diff --git a/src/SlashingRegistryCoordinator.sol b/src/SlashingRegistryCoordinator.sol index 0fc7442e..8f6dc07a 100644 --- a/src/SlashingRegistryCoordinator.sol +++ b/src/SlashingRegistryCoordinator.sol @@ -28,7 +28,8 @@ import {QuorumBitmapHistoryLib} from "./libraries/QuorumBitmapHistoryLib.sol"; import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; -import {EIP712} from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; +import {EIP712Upgradeable} from + "@openzeppelin-upgrades/contracts/utils/cryptography/EIP712Upgradeable.sol"; import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; import {SlashingRegistryCoordinatorStorage} from "./SlashingRegistryCoordinatorStorage.sol"; @@ -45,10 +46,10 @@ import {SlashingRegistryCoordinatorStorage} from "./SlashingRegistryCoordinatorS contract SlashingRegistryCoordinator is SlashingRegistryCoordinatorStorage, Initializable, - EIP712, SemVerMixin, Pausable, OwnableUpgradeable, + EIP712Upgradeable, ISignatureUtilsMixin { using BitmapUtils for *; @@ -89,7 +90,6 @@ contract SlashingRegistryCoordinator is _socketRegistry, _allocationManager ) - EIP712("AVSRegistryCoordinator", _version) SemVerMixin(_version) Pausable(_pauserRegistry) { @@ -102,17 +102,18 @@ contract SlashingRegistryCoordinator is * */ function initialize( - address _initialOwner, - address _churnApprover, - address _ejector, - uint256 _initialPausedStatus, - address _avs + address initialOwner, + address churnApprover, + address ejector, + uint256 initialPausedStatus, + address avs ) external initializer { - _transferOwnership(_initialOwner); - _setChurnApprover(_churnApprover); - _setPausedStatus(_initialPausedStatus); - _setEjector(_ejector); - _setAVS(_avs); + __EIP712_init("AVSRegistryCoordinator", "v0.0.1"); + _transferOwnership(initialOwner); + _setChurnApprover(churnApprover); + _setPausedStatus(initialPausedStatus); + _setEjector(ejector); + _setAVS(avs); } /// @inheritdoc ISlashingRegistryCoordinator @@ -668,13 +669,9 @@ contract SlashingRegistryCoordinator is address operator, IBLSApkRegistryTypes.PubkeyRegistrationParams memory params ) internal returns (bytes32 operatorId) { - operatorId = blsApkRegistry.getOperatorId(operator); - if (operatorId == 0) { - operatorId = blsApkRegistry.registerBLSPublicKey( - operator, params, pubkeyRegistrationMessageHash(operator) - ); - } - return operatorId; + return blsApkRegistry.getOrRegisterOperatorId( + operator, params, pubkeyRegistrationMessageHash(operator) + ); } /** @@ -1110,9 +1107,7 @@ contract SlashingRegistryCoordinator is function pubkeyRegistrationMessageHash( address operator ) public view returns (BN254.G1Point memory) { - return BN254.hashToG1( - _hashTypedDataV4(keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator))) - ); + return BN254.hashToG1(calculatePubkeyRegistrationMessageHash(operator)); } /** diff --git a/src/interfaces/IBLSApkRegistry.sol b/src/interfaces/IBLSApkRegistry.sol index e6af1d02..25d7d57c 100644 --- a/src/interfaces/IBLSApkRegistry.sol +++ b/src/interfaces/IBLSApkRegistry.sol @@ -163,7 +163,7 @@ interface IBLSApkRegistry is IBLSApkRegistryErrors, IBLSApkRegistryEvents { * @param quorumNumbers The quorum numbers to register for, where each byte is an 8-bit integer. * @dev Access restricted to the RegistryCoordinator. * @dev Preconditions (assumed, not validated): - * 1. `quorumNumbers` has no duplicatesd + * 1. `quorumNumbers` has no duplicates * 2. `quorumNumbers.length` != 0 * 3. `quorumNumbers` is ordered ascending * 4. The operator is not already registered @@ -291,4 +291,17 @@ interface IBLSApkRegistry is IBLSApkRegistryErrors, IBLSApkRegistryEvents { function getOperatorFromPubkeyHash( bytes32 pubkeyHash ) external view returns (address operator); + + /** + * @notice Gets an operator's ID if it exists, or registers a new BLS public key and returns the new ID + * @param operator The address of the operator + * @param params The parameters for registering a new BLS public key + * @param pubkeyRegistrationMessageHash The hash of the message to sign for registration + * @return operatorId The operator's ID (pubkey hash) + */ + function getOrRegisterOperatorId( + address operator, + PubkeyRegistrationParams calldata params, + BN254.G1Point calldata pubkeyRegistrationMessageHash + ) external returns (bytes32 operatorId); } diff --git a/src/interfaces/IRegistryCoordinator.sol b/src/interfaces/IRegistryCoordinator.sol index e5c34f15..9bd3221e 100644 --- a/src/interfaces/IRegistryCoordinator.sol +++ b/src/interfaces/IRegistryCoordinator.sol @@ -11,8 +11,14 @@ import { ISignatureUtilsMixin, ISignatureUtilsMixinTypes } from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtilsMixin.sol"; -import {IBLSApkRegistryTypes} from "./IBLSApkRegistry.sol"; +import {IBLSApkRegistry, IBLSApkRegistryTypes} from "./IBLSApkRegistry.sol"; import {IServiceManager} from "./IServiceManager.sol"; +import {IStakeRegistry} from "./IStakeRegistry.sol"; +import {IIndexRegistry} from "./IIndexRegistry.sol"; +import {ISocketRegistry} from "./ISocketRegistry.sol"; +import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; +import {IAllocationManager} from + "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; interface IRegistryCoordinatorErrors is ISlashingRegistryCoordinatorErrors { /// @notice Thrown when operator sets mode is already enabled. @@ -27,7 +33,35 @@ interface IRegistryCoordinatorErrors is ISlashingRegistryCoordinatorErrors { error OnlyM2QuorumsAllowed(); } -interface IRegistryCoordinatorTypes is ISlashingRegistryCoordinatorTypes {} +interface IRegistryCoordinatorTypes is ISlashingRegistryCoordinatorTypes { + /** + * @notice Parameters for initializing SlashingRegistryCoordinator + * @param stakeRegistry The StakeRegistry contract that keeps track of operators' stakes + * @param blsApkRegistry The BLSApkRegistry contract that keeps track of operators' BLS public keys + * @param indexRegistry The IndexRegistry contract that keeps track of ordered operator lists + * @param socketRegistry The SocketRegistry contract that keeps track of operators' sockets + * @param allocationManager The AllocationManager contract for operator set management + * @param pauserRegistry The PauserRegistry contract for pausing functionality + */ + struct SlashingRegistryParams { + IStakeRegistry stakeRegistry; + IBLSApkRegistry blsApkRegistry; + IIndexRegistry indexRegistry; + ISocketRegistry socketRegistry; + IAllocationManager allocationManager; + IPauserRegistry pauserRegistry; + } + + /** + * @notice Parameters for initializing RegistryCoordinator + * @param serviceManager The ServiceManager contract for this AVS + * @param slashingParams Parameters for initializing SlashingRegistryCoordinator + */ + struct RegistryCoordinatorParams { + IServiceManager serviceManager; + SlashingRegistryParams slashingParams; + } +} interface IRegistryCoordinatorEvents is ISlashingRegistryCoordinatorEvents, diff --git a/test/End2End.t.sol b/test/End2End.t.sol index 523434e1..5d838ee3 100644 --- a/test/End2End.t.sol +++ b/test/End2End.t.sol @@ -151,7 +151,7 @@ contract End2EndForkTest is Test { MiddlewareDeployLib.upgradeRegistriesM2Coordinator( core.delegationManager, core.avsDirectory, core.allocationManager, middleware ); - MiddlewareDeployLib.ugpradeServiceManager( + MiddlewareDeployLib.upgradeServiceManager( core.avsDirectory, core.rewardsCoordinator, core.allocationManager, middleware, owner ); MiddlewareDeployLib.upgradeM2Coordinator(core.allocationManager, middleware, owner); diff --git a/test/harnesses/RegistryCoordinatorHarness.t.sol b/test/harnesses/RegistryCoordinatorHarness.t.sol index d8366b99..4aa1dfa9 100644 --- a/test/harnesses/RegistryCoordinatorHarness.t.sol +++ b/test/harnesses/RegistryCoordinatorHarness.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.27; import "../../src/RegistryCoordinator.sol"; import {ISocketRegistry} from "../../src/interfaces/ISocketRegistry.sol"; import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol"; +import {IRegistryCoordinatorTypes} from "../../src/interfaces/IRegistryCoordinator.sol"; import "forge-std/Test.sol"; @@ -20,14 +21,17 @@ contract RegistryCoordinatorHarness is RegistryCoordinator, Test { string memory _version ) RegistryCoordinator( - _serviceManager, - _stakeRegistry, - _blsApkRegistry, - _indexRegistry, - _socketRegistry, - _allocationManager, - _pauserRegistry, - _version + IRegistryCoordinatorTypes.RegistryCoordinatorParams( + _serviceManager, + IRegistryCoordinatorTypes.SlashingRegistryParams( + _stakeRegistry, + _blsApkRegistry, + _indexRegistry, + _socketRegistry, + _allocationManager, + _pauserRegistry + ) + ) ) { _transferOwnership(msg.sender); diff --git a/test/integration/IntegrationDeployer.t.sol b/test/integration/IntegrationDeployer.t.sol index a5a30a6b..1d9dcc9e 100644 --- a/test/integration/IntegrationDeployer.t.sol +++ b/test/integration/IntegrationDeployer.t.sol @@ -34,6 +34,7 @@ import "../../src/BLSApkRegistry.sol"; import "../mocks/ServiceManagerMock.sol"; import "../../src/OperatorStateRetriever.sol"; import "../../src/SocketRegistry.sol"; +import "../../src/interfaces/IRegistryCoordinator.sol"; // Mocks and More import "../../src/libraries/BN254.sol"; @@ -423,14 +424,17 @@ abstract contract IntegrationDeployer is Test, IUserDeployer { uint32[] memory slashableStakeQuorumLookAheadPeriods = new uint32[](0); RegistryCoordinator registryCoordinatorImplementation = new RegistryCoordinator( - serviceManager, - stakeRegistry, - blsApkRegistry, - indexRegistry, - socketRegistry, - allocationManager, - pauserRegistry, - "v0.0.1" + IRegistryCoordinatorTypes.RegistryCoordinatorParams( + serviceManager, + IRegistryCoordinatorTypes.SlashingRegistryParams( + stakeRegistry, + blsApkRegistry, + indexRegistry, + socketRegistry, + allocationManager, + pauserRegistry + ) + ) ); proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(payable(address(registryCoordinator))), diff --git a/test/mocks/StakeRegistryMock.sol b/test/mocks/StakeRegistryMock.sol index 9ddfa002..d428a8f7 100644 --- a/test/mocks/StakeRegistryMock.sol +++ b/test/mocks/StakeRegistryMock.sol @@ -277,4 +277,37 @@ contract StakeRegistryMock is IStakeRegistry { ) external pure returns (bytes32) { return bytes32(uint256(keccak256(abi.encodePacked(operator, "operatorId")))); } + + /// @notice Calculates the individual kick threshold for an operator + function calculateIndividualKickThreshold( + uint96 minStake, + uint32 kickBips, + uint32 multiplier + ) external pure returns (uint96) { + return uint96(uint256(minStake) * kickBips * multiplier / 10000); + } + + /// @notice Calculates the total kick threshold across all operators + function calculateTotalKickThreshold( + uint96 individualThreshold, + uint32 numOperators + ) external pure returns (uint96) { + return uint96(uint256(individualThreshold) * numOperators / 2); + } + + /// @notice Validates if the churn rate is within acceptable limits + function validateChurn( + uint32 currentOperators, + uint32 newOperators, + uint32 churnBips + ) external pure returns (bool) { + if (currentOperators == 0) { + return true; + } + + uint32 maxChurn = uint32(uint256(currentOperators) * churnBips / 10000); + uint32 actualChurn = currentOperators > newOperators ? currentOperators - newOperators : 0; + + return actualChurn <= maxChurn; + } } diff --git a/test/utils/MiddlewareDeployLib.sol b/test/utils/MiddlewareDeployLib.sol index 9ee88648..2630fb80 100644 --- a/test/utils/MiddlewareDeployLib.sol +++ b/test/utils/MiddlewareDeployLib.sol @@ -33,7 +33,11 @@ import { } from "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; import {ServiceManagerMock} from "../mocks/ServiceManagerMock.sol"; import {CoreDeployLib} from "./CoreDeployLib.sol"; -import {RegistryCoordinator, IRegistryCoordinator} from "../../src/RegistryCoordinator.sol"; +import { + RegistryCoordinator, + IRegistryCoordinator, + IRegistryCoordinatorTypes +} from "../../src/RegistryCoordinator.sol"; import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; import {IPermissionController} from @@ -199,7 +203,7 @@ library MiddlewareDeployLib { UpgradeableProxyLib.upgrade(deployments.socketRegistry, socketRegistryImpl); } - function ugpradeServiceManager( + function upgradeServiceManager( address avsDirectory, address rewardsCoordinator, address allocationManager, @@ -224,7 +228,7 @@ library MiddlewareDeployLib { ); } - function ugpradeServiceManager( + function upgradeServiceManager( CoreDeployLib.DeploymentData memory core, MiddlewareDeployData memory deployment, address admin @@ -252,18 +256,23 @@ library MiddlewareDeployLib { MiddlewareDeployData memory deployment, address admin ) internal { - address impl = address( - new RegistryCoordinator( - IServiceManager(deployment.serviceManager), - IStakeRegistry(deployment.stakeRegistry), - IBLSApkRegistry(deployment.blsApkRegistry), - IIndexRegistry(deployment.indexRegistry), - ISocketRegistry(deployment.socketRegistry), - IAllocationManager(allocationManager), - IPauserRegistry(deployment.pauserRegistry), - "v0.0.1" - ) - ); + IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = + IRegistryCoordinatorTypes.SlashingRegistryParams({ + stakeRegistry: IStakeRegistry(deployment.stakeRegistry), + blsApkRegistry: IBLSApkRegistry(deployment.blsApkRegistry), + indexRegistry: IIndexRegistry(deployment.indexRegistry), + socketRegistry: ISocketRegistry(deployment.socketRegistry), + allocationManager: IAllocationManager(allocationManager), + pauserRegistry: IPauserRegistry(deployment.pauserRegistry) + }); + + IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = + IRegistryCoordinatorTypes.RegistryCoordinatorParams({ + serviceManager: IServiceManager(deployment.serviceManager), + slashingParams: slashingParams + }); + + address impl = address(new RegistryCoordinator(params)); bytes memory registryCoordinatorUpgradeCall = abi.encodeCall( SlashingRegistryCoordinator.initialize, (admin, admin, admin, 0, deployment.serviceManager)