From 190a88013fa8f3ab4a4f1ad281a4ac7585725ef7 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 31 Mar 2025 15:17:15 -0400 Subject: [PATCH 01/20] test: holesky fork eigenda --- test/fork/EigenDA.t.sol | 271 ++++++++++++++++++++++++++++++++ test/{ => fork}/End2End.t.sol | 22 +-- test/utils/EigenDA_Holesky.json | 30 ++++ 3 files changed, 312 insertions(+), 11 deletions(-) create mode 100644 test/fork/EigenDA.t.sol rename test/{ => fork}/End2End.t.sol (96%) create mode 100644 test/utils/EigenDA_Holesky.json diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol new file mode 100644 index 00000000..02d8343a --- /dev/null +++ b/test/fork/EigenDA.t.sol @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.12; + +import {Vm} from "forge-std/Vm.sol"; +import {stdJson} from "forge-std/StdJson.sol"; +import {Test, console2 as console} from "forge-std/Test.sol"; +import {UpgradeableProxyLib} from "../unit/UpgradeableProxyLib.sol"; +import {BN254} from "../../src/libraries/BN254.sol"; + +import {IRegistryCoordinator} from "../../src/interfaces/IRegistryCoordinator.sol"; +import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; +import {IStakeRegistry} from "../../src/interfaces/IStakeRegistry.sol"; +import {IBLSApkRegistry} from "../../src/interfaces/IBLSApkRegistry.sol"; +import {IIndexRegistry} from "../../src/interfaces/IIndexRegistry.sol"; + +contract EigenDATest is Test { + using stdJson for string; + + struct EigenDADeploymentData { + address blsApkRegistry; + address eigenDAProxyAdmin; + address eigenDAServiceManager; + address indexRegistry; + address mockDispatcher; + address operatorStateRetriever; + address registryCoordinator; + address serviceManagerRouter; + address stakeRegistry; + } + + struct EigenDAChainInfo { + uint256 chainId; + uint256 deploymentBlock; + } + + struct EigenDAPermissionsData { + address eigenDABatchConfirmer; + address eigenDAChurner; + address eigenDAEjector; + address eigenDAOwner; + address eigenDAUpgrader; + address pauserRegistry; + } + + struct EigenDAData { + EigenDADeploymentData addresses; + EigenDAChainInfo chainInfo; + EigenDAPermissionsData permissions; + } + + struct ConfigData { + address admin; + address proxyAdmin; + } + + struct RegistryCoordinatorState { + uint32 operatorSetUpdateNonce; + uint8 numQuorums; + } + + struct ServiceManagerState { + bool paused; + address owner; + } + + struct BlsApkRegistryState { + uint32 nextOperatorId; + } + + struct IndexRegistryState { + uint32 nextOperatorId; + } + + struct StakeRegistryState { + uint32 numStrategies; + } + + struct ContractStates { + RegistryCoordinatorState registryCoordinator; + ServiceManagerState serviceManager; + BlsApkRegistryState blsApkRegistry; + IndexRegistryState indexRegistry; + StakeRegistryState stakeRegistry; + } + + // Variables to hold our data + EigenDAData public eigenDAData; + ConfigData public config; + ContractStates public preUpgradeStates; + + // New implementation addresses for upgrade + address public newRegistryCoordinatorImpl; + address public newServiceManagerImpl; + address public newBlsApkRegistryImpl; + address public newIndexRegistryImpl; + address public newStakeRegistryImpl; + + // Test setup function that runs before each test + function setUp() public virtual { + // Setup the Holesky fork and load EigenDA deployment data + eigenDAData = _setupEigenDAFork("test/utils"); + + // Set the admin to the test contract address (this) + config.admin = address(this); + + // Deploy a proxy admin for potential upgrades + config.proxyAdmin = UpgradeableProxyLib.deployProxyAdmin(); + } + + function testEigenDAUpgradeSetup() public { + // 1. Verify initial setup + console.log("Verifying initial EigenDA setup on fork"); + _verifyInitialSetup(); + + _deployNewImplementations(); + + _performUpgrades( + newRegistryCoordinatorImpl, + newServiceManagerImpl, + newBlsApkRegistryImpl, + newIndexRegistryImpl, + newStakeRegistryImpl + ); + + console.log("Contract upgrades completed. Ready for validation testing."); + } + + function _verifyInitialSetup() internal view { + // Verify that contracts are deployed at the expected addresses + require( + eigenDAData.addresses.registryCoordinator != address(0), + "Registry Coordinator should be deployed" + ); + require( + eigenDAData.addresses.eigenDAServiceManager != address(0), + "Service Manager should be deployed" + ); + require( + eigenDAData.addresses.blsApkRegistry != address(0), + "BLS APK Registry should be deployed" + ); + require( + eigenDAData.addresses.indexRegistry != address(0), + "Index Registry should be deployed" + ); + require( + eigenDAData.addresses.stakeRegistry != address(0), + "Stake Registry should be deployed" + ); + + // Verify permissions + require( + eigenDAData.permissions.eigenDAUpgrader != address(0), + "EigenDA Upgrader should be defined" + ); + require( + eigenDAData.permissions.pauserRegistry != address(0), + "Pauser Registry should be defined" + ); + } + + function _deployNewImplementations() internal { + /// TODO: Placeholder for upgrading + } + + function _setupEigenDAFork( + string memory jsonPath + ) internal returns (EigenDAData memory) { + // Get the Holesky RPC URL from environment variables + string memory rpcUrl = vm.envString("HOLESKY_RPC_URL"); + + vm.createSelectFork(rpcUrl); + + EigenDAData memory data = _readEigenDADeploymentJson(jsonPath, 17000); + + vm.rollFork(data.chainInfo.deploymentBlock); + + return data; + } + + function _performUpgrades( + address newRegistryCoordinator, + address newServiceManager, + address newBlsApkRegistry, + address newIndexRegistry, + address newStakeRegistry + ) internal { + // Impersonate the upgrader account + vm.startPrank(eigenDAData.permissions.eigenDAUpgrader); + + // Upgrade each contract using the proxyAdmin + if (newRegistryCoordinator != address(0)) { + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.registryCoordinator, + newRegistryCoordinator + ); + } + + if (newServiceManager != address(0)) { + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.eigenDAServiceManager, + newServiceManager + ); + } + + if (newBlsApkRegistry != address(0)) { + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.blsApkRegistry, + newBlsApkRegistry + ); + } + + if (newIndexRegistry != address(0)) { + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.indexRegistry, + newIndexRegistry + ); + } + + if (newStakeRegistry != address(0)) { + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.stakeRegistry, + newStakeRegistry + ); + } + + vm.stopPrank(); + } + + function _readEigenDADeploymentJson( + string memory path, + uint256 chainId + ) internal returns (EigenDAData memory) { + string memory filePath = string(abi.encodePacked(path, "/EigenDA_Holesky.json")); + return _loadEigenDAJson(filePath); + } + + function _loadEigenDAJson( + string memory filePath + ) internal returns (EigenDAData memory) { + string memory json = vm.readFile(filePath); + require(vm.exists(filePath), "EigenDA deployment file does not exist"); + + EigenDAData memory data; + + // Parse addresses section + data.addresses.blsApkRegistry = json.readAddress(".addresses.blsApkRegistry"); + data.addresses.eigenDAProxyAdmin = json.readAddress(".addresses.eigenDAProxyAdmin"); + data.addresses.eigenDAServiceManager = json.readAddress(".addresses.eigenDAServiceManager"); + data.addresses.indexRegistry = json.readAddress(".addresses.indexRegistry"); + data.addresses.mockDispatcher = json.readAddress(".addresses.mockRollup"); + data.addresses.operatorStateRetriever = json.readAddress(".addresses.operatorStateRetriever"); + data.addresses.registryCoordinator = json.readAddress(".addresses.registryCoordinator"); + data.addresses.serviceManagerRouter = json.readAddress(".addresses.serviceManagerRouter"); + data.addresses.stakeRegistry = json.readAddress(".addresses.stakeRegistry"); + + // Parse chainInfo section + data.chainInfo.chainId = json.readUint(".chainInfo.chainId"); + data.chainInfo.deploymentBlock = json.readUint(".chainInfo.deploymentBlock"); + + // Parse permissions section + data.permissions.eigenDABatchConfirmer = json.readAddress(".permissions.eigenDABatchConfirmer"); + data.permissions.eigenDAChurner = json.readAddress(".permissions.eigenDAChurner"); + data.permissions.eigenDAEjector = json.readAddress(".permissions.eigenDAEjector"); + data.permissions.eigenDAOwner = json.readAddress(".permissions.eigenDAOwner"); + data.permissions.eigenDAUpgrader = json.readAddress(".permissions.eigenDAUpgrader"); + data.permissions.pauserRegistry = json.readAddress(".permissions.pauserRegistry"); + + return data; + } +} diff --git a/test/End2End.t.sol b/test/fork/End2End.t.sol similarity index 96% rename from test/End2End.t.sol rename to test/fork/End2End.t.sol index 5d838ee3..dd9fce35 100644 --- a/test/End2End.t.sol +++ b/test/fork/End2End.t.sol @@ -4,30 +4,30 @@ pragma solidity ^0.8.12; import {Vm} from "forge-std/Vm.sol"; import {stdJson} from "forge-std/StdJson.sol"; import {Test, console2 as console} from "forge-std/Test.sol"; -import {OperatorLib} from "./utils/OperatorLib.sol"; -import {UpgradeableProxyLib} from "./unit/UpgradeableProxyLib.sol"; -import {MiddlewareDeployLib} from "./utils/MiddlewareDeployLib.sol"; -import {BN254} from "../src/libraries/BN254.sol"; +import {OperatorLib} from "../utils/OperatorLib.sol"; +import {UpgradeableProxyLib} from "../unit/UpgradeableProxyLib.sol"; +import {MiddlewareDeployLib} from "../utils/MiddlewareDeployLib.sol"; +import {BN254} from "../../src/libraries/BN254.sol"; import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IAllocationManagerTypes} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; -import {IServiceManager} from "../src/interfaces/IServiceManager.sol"; -import {IStakeRegistry, IStakeRegistryTypes} from "../src/interfaces/IStakeRegistry.sol"; +import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; +import {IStakeRegistry, IStakeRegistryTypes} from "../../src/interfaces/IStakeRegistry.sol"; import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; -import {RegistryCoordinator} from "../src/RegistryCoordinator.sol"; -import {IRegistryCoordinator} from "../src/interfaces/IRegistryCoordinator.sol"; +import {RegistryCoordinator} from "../../src/RegistryCoordinator.sol"; +import {IRegistryCoordinator} from "../../src/interfaces/IRegistryCoordinator.sol"; import {OperatorSet} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; import {AllocationManager} from "eigenlayer-contracts/src/contracts/core/AllocationManager.sol"; import {PermissionController} from "eigenlayer-contracts/src/contracts/permissions/PermissionController.sol"; -import {ServiceManagerMock} from "./mocks/ServiceManagerMock.sol"; +import {ServiceManagerMock} from "../mocks/ServiceManagerMock.sol"; import { ISlashingRegistryCoordinator, ISlashingRegistryCoordinatorTypes -} from "../src/interfaces/ISlashingRegistryCoordinator.sol"; -import {ERC20Mock} from "./mocks/ERC20Mock.sol"; +} from "../../src/interfaces/ISlashingRegistryCoordinator.sol"; +import {ERC20Mock} from "../mocks/ERC20Mock.sol"; import {IStrategyFactory} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyFactory.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/test/utils/EigenDA_Holesky.json b/test/utils/EigenDA_Holesky.json new file mode 100644 index 00000000..16539651 --- /dev/null +++ b/test/utils/EigenDA_Holesky.json @@ -0,0 +1,30 @@ +{ + "addresses": { + "blsApkRegistry": "0x066cF95c1bf0927124DFB8B02B401bc23A79730D", + "blsApkRegistryImplementation": "0x885C0CC8118E428a2C04de58A93eB15Ed4F0e064", + "eigenDAProxyAdmin": "0xB043055dd967A382577c2f5261fA6428f2905c15", + "eigenDAServiceManager": "0xD4A7E1Bd8015057293f0D0A557088c286942e84b", + "eigenDAServiceManagerImplementation": "0x0A987C508b0f56154CA534b7Fa5b84863cbcc49d", + "indexRegistry": "0x2E3D6c0744b10eb0A4e6F679F71554a39Ec47a5D", + "indexRegistryImplementation": "0x889B040116f453D89e9d6d692Ad70Edd7357420d", + "mockRollup": "0x4B1481fFF061A0099408e71702b40Fe0932080Bc", + "operatorStateRetriever": "0xB4baAfee917fb4449f5ec64804217bccE9f46C67", + "registryCoordinator": "0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490", + "registryCoordinatorImplementation": "0xC908fAFAE29B5C9F0b5E0Da1d3025b8d6D42bfa0", + "serviceManagerRouter": "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37", + "stakeRegistry": "0xBDACD5998989Eec814ac7A0f0f6596088AA2a270", + "stakeRegistryImplementation": "0xa8d25410c3e3347d93647f10FB6961069BEc98E5" + }, + "chainInfo": { + "chainId": 17000, + "deploymentBlock": 1168409 + }, + "permissions": { + "eigenDABatchConfirmer": "0xC0996A3Cc9ECF2A96115C117f6Da99FA80F525eB", + "eigenDAChurner": "0x400c0D378F0E6881efb11b8E82480A3140B69258", + "eigenDAEjector": "0x28Ade60640fdBDb2609D8d8734D1b5cBeFc0C348", + "eigenDAOwner": "0x28Ade60640fdBDb2609D8d8734D1b5cBeFc0C348", + "eigenDAUpgrader": "0x28Ade60640fdBDb2609D8d8734D1b5cBeFc0C348", + "pauserRegistry": "0x85Ef7299F8311B25642679edBF02B62FA2212F06" + } + } \ No newline at end of file From 219e4a492eea043a73949721ffbaa5e843a982c3 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 31 Mar 2025 17:26:30 -0400 Subject: [PATCH 02/20] test: more testing for upgrade --- test/fork/EigenDA.t.sol | 268 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 260 insertions(+), 8 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 02d8343a..0ccd307c 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -6,12 +6,61 @@ import {stdJson} from "forge-std/StdJson.sol"; import {Test, console2 as console} from "forge-std/Test.sol"; import {UpgradeableProxyLib} from "../unit/UpgradeableProxyLib.sol"; import {BN254} from "../../src/libraries/BN254.sol"; +import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; +import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; import {IRegistryCoordinator} from "../../src/interfaces/IRegistryCoordinator.sol"; import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; import {IStakeRegistry} from "../../src/interfaces/IStakeRegistry.sol"; import {IBLSApkRegistry} from "../../src/interfaces/IBLSApkRegistry.sol"; import {IIndexRegistry} from "../../src/interfaces/IIndexRegistry.sol"; +import {ISlashingRegistryCoordinator} from "../../src/interfaces/ISlashingRegistryCoordinator.sol"; +import {ISocketRegistry} from "../../src/interfaces/ISocketRegistry.sol"; +import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; +import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; +import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; +import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; +import {IPermissionController} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; + +// Import concrete implementation for deployment +import {RegistryCoordinator, IRegistryCoordinatorTypes} from "../../src/RegistryCoordinator.sol"; +import {ServiceManagerBase} from "../../src/ServiceManagerBase.sol"; +import {BLSApkRegistry} from "../../src/BLSApkRegistry.sol"; +import {IndexRegistry} from "../../src/IndexRegistry.sol"; +import {StakeRegistry} from "../../src/StakeRegistry.sol"; +import {SocketRegistry} from "../../src/SocketRegistry.sol"; + +// Extended interface to get addresses of other contracts +interface IServiceManagerExtended { + function avsDirectory() external view returns (IAVSDirectory); +} + +interface StakeRegistryExtended { + function delegation() external view returns (IDelegationManager); +} + +interface IDelegationManagerExtended { + function allocationManager() external view returns (IAllocationManager); +} + +contract TestServiceManager is ServiceManagerBase { + constructor( + IAVSDirectory __avsDirectory, + IRewardsCoordinator __rewardsCoordinator, + ISlashingRegistryCoordinator __registryCoordinator, + IStakeRegistry __stakeRegistry, + IPermissionController __permissionController, + IAllocationManager __allocationManager + ) ServiceManagerBase( + __avsDirectory, + __rewardsCoordinator, + __registryCoordinator, + __stakeRegistry, + __permissionController, + __allocationManager + ) {} +} contract EigenDATest is Test { using stdJson for string; @@ -59,20 +108,20 @@ contract EigenDATest is Test { } struct ServiceManagerState { - bool paused; + uint256 paused; address owner; } struct BlsApkRegistryState { - uint32 nextOperatorId; + bytes32[] currentApkHashes; } struct IndexRegistryState { - uint32 nextOperatorId; + uint32[] nextOperatorIds; } struct StakeRegistryState { - uint32 numStrategies; + uint32[] numStrategies; } struct ContractStates { @@ -88,12 +137,20 @@ contract EigenDATest is Test { ConfigData public config; ContractStates public preUpgradeStates; + // Core contract addresses from StakeRegistry + address public delegationManagerAddr; + address public avsDirectoryAddr; + address public allocationManagerAddr; + address public permissionControllerAddr; // Will need to be fetched separately + address public rewardsCoordinatorAddr; // Will need to be fetched separately + // New implementation addresses for upgrade address public newRegistryCoordinatorImpl; address public newServiceManagerImpl; address public newBlsApkRegistryImpl; address public newIndexRegistryImpl; address public newStakeRegistryImpl; + address public socketRegistry; // Test setup function that runs before each test function setUp() public virtual { @@ -112,17 +169,25 @@ contract EigenDATest is Test { console.log("Verifying initial EigenDA setup on fork"); _verifyInitialSetup(); + // 2. Capture pre-upgrade state + console.log("Capturing pre-upgrade contract states"); + _capturePreUpgradeState(); + + // 3. Deploy new implementations _deployNewImplementations(); + // 4. Perform upgrades _performUpgrades( newRegistryCoordinatorImpl, newServiceManagerImpl, newBlsApkRegistryImpl, newIndexRegistryImpl, - newStakeRegistryImpl + newStakeRegistryImpl, + socketRegistry ); console.log("Contract upgrades completed. Ready for validation testing."); + } function _verifyInitialSetup() internal view { @@ -159,8 +224,127 @@ contract EigenDATest is Test { ); } + function _capturePreUpgradeState() internal { + // Registry Coordinator + ISlashingRegistryCoordinator rc = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + preUpgradeStates.registryCoordinator.numQuorums = rc.quorumCount(); + + // Service Manager + address payable smAddr = payable(eigenDAData.addresses.eigenDAServiceManager); + OwnableUpgradeable sm_ownable = OwnableUpgradeable(smAddr); + preUpgradeStates.serviceManager.owner = sm_ownable.owner(); + + // Check if service manager is paused + Pausable sm_pausable = Pausable(smAddr); + preUpgradeStates.serviceManager.paused = sm_pausable.paused(); + + // BLS Apk Registry + IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + + // Index Registry + IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); + + // Initialize arrays for each quorum + uint8 quorumCount = rc.quorumCount(); + preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); + preUpgradeStates.indexRegistry.nextOperatorIds = new uint32[](quorumCount); + preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); + + // Stake Registry + IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + + // For each quorum, gather data from all registries + for (uint8 i = 0; i < quorumCount; i++) { + // Get operator count for each quorum from IndexRegistry + uint32 operatorCount = idx.totalOperatorsForQuorum(i); + preUpgradeStates.indexRegistry.nextOperatorIds[i] = operatorCount; + + // Get APK hash for each quorum from BLSApkRegistry + // Store the hash of the APK as bytes32 + preUpgradeStates.blsApkRegistry.currentApkHashes[i] = BN254.hashG1Point(bls.getApk(i)); + + // Get strategy count for each quorum from StakeRegistry + // Check if we can get total stake history for this quorum + // If getTotalStakeHistoryLength doesn't revert, the quorum exists in StakeRegistry + uint256 strategyCount = 0; + + // First check if we can get the total stake history length, which confirms quorum exists + if (stake.getTotalStakeHistoryLength(i) > 0) { + // Now it's safe to get strategy params length + strategyCount = stake.strategyParamsLength(i); + } + + preUpgradeStates.stakeRegistry.numStrategies[i] = uint32(strategyCount); + } + } + function _deployNewImplementations() internal { - /// TODO: Placeholder for upgrading + // Deploy SocketRegistry first + socketRegistry = address(new SocketRegistry(ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator))); + console.log("Deployed new SocketRegistry instance at:", socketRegistry); + + IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = IRegistryCoordinatorTypes.SlashingRegistryParams({ + stakeRegistry: IStakeRegistry(eigenDAData.addresses.stakeRegistry), + blsApkRegistry: IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry), + indexRegistry: IIndexRegistry(eigenDAData.addresses.indexRegistry), + socketRegistry: ISocketRegistry(socketRegistry), + allocationManager: IAllocationManager(allocationManagerAddr), + pauserRegistry: IPauserRegistry(eigenDAData.permissions.pauserRegistry) + }); + + // Populate RegistryCoordinatorParams + IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = IRegistryCoordinatorTypes.RegistryCoordinatorParams({ + serviceManager: IServiceManager(payable(eigenDAData.addresses.eigenDAServiceManager)), + slashingParams: slashingParams + }); + + // Deploy RegistryCoordinator + newRegistryCoordinatorImpl = address(new RegistryCoordinator(params)); + console.log("Deployed new RegistryCoordinator implementation at:", newRegistryCoordinatorImpl); + + // Deploy ServiceManagerBase + // Use extracted addresses for core dependencies + address registryCoordinatorAddr = eigenDAData.addresses.registryCoordinator; + address stakeRegistryAddr = eigenDAData.addresses.stakeRegistry; + + // Use extracted addresses where available + IAVSDirectory avsDirectory = IAVSDirectory(avsDirectoryAddr); + IRewardsCoordinator rewardsCoordinator = IRewardsCoordinator(rewardsCoordinatorAddr); + ISlashingRegistryCoordinator registryCoordinator = ISlashingRegistryCoordinator(registryCoordinatorAddr); + IStakeRegistry stakeRegistry = IStakeRegistry(stakeRegistryAddr); + IPermissionController permissionController = IPermissionController(permissionControllerAddr); + IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); + + // Deploy TestServiceManager (concrete implementation) + newServiceManagerImpl = address(new TestServiceManager( + avsDirectory, + rewardsCoordinator, + registryCoordinator, + stakeRegistry, + permissionController, + allocationManager + )); + console.log("Deployed new ServiceManager implementation at:", newServiceManagerImpl); + + // Deploy BLSApkRegistry + newBlsApkRegistryImpl = address(new BLSApkRegistry(registryCoordinator)); + console.log("Deployed new BLSApkRegistry implementation at:", newBlsApkRegistryImpl); + + // Deploy IndexRegistry + newIndexRegistryImpl = address(new IndexRegistry(registryCoordinator)); + console.log("Deployed new IndexRegistry implementation at:", newIndexRegistryImpl); + + // Deploy StakeRegistry + // Use extracted address for delegationManager + IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); + + newStakeRegistryImpl = address(new StakeRegistry( + registryCoordinator, + delegationManager, + avsDirectory, + allocationManager // Using null address for now + )); + console.log("Deployed new StakeRegistry implementation at:", newStakeRegistryImpl); } function _setupEigenDAFork( @@ -173,7 +357,15 @@ contract EigenDATest is Test { EigenDAData memory data = _readEigenDADeploymentJson(jsonPath, 17000); - vm.rollFork(data.chainInfo.deploymentBlock); + + vm.rollFork(3592349); /// Recent block post ALM upgrade + + delegationManagerAddr = address(StakeRegistryExtended(data.addresses.stakeRegistry).delegation()); + avsDirectoryAddr = address(IServiceManagerExtended(data.addresses.eigenDAServiceManager).avsDirectory()); + allocationManagerAddr = address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); + console.log("DelegationManager address:", delegationManagerAddr); + console.log("AVSDirectory address:", avsDirectoryAddr); + console.log("Allocation Manager address:", allocationManagerAddr); return data; } @@ -183,7 +375,8 @@ contract EigenDATest is Test { address newServiceManager, address newBlsApkRegistry, address newIndexRegistry, - address newStakeRegistry + address newStakeRegistry, + address socketRegistry ) internal { // Impersonate the upgrader account vm.startPrank(eigenDAData.permissions.eigenDAUpgrader); @@ -224,6 +417,12 @@ contract EigenDATest is Test { ); } + // Deploy and use the new SocketRegistry instance + if (socketRegistry != address(0)) { + // Since this is a new deployment, not an upgrade + console.log("Using new SocketRegistry instance at:", socketRegistry); + } + vm.stopPrank(); } @@ -268,4 +467,57 @@ contract EigenDATest is Test { return data; } + + function testValidatePostUpgradeState() public { + testEigenDAUpgradeSetup(); + + // 2. Verify post-upgrade state matches pre-upgrade state + console.log("Validating post-upgrade contract states"); + + // // Get contract instances for post-upgrade validation + // ISlashingRegistryCoordinator rc = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + // IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + // IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); + // IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + + // // Verify quorum count is maintained + // uint8 quorumCount = rc.quorumCount(); + // require( + // quorumCount == preUpgradeStates.registryCoordinator.numQuorums, + // "Quorum count changed after upgrade" + // ); + + // // Verify each quorum's data is maintained across all registries + // for (uint8 i = 0; i < quorumCount; i++) { + // // 1. Verify BLSApkRegistry state + // bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); + // require( + // currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], + // "BLSApkRegistry: APK hash changed after upgrade" + // ); + + // // 2. Verify IndexRegistry state + // uint32 operatorCount = idx.totalOperatorsForQuorum(i); + // require( + // operatorCount == preUpgradeStates.indexRegistry.nextOperatorIds[i], + // "IndexRegistry: Operator count changed after upgrade" + // ); + + // // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry + // if (stake.getTotalStakeHistoryLength(i) > 0) { + // uint256 strategyCount = stake.strategyParamsLength(i); + // require( + // uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], + // "StakeRegistry: Strategy count changed after upgrade" + // ); + // } + // } + + // // Test Socket Registry integration by checking if the registry coordinator can interact with it + // // This is a basic check to ensure the new SocketRegistry contract is properly connected + // bool socketRegistryExists = address(rc) != address(0) && socketRegistry != address(0); + // require(socketRegistryExists, "Socket Registry not properly integrated"); + + console.log("Post-upgrade validation successful"); + } } From a19d1a6a1ee58a8b9f6b97f1437d6d5dc1a4dbe2 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 31 Mar 2025 17:31:06 -0400 Subject: [PATCH 03/20] chore: forge fmt --- test/fork/EigenDA.t.sol | 138 ++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 0ccd307c..06967be5 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -17,11 +17,15 @@ import {IIndexRegistry} from "../../src/interfaces/IIndexRegistry.sol"; import {ISlashingRegistryCoordinator} from "../../src/interfaces/ISlashingRegistryCoordinator.sol"; import {ISocketRegistry} from "../../src/interfaces/ISocketRegistry.sol"; import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; -import {IAllocationManager} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; -import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; +import {IAllocationManager} from + "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IDelegationManager} from + "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; -import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; -import {IPermissionController} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; +import {IRewardsCoordinator} from + "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; +import {IPermissionController} from + "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; // Import concrete implementation for deployment import {RegistryCoordinator, IRegistryCoordinatorTypes} from "../../src/RegistryCoordinator.sol"; @@ -52,14 +56,16 @@ contract TestServiceManager is ServiceManagerBase { IStakeRegistry __stakeRegistry, IPermissionController __permissionController, IAllocationManager __allocationManager - ) ServiceManagerBase( - __avsDirectory, - __rewardsCoordinator, - __registryCoordinator, - __stakeRegistry, - __permissionController, - __allocationManager - ) {} + ) + ServiceManagerBase( + __avsDirectory, + __rewardsCoordinator, + __registryCoordinator, + __stakeRegistry, + __permissionController, + __allocationManager + ) + {} } contract EigenDATest is Test { @@ -117,7 +123,7 @@ contract EigenDATest is Test { } struct IndexRegistryState { - uint32[] nextOperatorIds; + uint32[] operatorCounts; } struct StakeRegistryState { @@ -187,7 +193,6 @@ contract EigenDATest is Test { ); console.log("Contract upgrades completed. Ready for validation testing."); - } function _verifyInitialSetup() internal view { @@ -205,12 +210,10 @@ contract EigenDATest is Test { "BLS APK Registry should be deployed" ); require( - eigenDAData.addresses.indexRegistry != address(0), - "Index Registry should be deployed" + eigenDAData.addresses.indexRegistry != address(0), "Index Registry should be deployed" ); require( - eigenDAData.addresses.stakeRegistry != address(0), - "Stake Registry should be deployed" + eigenDAData.addresses.stakeRegistry != address(0), "Stake Registry should be deployed" ); // Verify permissions @@ -226,7 +229,8 @@ contract EigenDATest is Test { function _capturePreUpgradeState() internal { // Registry Coordinator - ISlashingRegistryCoordinator rc = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + ISlashingRegistryCoordinator rc = + ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); preUpgradeStates.registryCoordinator.numQuorums = rc.quorumCount(); // Service Manager @@ -247,7 +251,7 @@ contract EigenDATest is Test { // Initialize arrays for each quorum uint8 quorumCount = rc.quorumCount(); preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); - preUpgradeStates.indexRegistry.nextOperatorIds = new uint32[](quorumCount); + preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); // Stake Registry @@ -257,7 +261,7 @@ contract EigenDATest is Test { for (uint8 i = 0; i < quorumCount; i++) { // Get operator count for each quorum from IndexRegistry uint32 operatorCount = idx.totalOperatorsForQuorum(i); - preUpgradeStates.indexRegistry.nextOperatorIds[i] = operatorCount; + preUpgradeStates.indexRegistry.operatorCounts[i] = operatorCount; // Get APK hash for each quorum from BLSApkRegistry // Store the hash of the APK as bytes32 @@ -280,10 +284,15 @@ contract EigenDATest is Test { function _deployNewImplementations() internal { // Deploy SocketRegistry first - socketRegistry = address(new SocketRegistry(ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator))); + socketRegistry = address( + new SocketRegistry( + ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator) + ) + ); console.log("Deployed new SocketRegistry instance at:", socketRegistry); - IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = IRegistryCoordinatorTypes.SlashingRegistryParams({ + IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = + IRegistryCoordinatorTypes.SlashingRegistryParams({ stakeRegistry: IStakeRegistry(eigenDAData.addresses.stakeRegistry), blsApkRegistry: IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry), indexRegistry: IIndexRegistry(eigenDAData.addresses.indexRegistry), @@ -293,14 +302,17 @@ contract EigenDATest is Test { }); // Populate RegistryCoordinatorParams - IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = IRegistryCoordinatorTypes.RegistryCoordinatorParams({ + IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = + IRegistryCoordinatorTypes.RegistryCoordinatorParams({ serviceManager: IServiceManager(payable(eigenDAData.addresses.eigenDAServiceManager)), slashingParams: slashingParams }); // Deploy RegistryCoordinator newRegistryCoordinatorImpl = address(new RegistryCoordinator(params)); - console.log("Deployed new RegistryCoordinator implementation at:", newRegistryCoordinatorImpl); + console.log( + "Deployed new RegistryCoordinator implementation at:", newRegistryCoordinatorImpl + ); // Deploy ServiceManagerBase // Use extracted addresses for core dependencies @@ -310,20 +322,23 @@ contract EigenDATest is Test { // Use extracted addresses where available IAVSDirectory avsDirectory = IAVSDirectory(avsDirectoryAddr); IRewardsCoordinator rewardsCoordinator = IRewardsCoordinator(rewardsCoordinatorAddr); - ISlashingRegistryCoordinator registryCoordinator = ISlashingRegistryCoordinator(registryCoordinatorAddr); + ISlashingRegistryCoordinator registryCoordinator = + ISlashingRegistryCoordinator(registryCoordinatorAddr); IStakeRegistry stakeRegistry = IStakeRegistry(stakeRegistryAddr); IPermissionController permissionController = IPermissionController(permissionControllerAddr); IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); // Deploy TestServiceManager (concrete implementation) - newServiceManagerImpl = address(new TestServiceManager( - avsDirectory, - rewardsCoordinator, - registryCoordinator, - stakeRegistry, - permissionController, - allocationManager - )); + newServiceManagerImpl = address( + new TestServiceManager( + avsDirectory, + rewardsCoordinator, + registryCoordinator, + stakeRegistry, + permissionController, + allocationManager + ) + ); console.log("Deployed new ServiceManager implementation at:", newServiceManagerImpl); // Deploy BLSApkRegistry @@ -338,12 +353,14 @@ contract EigenDATest is Test { // Use extracted address for delegationManager IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); - newStakeRegistryImpl = address(new StakeRegistry( - registryCoordinator, - delegationManager, - avsDirectory, - allocationManager // Using null address for now - )); + newStakeRegistryImpl = address( + new StakeRegistry( + registryCoordinator, + delegationManager, + avsDirectory, + allocationManager // Using null address for now + ) + ); console.log("Deployed new StakeRegistry implementation at:", newStakeRegistryImpl); } @@ -357,12 +374,16 @@ contract EigenDATest is Test { EigenDAData memory data = _readEigenDADeploymentJson(jsonPath, 17000); + vm.rollFork(3592349); - vm.rollFork(3592349); /// Recent block post ALM upgrade + /// Recent block post ALM upgrade - delegationManagerAddr = address(StakeRegistryExtended(data.addresses.stakeRegistry).delegation()); - avsDirectoryAddr = address(IServiceManagerExtended(data.addresses.eigenDAServiceManager).avsDirectory()); - allocationManagerAddr = address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); + delegationManagerAddr = + address(StakeRegistryExtended(data.addresses.stakeRegistry).delegation()); + avsDirectoryAddr = + address(IServiceManagerExtended(data.addresses.eigenDAServiceManager).avsDirectory()); + allocationManagerAddr = + address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); console.log("DelegationManager address:", delegationManagerAddr); console.log("AVSDirectory address:", avsDirectoryAddr); console.log("Allocation Manager address:", allocationManagerAddr); @@ -384,37 +405,26 @@ contract EigenDATest is Test { // Upgrade each contract using the proxyAdmin if (newRegistryCoordinator != address(0)) { UpgradeableProxyLib.upgrade( - eigenDAData.addresses.registryCoordinator, - newRegistryCoordinator + eigenDAData.addresses.registryCoordinator, newRegistryCoordinator ); } if (newServiceManager != address(0)) { UpgradeableProxyLib.upgrade( - eigenDAData.addresses.eigenDAServiceManager, - newServiceManager + eigenDAData.addresses.eigenDAServiceManager, newServiceManager ); } if (newBlsApkRegistry != address(0)) { - UpgradeableProxyLib.upgrade( - eigenDAData.addresses.blsApkRegistry, - newBlsApkRegistry - ); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.blsApkRegistry, newBlsApkRegistry); } if (newIndexRegistry != address(0)) { - UpgradeableProxyLib.upgrade( - eigenDAData.addresses.indexRegistry, - newIndexRegistry - ); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.indexRegistry, newIndexRegistry); } if (newStakeRegistry != address(0)) { - UpgradeableProxyLib.upgrade( - eigenDAData.addresses.stakeRegistry, - newStakeRegistry - ); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.stakeRegistry, newStakeRegistry); } // Deploy and use the new SocketRegistry instance @@ -448,7 +458,8 @@ contract EigenDATest is Test { data.addresses.eigenDAServiceManager = json.readAddress(".addresses.eigenDAServiceManager"); data.addresses.indexRegistry = json.readAddress(".addresses.indexRegistry"); data.addresses.mockDispatcher = json.readAddress(".addresses.mockRollup"); - data.addresses.operatorStateRetriever = json.readAddress(".addresses.operatorStateRetriever"); + data.addresses.operatorStateRetriever = + json.readAddress(".addresses.operatorStateRetriever"); data.addresses.registryCoordinator = json.readAddress(".addresses.registryCoordinator"); data.addresses.serviceManagerRouter = json.readAddress(".addresses.serviceManagerRouter"); data.addresses.stakeRegistry = json.readAddress(".addresses.stakeRegistry"); @@ -458,7 +469,8 @@ contract EigenDATest is Test { data.chainInfo.deploymentBlock = json.readUint(".chainInfo.deploymentBlock"); // Parse permissions section - data.permissions.eigenDABatchConfirmer = json.readAddress(".permissions.eigenDABatchConfirmer"); + data.permissions.eigenDABatchConfirmer = + json.readAddress(".permissions.eigenDABatchConfirmer"); data.permissions.eigenDAChurner = json.readAddress(".permissions.eigenDAChurner"); data.permissions.eigenDAEjector = json.readAddress(".permissions.eigenDAEjector"); data.permissions.eigenDAOwner = json.readAddress(".permissions.eigenDAOwner"); @@ -499,7 +511,7 @@ contract EigenDATest is Test { // // 2. Verify IndexRegistry state // uint32 operatorCount = idx.totalOperatorsForQuorum(i); // require( - // operatorCount == preUpgradeStates.indexRegistry.nextOperatorIds[i], + // operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], // "IndexRegistry: Operator count changed after upgrade" // ); From c5435963a673361ce6e07e6f96aaf1ee028854a4 Mon Sep 17 00:00:00 2001 From: steven Date: Tue, 1 Apr 2025 14:52:30 -0400 Subject: [PATCH 04/20] test: validate post upgrade state --- test/fork/EigenDA.t.sol | 83 +++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 06967be5..c56b160c 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -483,52 +483,47 @@ contract EigenDATest is Test { function testValidatePostUpgradeState() public { testEigenDAUpgradeSetup(); - // 2. Verify post-upgrade state matches pre-upgrade state console.log("Validating post-upgrade contract states"); - // // Get contract instances for post-upgrade validation - // ISlashingRegistryCoordinator rc = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - // IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); - // IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); - // IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); - - // // Verify quorum count is maintained - // uint8 quorumCount = rc.quorumCount(); - // require( - // quorumCount == preUpgradeStates.registryCoordinator.numQuorums, - // "Quorum count changed after upgrade" - // ); - - // // Verify each quorum's data is maintained across all registries - // for (uint8 i = 0; i < quorumCount; i++) { - // // 1. Verify BLSApkRegistry state - // bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); - // require( - // currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], - // "BLSApkRegistry: APK hash changed after upgrade" - // ); - - // // 2. Verify IndexRegistry state - // uint32 operatorCount = idx.totalOperatorsForQuorum(i); - // require( - // operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], - // "IndexRegistry: Operator count changed after upgrade" - // ); - - // // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry - // if (stake.getTotalStakeHistoryLength(i) > 0) { - // uint256 strategyCount = stake.strategyParamsLength(i); - // require( - // uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], - // "StakeRegistry: Strategy count changed after upgrade" - // ); - // } - // } - - // // Test Socket Registry integration by checking if the registry coordinator can interact with it - // // This is a basic check to ensure the new SocketRegistry contract is properly connected - // bool socketRegistryExists = address(rc) != address(0) && socketRegistry != address(0); - // require(socketRegistryExists, "Socket Registry not properly integrated"); + ISlashingRegistryCoordinator rc = + ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); + IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + + // Verify quorum count is maintained + uint8 quorumCount = rc.quorumCount(); + console.log("quorum count:", quorumCount); + require( + quorumCount == preUpgradeStates.registryCoordinator.numQuorums, + "Quorum count changed after upgrade" + ); + + // Verify each quorum's data is maintained across all registries + for (uint8 i = 0; i < quorumCount; i++) { + // 1. Verify BLSApkRegistry state + bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); + require( + currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], + "BLSApkRegistry: APK hash changed after upgrade" + ); + + // 2. Verify IndexRegistry state + uint32 operatorCount = idx.totalOperatorsForQuorum(i); + require( + operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], + "IndexRegistry: Operator count changed after upgrade" + ); + + // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry + if (stake.getTotalStakeHistoryLength(i) > 0) { + uint256 strategyCount = stake.strategyParamsLength(i); + require( + uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], + "StakeRegistry: Strategy count changed after upgrade" + ); + } + } console.log("Post-upgrade validation successful"); } From 0aab4cb68b46bfc999f93e3b3255abddd219deab Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 2 Apr 2025 14:51:34 -0400 Subject: [PATCH 05/20] test: create slashable stake quorum --- test/fork/EigenDA.t.sol | 147 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 141 insertions(+), 6 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index c56b160c..44bab463 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -22,17 +22,25 @@ import {IAllocationManager} from import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; import {IPermissionController} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; +import { + IAllocationManager, + OperatorSet, + IAllocationManagerTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; // Import concrete implementation for deployment import {RegistryCoordinator, IRegistryCoordinatorTypes} from "../../src/RegistryCoordinator.sol"; +import {ISlashingRegistryCoordinatorTypes} from + "../../src/interfaces/ISlashingRegistryCoordinator.sol"; import {ServiceManagerBase} from "../../src/ServiceManagerBase.sol"; import {BLSApkRegistry} from "../../src/BLSApkRegistry.sol"; import {IndexRegistry} from "../../src/IndexRegistry.sol"; -import {StakeRegistry} from "../../src/StakeRegistry.sol"; +import {StakeRegistry, IStakeRegistryTypes} from "../../src/StakeRegistry.sol"; import {SocketRegistry} from "../../src/SocketRegistry.sol"; // Extended interface to get addresses of other contracts @@ -40,6 +48,10 @@ interface IServiceManagerExtended { function avsDirectory() external view returns (IAVSDirectory); } +interface IAVSDirectoryExtended { + function permissionController() external view returns (IPermissionController); +} + interface StakeRegistryExtended { function delegation() external view returns (IDelegationManager); } @@ -48,7 +60,20 @@ interface IDelegationManagerExtended { function allocationManager() external view returns (IAllocationManager); } -contract TestServiceManager is ServiceManagerBase { +contract EigenDA_SM_Gap { + uint256[50] private __EigenDASM_GAP; +} + +contract BLSSignatureChecker_Pausable_GAP { + uint256[100] private __GAP; +} + +// EigenDAServiceManagerStorage, ServiceManagerBase, BLSSignatureChecker, Pausable +contract TestServiceManager is + EigenDA_SM_Gap, + ServiceManagerBase, + BLSSignatureChecker_Pausable_GAP +{ constructor( IAVSDirectory __avsDirectory, IRewardsCoordinator __rewardsCoordinator, @@ -325,9 +350,27 @@ contract EigenDATest is Test { ISlashingRegistryCoordinator registryCoordinator = ISlashingRegistryCoordinator(registryCoordinatorAddr); IStakeRegistry stakeRegistry = IStakeRegistry(stakeRegistryAddr); + // Fetch PermissionController from AVS Directory + permissionControllerAddr = + address(IAVSDirectoryExtended(allocationManagerAddr).permissionController()); + require(permissionControllerAddr != address(0), "PermissionController address not found"); + console.log("PermissionController address:", permissionControllerAddr); + IPermissionController permissionController = IPermissionController(permissionControllerAddr); IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); + // Assert all addresses are not zero before deployment + assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); + // assertTrue(address(rewardsCoordinator) != address(0), "RewardsCoordinator address is zero"); + assertTrue( + address(registryCoordinator) != address(0), "RegistryCoordinator address is zero" + ); + assertTrue(address(stakeRegistry) != address(0), "StakeRegistry address is zero"); + assertTrue( + address(permissionController) != address(0), "PermissionController address is zero" + ); + assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); + // Deploy TestServiceManager (concrete implementation) newServiceManagerImpl = address( new TestServiceManager( @@ -353,12 +396,16 @@ contract EigenDATest is Test { // Use extracted address for delegationManager IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); + assertTrue( + address(registryCoordinator) != address(0), "RegistryCoordinator address is zero" + ); + assertTrue(address(delegationManager) != address(0), "DelegationManager address is zero"); + assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); + assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); + newStakeRegistryImpl = address( new StakeRegistry( - registryCoordinator, - delegationManager, - avsDirectory, - allocationManager // Using null address for now + registryCoordinator, delegationManager, avsDirectory, allocationManager ) ); console.log("Deployed new StakeRegistry implementation at:", newStakeRegistryImpl); @@ -477,6 +524,25 @@ contract EigenDATest is Test { data.permissions.eigenDAUpgrader = json.readAddress(".permissions.eigenDAUpgrader"); data.permissions.pauserRegistry = json.readAddress(".permissions.pauserRegistry"); + // Label all addresses for better debugging and tracing + vm.label(data.addresses.blsApkRegistry, "BLSApkRegistry"); + vm.label(data.addresses.eigenDAProxyAdmin, "EigenDAProxyAdmin"); + vm.label(data.addresses.eigenDAServiceManager, "EigenDAServiceManager"); + vm.label(data.addresses.indexRegistry, "IndexRegistry"); + vm.label(data.addresses.mockDispatcher, "MockDispatcher"); + vm.label(data.addresses.operatorStateRetriever, "OperatorStateRetriever"); + vm.label(data.addresses.registryCoordinator, "RegistryCoordinator"); + vm.label(data.addresses.serviceManagerRouter, "ServiceManagerRouter"); + vm.label(data.addresses.stakeRegistry, "StakeRegistry"); + + // Label permission addresses + vm.label(data.permissions.eigenDABatchConfirmer, "EigenDABatchConfirmer"); + vm.label(data.permissions.eigenDAChurner, "EigenDAChurner"); + vm.label(data.permissions.eigenDAEjector, "EigenDAEjector"); + vm.label(data.permissions.eigenDAOwner, "EigenDAOwner"); + vm.label(data.permissions.eigenDAUpgrader, "EigenDAUpgrader"); + vm.label(data.permissions.pauserRegistry, "PauserRegistry"); + return data; } @@ -527,4 +593,73 @@ contract EigenDATest is Test { console.log("Post-upgrade validation successful"); } + + function testPostUpgrade_CreateOperatorSet() public { + // Run the upgrade setup first + testEigenDAUpgradeSetup(); + + console.log("Setting up operator sets post-upgrade..."); + + // Get contract instances + IRegistryCoordinator rc = IRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); + + address avs = eigenDAData.addresses.eigenDAServiceManager; // Service Manager is the account + assert(preUpgradeStates.serviceManager.owner == OwnableUpgradeable(avs).owner()); + + console.log("Setting appointee for createOperatorSets..."); + + // Define appointee parameters + vm.startPrank(preUpgradeStates.serviceManager.owner); + ServiceManagerBase(avs).setAppointee( + address(rc), allocationManagerAddr, IAllocationManager.createOperatorSets.selector + ); + + ServiceManagerBase(avs).setAppointee( + preUpgradeStates.serviceManager.owner, allocationManagerAddr, IAllocationManager.updateAVSMetadataURI.selector + ); + + // Update AVS metadata URI so we can create operator sets + string memory metadataURI = "https://eigenda.xyz/metadata"; + console.log("Updating AVS metadata URI..."); + allocationManager.updateAVSMetadataURI(avs, metadataURI); + + vm.stopPrank(); + + + address registryCoordinatorOwner = + OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); + vm.startPrank(registryCoordinatorOwner); + + rc.setAVS(avs); + + console.log("Creating a new slashable stake quorum (quorum 1)..."); + // Create a new quorum with the SlashingRegistryCoordinator + IStakeRegistryTypes.StrategyParams[] memory strategyParams = + new IStakeRegistryTypes.StrategyParams[](1); + strategyParams[0] = IStakeRegistryTypes.StrategyParams({ + strategy: IStrategy(address(0)), // Replace with actual strategy address + multiplier: 1 + }); + + ISlashingRegistryCoordinatorTypes.OperatorSetParam[] memory operatorSetParams = + new ISlashingRegistryCoordinatorTypes.OperatorSetParam[](1); + operatorSetParams[0] = ISlashingRegistryCoordinatorTypes.OperatorSetParam({ + maxOperatorCount: 100, + kickBIPsOfOperatorStake: 10500, + kickBIPsOfTotalStake: 100 + }); + + + rc.createSlashableStakeQuorum( + operatorSetParams[0], + 1 ether, // minimumStake + strategyParams, + 10 // lookAheadPeriod + ); + + vm.stopPrank(); + + console.log("Post-upgrade creation of operator set quorums"); + } } From 7bf57a7ce6fd7ab708d2427ee2eb3688f628229c Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 2 Apr 2025 15:30:03 -0400 Subject: [PATCH 06/20] chore: forge fmt --- test/fork/EigenDA.t.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 44bab463..7f806337 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -616,7 +616,9 @@ contract EigenDATest is Test { ); ServiceManagerBase(avs).setAppointee( - preUpgradeStates.serviceManager.owner, allocationManagerAddr, IAllocationManager.updateAVSMetadataURI.selector + preUpgradeStates.serviceManager.owner, + allocationManagerAddr, + IAllocationManager.updateAVSMetadataURI.selector ); // Update AVS metadata URI so we can create operator sets @@ -626,7 +628,6 @@ contract EigenDATest is Test { vm.stopPrank(); - address registryCoordinatorOwner = OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); vm.startPrank(registryCoordinatorOwner); @@ -650,7 +651,6 @@ contract EigenDATest is Test { kickBIPsOfTotalStake: 100 }); - rc.createSlashableStakeQuorum( operatorSetParams[0], 1 ether, // minimumStake From 43f61c8bee3688558f969f8bbd357202f8cbbd32 Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 2 Apr 2025 19:36:10 -0400 Subject: [PATCH 07/20] chore: refactor setup and cleanup duplicate variables --- test/fork/EigenDA.t.sol | 463 +++++++++++++++++----------------------- 1 file changed, 201 insertions(+), 262 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 7f806337..2d08dec3 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -48,10 +48,6 @@ interface IServiceManagerExtended { function avsDirectory() external view returns (IAVSDirectory); } -interface IAVSDirectoryExtended { - function permissionController() external view returns (IPermissionController); -} - interface StakeRegistryExtended { function delegation() external view returns (IDelegationManager); } @@ -60,6 +56,10 @@ interface IDelegationManagerExtended { function allocationManager() external view returns (IAllocationManager); } +interface IAllocationManagerExtended { + function permissionController() external view returns (IPermissionController); +} + contract EigenDA_SM_Gap { uint256[50] private __EigenDASM_GAP; } @@ -128,11 +128,6 @@ contract EigenDATest is Test { EigenDAPermissionsData permissions; } - struct ConfigData { - address admin; - address proxyAdmin; - } - struct RegistryCoordinatorState { uint32 operatorSetUpdateNonce; uint8 numQuorums; @@ -165,15 +160,14 @@ contract EigenDATest is Test { // Variables to hold our data EigenDAData public eigenDAData; - ConfigData public config; ContractStates public preUpgradeStates; // Core contract addresses from StakeRegistry address public delegationManagerAddr; address public avsDirectoryAddr; address public allocationManagerAddr; - address public permissionControllerAddr; // Will need to be fetched separately - address public rewardsCoordinatorAddr; // Will need to be fetched separately + address public permissionControllerAddr; + address public rewardsCoordinatorAddr; // New implementation addresses for upgrade address public newRegistryCoordinatorImpl; @@ -188,133 +182,201 @@ contract EigenDATest is Test { // Setup the Holesky fork and load EigenDA deployment data eigenDAData = _setupEigenDAFork("test/utils"); - // Set the admin to the test contract address (this) - config.admin = address(this); + delegationManagerAddr = address(StakeRegistryExtended(eigenDAData.addresses.stakeRegistry).delegation()); + avsDirectoryAddr = address(IServiceManagerExtended(eigenDAData.addresses.eigenDAServiceManager).avsDirectory()); + allocationManagerAddr = address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); + permissionControllerAddr = address(IAllocationManagerExtended(allocationManagerAddr).permissionController()); + rewardsCoordinatorAddr = address(0); /// TODO: - // Deploy a proxy admin for potential upgrades - config.proxyAdmin = UpgradeableProxyLib.deployProxyAdmin(); - } - - function testEigenDAUpgradeSetup() public { - // 1. Verify initial setup - console.log("Verifying initial EigenDA setup on fork"); _verifyInitialSetup(); - // 2. Capture pre-upgrade state - console.log("Capturing pre-upgrade contract states"); - _capturePreUpgradeState(); + _captureAndStorePreUpgradeState(); - // 3. Deploy new implementations _deployNewImplementations(); + } - // 4. Perform upgrades - _performUpgrades( - newRegistryCoordinatorImpl, - newServiceManagerImpl, - newBlsApkRegistryImpl, - newIndexRegistryImpl, - newStakeRegistryImpl, - socketRegistry - ); - - console.log("Contract upgrades completed. Ready for validation testing."); + function test_Upgrade() public { + _upgradeContracts(); } - function _verifyInitialSetup() internal view { - // Verify that contracts are deployed at the expected addresses - require( - eigenDAData.addresses.registryCoordinator != address(0), - "Registry Coordinator should be deployed" - ); - require( - eigenDAData.addresses.eigenDAServiceManager != address(0), - "Service Manager should be deployed" - ); + function test_ValidatePostUpgradeState() public { + _upgradeContracts(); + console.log("Validating post-upgrade contract states"); + + ISlashingRegistryCoordinator rc = + ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); + IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + + // Verify quorum count is maintained + uint8 quorumCount = rc.quorumCount(); + console.log("quorum count:", quorumCount); require( - eigenDAData.addresses.blsApkRegistry != address(0), - "BLS APK Registry should be deployed" + quorumCount == preUpgradeStates.registryCoordinator.numQuorums, + "Quorum count changed after upgrade" ); + + // Verify each quorum's data is maintained across all registries + for (uint8 i = 0; i < quorumCount; i++) { + // 1. Verify BLSApkRegistry state + bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); + require( + currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], + "BLSApkRegistry: APK hash changed after upgrade" + ); + + // 2. Verify IndexRegistry state + uint32 operatorCount = idx.totalOperatorsForQuorum(i); + require( + operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], + "IndexRegistry: Operator count changed after upgrade" + ); + + // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry + if (stake.getTotalStakeHistoryLength(i) > 0) { + uint256 strategyCount = stake.strategyParamsLength(i); + require( + uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], + "StakeRegistry: Strategy count changed after upgrade" + ); + } + } + + console.log("Post-upgrade validation successful"); + } + + function test_PostUpgrade_CreateOperatorSet() public { + _upgradeContracts(); + + IRegistryCoordinator registryCoordinator = + IRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); + address serviceManagerAddress = eigenDAData.addresses.eigenDAServiceManager; + + // Verify the owner remained the same post-upgrade (sanity check) require( - eigenDAData.addresses.indexRegistry != address(0), "Index Registry should be deployed" + preUpgradeStates.serviceManager.owner + == OwnableUpgradeable(serviceManagerAddress).owner(), + "Service Manager owner mismatch post-upgrade" ); - require( - eigenDAData.addresses.stakeRegistry != address(0), "Stake Registry should be deployed" + + console.log("Configuring permissions for operator set creation..."); + + address serviceManagerOwner = preUpgradeStates.serviceManager.owner; + vm.startPrank(serviceManagerOwner); + + // Grant RegistryCoordinator permission to call createOperatorSets on AllocationManager + ServiceManagerBase(serviceManagerAddress).setAppointee( + address(registryCoordinator), + allocationManagerAddr, + IAllocationManager.createOperatorSets.selector ); + console.log("Appointee set for createOperatorSets"); - // Verify permissions - require( - eigenDAData.permissions.eigenDAUpgrader != address(0), - "EigenDA Upgrader should be defined" + ServiceManagerBase(serviceManagerAddress).setAppointee( + serviceManagerOwner, // Grant permission to the owner itself + allocationManagerAddr, + IAllocationManager.updateAVSMetadataURI.selector ); - require( - eigenDAData.permissions.pauserRegistry != address(0), - "Pauser Registry should be defined" + console.log("Appointee set for updateAVSMetadataURI"); + + // Update AVS metadata URI - required before creating operator sets + string memory metadataURI = "https://eigenda.xyz/metadata"; + console.log("Updating AVS metadata URI to:", metadataURI); + allocationManager.updateAVSMetadataURI(serviceManagerAddress, metadataURI); + + vm.stopPrank(); // Stop impersonating serviceManagerOwner + + // Set the AVS address in the Registry Coordinator (requires RC owner) - required before creating operator sets + address registryCoordinatorOwner = + OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); + console.log("Setting AVS address in Registry Coordinator..."); + vm.startPrank(registryCoordinatorOwner); + registryCoordinator.setAVS(serviceManagerAddress); + vm.stopPrank(); // Stop impersonating registryCoordinatorOwner + + // === Action Phase === + console.log("Creating a new slashable stake quorum (quorum 1)..."); + vm.startPrank(serviceManagerOwner); // Use service manager owner who now has permission via setAppointee + + // Define parameters for the new quorum + ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = + ISlashingRegistryCoordinatorTypes.OperatorSetParam({ + maxOperatorCount: 100, + kickBIPsOfOperatorStake: 10500, // 105% + kickBIPsOfTotalStake: 100 // 1% + }); + + IStakeRegistryTypes.StrategyParams[] memory strategyParams = + new IStakeRegistryTypes.StrategyParams[](1); + strategyParams[0] = IStakeRegistryTypes.StrategyParams({ + strategy: IStrategy(address(0)), // TODO: Placeholder + multiplier: 1 * 1e18 + }); + + uint96 minimumStake = uint96(1 ether); + uint32 lookAheadPeriod = 10; // Example value + + registryCoordinator.createSlashableStakeQuorum( + operatorSetParam, minimumStake, strategyParams, lookAheadPeriod ); + + vm.stopPrank(); + + console.log("Successfully created new operator set quorum."); } - function _capturePreUpgradeState() internal { - // Registry Coordinator - ISlashingRegistryCoordinator rc = + function _captureAndStorePreUpgradeState() internal { + ISlashingRegistryCoordinator registryCoordinator = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - preUpgradeStates.registryCoordinator.numQuorums = rc.quorumCount(); + preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); - // Service Manager - address payable smAddr = payable(eigenDAData.addresses.eigenDAServiceManager); - OwnableUpgradeable sm_ownable = OwnableUpgradeable(smAddr); - preUpgradeStates.serviceManager.owner = sm_ownable.owner(); + address payable serviceManagerAddress = payable(eigenDAData.addresses.eigenDAServiceManager); + OwnableUpgradeable serviceManagerOwnable = OwnableUpgradeable(serviceManagerAddress); + preUpgradeStates.serviceManager.owner = serviceManagerOwnable.owner(); - // Check if service manager is paused - Pausable sm_pausable = Pausable(smAddr); - preUpgradeStates.serviceManager.paused = sm_pausable.paused(); + Pausable serviceManagerPausable = Pausable(serviceManagerAddress); + preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); - // BLS Apk Registry - IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + IBLSApkRegistry blsApkRegistry = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); - // Index Registry - IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); + IIndexRegistry indexRegistry = IIndexRegistry(eigenDAData.addresses.indexRegistry); - // Initialize arrays for each quorum - uint8 quorumCount = rc.quorumCount(); + uint8 quorumCount = registryCoordinator.quorumCount(); preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); - // Stake Registry - IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + IStakeRegistry stakeRegistry = IStakeRegistry(eigenDAData.addresses.stakeRegistry); // For each quorum, gather data from all registries - for (uint8 i = 0; i < quorumCount; i++) { + for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { // Get operator count for each quorum from IndexRegistry - uint32 operatorCount = idx.totalOperatorsForQuorum(i); - preUpgradeStates.indexRegistry.operatorCounts[i] = operatorCount; + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(quorumIndex); + preUpgradeStates.indexRegistry.operatorCounts[quorumIndex] = operatorCount; // Get APK hash for each quorum from BLSApkRegistry // Store the hash of the APK as bytes32 - preUpgradeStates.blsApkRegistry.currentApkHashes[i] = BN254.hashG1Point(bls.getApk(i)); + preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = + BN254.hashG1Point(blsApkRegistry.getApk(quorumIndex)); // Get strategy count for each quorum from StakeRegistry - // Check if we can get total stake history for this quorum - // If getTotalStakeHistoryLength doesn't revert, the quorum exists in StakeRegistry uint256 strategyCount = 0; - - // First check if we can get the total stake history length, which confirms quorum exists - if (stake.getTotalStakeHistoryLength(i) > 0) { - // Now it's safe to get strategy params length - strategyCount = stake.strategyParamsLength(i); + // Check if quorum exists in StakeRegistry before querying + if (stakeRegistry.getTotalStakeHistoryLength(quorumIndex) > 0) { + strategyCount = stakeRegistry.strategyParamsLength(quorumIndex); } - - preUpgradeStates.stakeRegistry.numStrategies[i] = uint32(strategyCount); + preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); } } function _deployNewImplementations() internal { - // Deploy SocketRegistry first socketRegistry = address( new SocketRegistry( ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator) ) ); - console.log("Deployed new SocketRegistry instance at:", socketRegistry); IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = IRegistryCoordinatorTypes.SlashingRegistryParams({ @@ -326,40 +388,28 @@ contract EigenDATest is Test { pauserRegistry: IPauserRegistry(eigenDAData.permissions.pauserRegistry) }); - // Populate RegistryCoordinatorParams IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = IRegistryCoordinatorTypes.RegistryCoordinatorParams({ serviceManager: IServiceManager(payable(eigenDAData.addresses.eigenDAServiceManager)), slashingParams: slashingParams }); - // Deploy RegistryCoordinator newRegistryCoordinatorImpl = address(new RegistryCoordinator(params)); - console.log( - "Deployed new RegistryCoordinator implementation at:", newRegistryCoordinatorImpl - ); - // Deploy ServiceManagerBase - // Use extracted addresses for core dependencies address registryCoordinatorAddr = eigenDAData.addresses.registryCoordinator; address stakeRegistryAddr = eigenDAData.addresses.stakeRegistry; - // Use extracted addresses where available IAVSDirectory avsDirectory = IAVSDirectory(avsDirectoryAddr); IRewardsCoordinator rewardsCoordinator = IRewardsCoordinator(rewardsCoordinatorAddr); ISlashingRegistryCoordinator registryCoordinator = ISlashingRegistryCoordinator(registryCoordinatorAddr); IStakeRegistry stakeRegistry = IStakeRegistry(stakeRegistryAddr); - // Fetch PermissionController from AVS Directory - permissionControllerAddr = - address(IAVSDirectoryExtended(allocationManagerAddr).permissionController()); - require(permissionControllerAddr != address(0), "PermissionController address not found"); - console.log("PermissionController address:", permissionControllerAddr); IPermissionController permissionController = IPermissionController(permissionControllerAddr); IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); // Assert all addresses are not zero before deployment + assertTrue(permissionControllerAddr != address(0), "PermissionController address not found"); assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); // assertTrue(address(rewardsCoordinator) != address(0), "RewardsCoordinator address is zero"); assertTrue( @@ -371,7 +421,6 @@ contract EigenDATest is Test { ); assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); - // Deploy TestServiceManager (concrete implementation) newServiceManagerImpl = address( new TestServiceManager( avsDirectory, @@ -382,102 +431,77 @@ contract EigenDATest is Test { allocationManager ) ); - console.log("Deployed new ServiceManager implementation at:", newServiceManagerImpl); - - // Deploy BLSApkRegistry newBlsApkRegistryImpl = address(new BLSApkRegistry(registryCoordinator)); - console.log("Deployed new BLSApkRegistry implementation at:", newBlsApkRegistryImpl); - - // Deploy IndexRegistry newIndexRegistryImpl = address(new IndexRegistry(registryCoordinator)); - console.log("Deployed new IndexRegistry implementation at:", newIndexRegistryImpl); - - // Deploy StakeRegistry - // Use extracted address for delegationManager - IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); assertTrue( address(registryCoordinator) != address(0), "RegistryCoordinator address is zero" ); - assertTrue(address(delegationManager) != address(0), "DelegationManager address is zero"); + assertTrue(delegationManagerAddr != address(0), "DelegationManager address is zero"); assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); + IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); newStakeRegistryImpl = address( new StakeRegistry( registryCoordinator, delegationManager, avsDirectory, allocationManager ) ); - console.log("Deployed new StakeRegistry implementation at:", newStakeRegistryImpl); } function _setupEigenDAFork( string memory jsonPath ) internal returns (EigenDAData memory) { - // Get the Holesky RPC URL from environment variables string memory rpcUrl = vm.envString("HOLESKY_RPC_URL"); vm.createSelectFork(rpcUrl); EigenDAData memory data = _readEigenDADeploymentJson(jsonPath, 17000); - vm.rollFork(3592349); - /// Recent block post ALM upgrade + vm.rollFork(3592349); - delegationManagerAddr = - address(StakeRegistryExtended(data.addresses.stakeRegistry).delegation()); - avsDirectoryAddr = - address(IServiceManagerExtended(data.addresses.eigenDAServiceManager).avsDirectory()); - allocationManagerAddr = - address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); - console.log("DelegationManager address:", delegationManagerAddr); - console.log("AVSDirectory address:", avsDirectoryAddr); - console.log("Allocation Manager address:", allocationManagerAddr); return data; } - function _performUpgrades( - address newRegistryCoordinator, - address newServiceManager, - address newBlsApkRegistry, - address newIndexRegistry, - address newStakeRegistry, - address socketRegistry - ) internal { + function _upgradeContracts() internal { // Impersonate the upgrader account vm.startPrank(eigenDAData.permissions.eigenDAUpgrader); - // Upgrade each contract using the proxyAdmin - if (newRegistryCoordinator != address(0)) { + // Upgrade each contract using the proxyAdmin and new implementations + if (newRegistryCoordinatorImpl != address(0)) { UpgradeableProxyLib.upgrade( - eigenDAData.addresses.registryCoordinator, newRegistryCoordinator + eigenDAData.addresses.registryCoordinator, newRegistryCoordinatorImpl ); + console.log("Upgraded RegistryCoordinator to:", newRegistryCoordinatorImpl); } - if (newServiceManager != address(0)) { + if (newServiceManagerImpl != address(0)) { UpgradeableProxyLib.upgrade( - eigenDAData.addresses.eigenDAServiceManager, newServiceManager + eigenDAData.addresses.eigenDAServiceManager, newServiceManagerImpl ); + console.log("Upgraded EigenDAServiceManager to:", newServiceManagerImpl); } - if (newBlsApkRegistry != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.blsApkRegistry, newBlsApkRegistry); + if (newBlsApkRegistryImpl != address(0)) { + UpgradeableProxyLib.upgrade(eigenDAData.addresses.blsApkRegistry, newBlsApkRegistryImpl); + console.log("Upgraded BLSApkRegistry to:", newBlsApkRegistryImpl); } - if (newIndexRegistry != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.indexRegistry, newIndexRegistry); + if (newIndexRegistryImpl != address(0)) { + UpgradeableProxyLib.upgrade(eigenDAData.addresses.indexRegistry, newIndexRegistryImpl); + console.log("Upgraded IndexRegistry to:", newIndexRegistryImpl); } - if (newStakeRegistry != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.stakeRegistry, newStakeRegistry); + if (newStakeRegistryImpl != address(0)) { + UpgradeableProxyLib.upgrade(eigenDAData.addresses.stakeRegistry, newStakeRegistryImpl); + console.log("Upgraded StakeRegistry to:", newStakeRegistryImpl); } - // Deploy and use the new SocketRegistry instance + // SocketRegistry is a new deployment, not an upgrade, log its usage if (socketRegistry != address(0)) { - // Since this is a new deployment, not an upgrade - console.log("Using new SocketRegistry instance at:", socketRegistry); + console.log("Using newly deployed SocketRegistry instance at:", socketRegistry); } vm.stopPrank(); @@ -546,120 +570,35 @@ contract EigenDATest is Test { return data; } - function testValidatePostUpgradeState() public { - testEigenDAUpgradeSetup(); - - console.log("Validating post-upgrade contract states"); - - ISlashingRegistryCoordinator rc = - ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); - IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); - IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); - - // Verify quorum count is maintained - uint8 quorumCount = rc.quorumCount(); - console.log("quorum count:", quorumCount); + function _verifyInitialSetup() internal view { + // Verify that contracts are deployed at the expected addresses require( - quorumCount == preUpgradeStates.registryCoordinator.numQuorums, - "Quorum count changed after upgrade" + eigenDAData.addresses.registryCoordinator != address(0), + "Registry Coordinator should be deployed" ); - - // Verify each quorum's data is maintained across all registries - for (uint8 i = 0; i < quorumCount; i++) { - // 1. Verify BLSApkRegistry state - bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); - require( - currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], - "BLSApkRegistry: APK hash changed after upgrade" - ); - - // 2. Verify IndexRegistry state - uint32 operatorCount = idx.totalOperatorsForQuorum(i); - require( - operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], - "IndexRegistry: Operator count changed after upgrade" - ); - - // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry - if (stake.getTotalStakeHistoryLength(i) > 0) { - uint256 strategyCount = stake.strategyParamsLength(i); - require( - uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], - "StakeRegistry: Strategy count changed after upgrade" - ); - } - } - - console.log("Post-upgrade validation successful"); - } - - function testPostUpgrade_CreateOperatorSet() public { - // Run the upgrade setup first - testEigenDAUpgradeSetup(); - - console.log("Setting up operator sets post-upgrade..."); - - // Get contract instances - IRegistryCoordinator rc = IRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); - - address avs = eigenDAData.addresses.eigenDAServiceManager; // Service Manager is the account - assert(preUpgradeStates.serviceManager.owner == OwnableUpgradeable(avs).owner()); - - console.log("Setting appointee for createOperatorSets..."); - - // Define appointee parameters - vm.startPrank(preUpgradeStates.serviceManager.owner); - ServiceManagerBase(avs).setAppointee( - address(rc), allocationManagerAddr, IAllocationManager.createOperatorSets.selector + require( + eigenDAData.addresses.eigenDAServiceManager != address(0), + "Service Manager should be deployed" ); - - ServiceManagerBase(avs).setAppointee( - preUpgradeStates.serviceManager.owner, - allocationManagerAddr, - IAllocationManager.updateAVSMetadataURI.selector + require( + eigenDAData.addresses.blsApkRegistry != address(0), + "BLS APK Registry should be deployed" ); - - // Update AVS metadata URI so we can create operator sets - string memory metadataURI = "https://eigenda.xyz/metadata"; - console.log("Updating AVS metadata URI..."); - allocationManager.updateAVSMetadataURI(avs, metadataURI); - - vm.stopPrank(); - - address registryCoordinatorOwner = - OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); - vm.startPrank(registryCoordinatorOwner); - - rc.setAVS(avs); - - console.log("Creating a new slashable stake quorum (quorum 1)..."); - // Create a new quorum with the SlashingRegistryCoordinator - IStakeRegistryTypes.StrategyParams[] memory strategyParams = - new IStakeRegistryTypes.StrategyParams[](1); - strategyParams[0] = IStakeRegistryTypes.StrategyParams({ - strategy: IStrategy(address(0)), // Replace with actual strategy address - multiplier: 1 - }); - - ISlashingRegistryCoordinatorTypes.OperatorSetParam[] memory operatorSetParams = - new ISlashingRegistryCoordinatorTypes.OperatorSetParam[](1); - operatorSetParams[0] = ISlashingRegistryCoordinatorTypes.OperatorSetParam({ - maxOperatorCount: 100, - kickBIPsOfOperatorStake: 10500, - kickBIPsOfTotalStake: 100 - }); - - rc.createSlashableStakeQuorum( - operatorSetParams[0], - 1 ether, // minimumStake - strategyParams, - 10 // lookAheadPeriod + require( + eigenDAData.addresses.indexRegistry != address(0), "Index Registry should be deployed" + ); + require( + eigenDAData.addresses.stakeRegistry != address(0), "Stake Registry should be deployed" ); - vm.stopPrank(); - - console.log("Post-upgrade creation of operator set quorums"); + // Verify permissions + require( + eigenDAData.permissions.eigenDAUpgrader != address(0), + "EigenDA Upgrader should be defined" + ); + require( + eigenDAData.permissions.pauserRegistry != address(0), + "Pauser Registry should be defined" + ); } } From ac6167795f0f2a9d73626344d9538d5680e6878c Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 2 Apr 2025 19:39:27 -0400 Subject: [PATCH 08/20] chore: refactor setup and cleanup duplicate variables --- test/fork/EigenDA.t.sol | 77 +++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 50 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 2d08dec3..b224f5f8 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -182,11 +182,17 @@ contract EigenDATest is Test { // Setup the Holesky fork and load EigenDA deployment data eigenDAData = _setupEigenDAFork("test/utils"); - delegationManagerAddr = address(StakeRegistryExtended(eigenDAData.addresses.stakeRegistry).delegation()); - avsDirectoryAddr = address(IServiceManagerExtended(eigenDAData.addresses.eigenDAServiceManager).avsDirectory()); - allocationManagerAddr = address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); - permissionControllerAddr = address(IAllocationManagerExtended(allocationManagerAddr).permissionController()); - rewardsCoordinatorAddr = address(0); /// TODO: + delegationManagerAddr = + address(StakeRegistryExtended(eigenDAData.addresses.stakeRegistry).delegation()); + avsDirectoryAddr = address( + IServiceManagerExtended(eigenDAData.addresses.eigenDAServiceManager).avsDirectory() + ); + allocationManagerAddr = + address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); + permissionControllerAddr = + address(IAllocationManagerExtended(allocationManagerAddr).permissionController()); + rewardsCoordinatorAddr = address(0); + /// TODO: _verifyInitialSetup(); @@ -266,12 +272,12 @@ contract EigenDATest is Test { address serviceManagerOwner = preUpgradeStates.serviceManager.owner; vm.startPrank(serviceManagerOwner); - // Grant RegistryCoordinator permission to call createOperatorSets on AllocationManager ServiceManagerBase(serviceManagerAddress).setAppointee( address(registryCoordinator), allocationManagerAddr, IAllocationManager.createOperatorSets.selector ); + console.log("Appointee set for createOperatorSets"); ServiceManagerBase(serviceManagerAddress).setAppointee( @@ -286,7 +292,7 @@ contract EigenDATest is Test { console.log("Updating AVS metadata URI to:", metadataURI); allocationManager.updateAVSMetadataURI(serviceManagerAddress, metadataURI); - vm.stopPrank(); // Stop impersonating serviceManagerOwner + vm.stopPrank(); // Set the AVS address in the Registry Coordinator (requires RC owner) - required before creating operator sets address registryCoordinatorOwner = @@ -296,9 +302,8 @@ contract EigenDATest is Test { registryCoordinator.setAVS(serviceManagerAddress); vm.stopPrank(); // Stop impersonating registryCoordinatorOwner - // === Action Phase === console.log("Creating a new slashable stake quorum (quorum 1)..."); - vm.startPrank(serviceManagerOwner); // Use service manager owner who now has permission via setAppointee + vm.startPrank(serviceManagerOwner); // Define parameters for the new quorum ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = @@ -316,7 +321,7 @@ contract EigenDATest is Test { }); uint96 minimumStake = uint96(1 ether); - uint32 lookAheadPeriod = 10; // Example value + uint32 lookAheadPeriod = 10; registryCoordinator.createSlashableStakeQuorum( operatorSetParam, minimumStake, strategyParams, lookAheadPeriod @@ -411,7 +416,7 @@ contract EigenDATest is Test { // Assert all addresses are not zero before deployment assertTrue(permissionControllerAddr != address(0), "PermissionController address not found"); assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); - // assertTrue(address(rewardsCoordinator) != address(0), "RewardsCoordinator address is zero"); + // assertTrue(address(rewardsCoordinator) != address(0), "RewardsCoordinator address is zero"); //TODO: assertTrue( address(registryCoordinator) != address(0), "RegistryCoordinator address is zero" ); @@ -461,48 +466,21 @@ contract EigenDATest is Test { /// Recent block post ALM upgrade vm.rollFork(3592349); - return data; } function _upgradeContracts() internal { - // Impersonate the upgrader account vm.startPrank(eigenDAData.permissions.eigenDAUpgrader); - // Upgrade each contract using the proxyAdmin and new implementations - if (newRegistryCoordinatorImpl != address(0)) { - UpgradeableProxyLib.upgrade( - eigenDAData.addresses.registryCoordinator, newRegistryCoordinatorImpl - ); - console.log("Upgraded RegistryCoordinator to:", newRegistryCoordinatorImpl); - } - - if (newServiceManagerImpl != address(0)) { - UpgradeableProxyLib.upgrade( - eigenDAData.addresses.eigenDAServiceManager, newServiceManagerImpl - ); - console.log("Upgraded EigenDAServiceManager to:", newServiceManagerImpl); - } - - if (newBlsApkRegistryImpl != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.blsApkRegistry, newBlsApkRegistryImpl); - console.log("Upgraded BLSApkRegistry to:", newBlsApkRegistryImpl); - } - - if (newIndexRegistryImpl != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.indexRegistry, newIndexRegistryImpl); - console.log("Upgraded IndexRegistry to:", newIndexRegistryImpl); - } - - if (newStakeRegistryImpl != address(0)) { - UpgradeableProxyLib.upgrade(eigenDAData.addresses.stakeRegistry, newStakeRegistryImpl); - console.log("Upgraded StakeRegistry to:", newStakeRegistryImpl); - } - - // SocketRegistry is a new deployment, not an upgrade, log its usage - if (socketRegistry != address(0)) { - console.log("Using newly deployed SocketRegistry instance at:", socketRegistry); - } + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.registryCoordinator, newRegistryCoordinatorImpl + ); + UpgradeableProxyLib.upgrade( + eigenDAData.addresses.eigenDAServiceManager, newServiceManagerImpl + ); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.blsApkRegistry, newBlsApkRegistryImpl); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.indexRegistry, newIndexRegistryImpl); + UpgradeableProxyLib.upgrade(eigenDAData.addresses.stakeRegistry, newStakeRegistryImpl); vm.stopPrank(); } @@ -559,7 +537,7 @@ contract EigenDATest is Test { vm.label(data.addresses.serviceManagerRouter, "ServiceManagerRouter"); vm.label(data.addresses.stakeRegistry, "StakeRegistry"); - // Label permission addresses + // Label permissioned addresses vm.label(data.permissions.eigenDABatchConfirmer, "EigenDABatchConfirmer"); vm.label(data.permissions.eigenDAChurner, "EigenDAChurner"); vm.label(data.permissions.eigenDAEjector, "EigenDAEjector"); @@ -571,7 +549,7 @@ contract EigenDATest is Test { } function _verifyInitialSetup() internal view { - // Verify that contracts are deployed at the expected addresses + // Verify that contracts are deployed and at least not null require( eigenDAData.addresses.registryCoordinator != address(0), "Registry Coordinator should be deployed" @@ -591,7 +569,6 @@ contract EigenDATest is Test { eigenDAData.addresses.stakeRegistry != address(0), "Stake Registry should be deployed" ); - // Verify permissions require( eigenDAData.permissions.eigenDAUpgrader != address(0), "EigenDA Upgrader should be defined" From 57bdddfd6e5528c36316b24d37f4531db49f2e63 Mon Sep 17 00:00:00 2001 From: steven Date: Thu, 3 Apr 2025 17:19:55 -0400 Subject: [PATCH 09/20] chore: refactor some setup and add missing function to interface --- src/interfaces/IRegistryCoordinator.sol | 2 + test/fork/EigenDA.t.sol | 117 ++++++++++++------------ 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/interfaces/IRegistryCoordinator.sol b/src/interfaces/IRegistryCoordinator.sol index 9bd3221e..e9116cb0 100644 --- a/src/interfaces/IRegistryCoordinator.sol +++ b/src/interfaces/IRegistryCoordinator.sol @@ -147,6 +147,8 @@ interface IRegistryCoordinator is bytes memory quorumNumbers ) external; + function operatorSetsEnabled() external view returns (bool); + /** * @notice Checks if a quorum is an M2 quorum. * @param quorumNumber The quorum identifier. diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index b224f5f8..9dac9f84 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -177,11 +177,23 @@ contract EigenDATest is Test { address public newStakeRegistryImpl; address public socketRegistry; + // Contract instances + ISlashingRegistryCoordinator public registryCoordinator; + IBLSApkRegistry public apkRegistry; + IIndexRegistry public indexRegistry; + IStakeRegistry public stakeRegistry; + IServiceManager public serviceManager; + IAllocationManager public allocationManager; + IAVSDirectory public avsDirectory; + IDelegationManagerExtended public delegationManager; + IPermissionController public permissionController; + // Test setup function that runs before each test function setUp() public virtual { // Setup the Holesky fork and load EigenDA deployment data eigenDAData = _setupEigenDAFork("test/utils"); + // Store contract addresses delegationManagerAddr = address(StakeRegistryExtended(eigenDAData.addresses.stakeRegistry).delegation()); avsDirectoryAddr = address( @@ -191,8 +203,20 @@ contract EigenDATest is Test { address(IDelegationManagerExtended(delegationManagerAddr).allocationManager()); permissionControllerAddr = address(IAllocationManagerExtended(allocationManagerAddr).permissionController()); - rewardsCoordinatorAddr = address(0); /// TODO: + rewardsCoordinatorAddr = address(0); + + // Store contract instances + registryCoordinator = + ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); + apkRegistry = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); + indexRegistry = IIndexRegistry(eigenDAData.addresses.indexRegistry); + stakeRegistry = IStakeRegistry(eigenDAData.addresses.stakeRegistry); + serviceManager = IServiceManager(eigenDAData.addresses.eigenDAServiceManager); + allocationManager = IAllocationManager(allocationManagerAddr); + avsDirectory = IAVSDirectory(avsDirectoryAddr); + delegationManager = IDelegationManagerExtended(delegationManagerAddr); + permissionController = IPermissionController(permissionControllerAddr); _verifyInitialSetup(); @@ -209,14 +233,8 @@ contract EigenDATest is Test { _upgradeContracts(); console.log("Validating post-upgrade contract states"); - ISlashingRegistryCoordinator rc = - ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - IBLSApkRegistry bls = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); - IIndexRegistry idx = IIndexRegistry(eigenDAData.addresses.indexRegistry); - IStakeRegistry stake = IStakeRegistry(eigenDAData.addresses.stakeRegistry); - // Verify quorum count is maintained - uint8 quorumCount = rc.quorumCount(); + uint8 quorumCount = registryCoordinator.quorumCount(); console.log("quorum count:", quorumCount); require( quorumCount == preUpgradeStates.registryCoordinator.numQuorums, @@ -226,22 +244,22 @@ contract EigenDATest is Test { // Verify each quorum's data is maintained across all registries for (uint8 i = 0; i < quorumCount; i++) { // 1. Verify BLSApkRegistry state - bytes32 currentApkHash = BN254.hashG1Point(bls.getApk(i)); + bytes32 currentApkHash = BN254.hashG1Point(apkRegistry.getApk(i)); require( currentApkHash == preUpgradeStates.blsApkRegistry.currentApkHashes[i], "BLSApkRegistry: APK hash changed after upgrade" ); // 2. Verify IndexRegistry state - uint32 operatorCount = idx.totalOperatorsForQuorum(i); + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(i); require( operatorCount == preUpgradeStates.indexRegistry.operatorCounts[i], "IndexRegistry: Operator count changed after upgrade" ); // 3. Verify StakeRegistry state - only if quorum exists in StakeRegistry - if (stake.getTotalStakeHistoryLength(i) > 0) { - uint256 strategyCount = stake.strategyParamsLength(i); + if (stakeRegistry.getTotalStakeHistoryLength(i) > 0) { + uint256 strategyCount = stakeRegistry.strategyParamsLength(i); require( uint32(strategyCount) == preUpgradeStates.stakeRegistry.numStrategies[i], "StakeRegistry: Strategy count changed after upgrade" @@ -255,15 +273,10 @@ contract EigenDATest is Test { function test_PostUpgrade_CreateOperatorSet() public { _upgradeContracts(); - IRegistryCoordinator registryCoordinator = - IRegistryCoordinator(eigenDAData.addresses.registryCoordinator); - IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); - address serviceManagerAddress = eigenDAData.addresses.eigenDAServiceManager; - // Verify the owner remained the same post-upgrade (sanity check) require( preUpgradeStates.serviceManager.owner - == OwnableUpgradeable(serviceManagerAddress).owner(), + == OwnableUpgradeable(address(serviceManager)).owner(), "Service Manager owner mismatch post-upgrade" ); @@ -272,7 +285,7 @@ contract EigenDATest is Test { address serviceManagerOwner = preUpgradeStates.serviceManager.owner; vm.startPrank(serviceManagerOwner); - ServiceManagerBase(serviceManagerAddress).setAppointee( + serviceManager.setAppointee( address(registryCoordinator), allocationManagerAddr, IAllocationManager.createOperatorSets.selector @@ -280,7 +293,7 @@ contract EigenDATest is Test { console.log("Appointee set for createOperatorSets"); - ServiceManagerBase(serviceManagerAddress).setAppointee( + serviceManager.setAppointee( serviceManagerOwner, // Grant permission to the owner itself allocationManagerAddr, IAllocationManager.updateAVSMetadataURI.selector @@ -290,7 +303,7 @@ contract EigenDATest is Test { // Update AVS metadata URI - required before creating operator sets string memory metadataURI = "https://eigenda.xyz/metadata"; console.log("Updating AVS metadata URI to:", metadataURI); - allocationManager.updateAVSMetadataURI(serviceManagerAddress, metadataURI); + allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); vm.stopPrank(); @@ -299,7 +312,7 @@ contract EigenDATest is Test { OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); console.log("Setting AVS address in Registry Coordinator..."); vm.startPrank(registryCoordinatorOwner); - registryCoordinator.setAVS(serviceManagerAddress); + registryCoordinator.setAVS(address(serviceManager)); vm.stopPrank(); // Stop impersonating registryCoordinatorOwner console.log("Creating a new slashable stake quorum (quorum 1)..."); @@ -329,32 +342,32 @@ contract EigenDATest is Test { vm.stopPrank(); + // Verify that operator sets are enabled in the Registry Coordinator + console.log("Verifying operator sets are enabled..."); + bool operatorSetsEnabled = + IRegistryCoordinator(address(registryCoordinator)).operatorSetsEnabled(); + assertTrue( + operatorSetsEnabled, + "Operator sets should be enabled after creating a slashable stake quorum" + ); + console.log("Successfully created new operator set quorum."); } function _captureAndStorePreUpgradeState() internal { - ISlashingRegistryCoordinator registryCoordinator = - ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); - address payable serviceManagerAddress = payable(eigenDAData.addresses.eigenDAServiceManager); - OwnableUpgradeable serviceManagerOwnable = OwnableUpgradeable(serviceManagerAddress); + OwnableUpgradeable serviceManagerOwnable = OwnableUpgradeable(address(serviceManager)); preUpgradeStates.serviceManager.owner = serviceManagerOwnable.owner(); - Pausable serviceManagerPausable = Pausable(serviceManagerAddress); + Pausable serviceManagerPausable = Pausable(address(serviceManager)); preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); - IBLSApkRegistry blsApkRegistry = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); - - IIndexRegistry indexRegistry = IIndexRegistry(eigenDAData.addresses.indexRegistry); - uint8 quorumCount = registryCoordinator.quorumCount(); preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); - IStakeRegistry stakeRegistry = IStakeRegistry(eigenDAData.addresses.stakeRegistry); - // For each quorum, gather data from all registries for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { // Get operator count for each quorum from IndexRegistry @@ -364,7 +377,7 @@ contract EigenDATest is Test { // Get APK hash for each quorum from BLSApkRegistry // Store the hash of the APK as bytes32 preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = - BN254.hashG1Point(blsApkRegistry.getApk(quorumIndex)); + BN254.hashG1Point(apkRegistry.getApk(quorumIndex)); // Get strategy count for each quorum from StakeRegistry uint256 strategyCount = 0; @@ -385,33 +398,23 @@ contract EigenDATest is Test { IRegistryCoordinatorTypes.SlashingRegistryParams memory slashingParams = IRegistryCoordinatorTypes.SlashingRegistryParams({ - stakeRegistry: IStakeRegistry(eigenDAData.addresses.stakeRegistry), - blsApkRegistry: IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry), - indexRegistry: IIndexRegistry(eigenDAData.addresses.indexRegistry), + stakeRegistry: stakeRegistry, + blsApkRegistry: apkRegistry, + indexRegistry: indexRegistry, socketRegistry: ISocketRegistry(socketRegistry), - allocationManager: IAllocationManager(allocationManagerAddr), + allocationManager: allocationManager, pauserRegistry: IPauserRegistry(eigenDAData.permissions.pauserRegistry) }); IRegistryCoordinatorTypes.RegistryCoordinatorParams memory params = IRegistryCoordinatorTypes.RegistryCoordinatorParams({ - serviceManager: IServiceManager(payable(eigenDAData.addresses.eigenDAServiceManager)), + serviceManager: serviceManager, slashingParams: slashingParams }); newRegistryCoordinatorImpl = address(new RegistryCoordinator(params)); - address registryCoordinatorAddr = eigenDAData.addresses.registryCoordinator; - address stakeRegistryAddr = eigenDAData.addresses.stakeRegistry; - - IAVSDirectory avsDirectory = IAVSDirectory(avsDirectoryAddr); IRewardsCoordinator rewardsCoordinator = IRewardsCoordinator(rewardsCoordinatorAddr); - ISlashingRegistryCoordinator registryCoordinator = - ISlashingRegistryCoordinator(registryCoordinatorAddr); - IStakeRegistry stakeRegistry = IStakeRegistry(stakeRegistryAddr); - - IPermissionController permissionController = IPermissionController(permissionControllerAddr); - IAllocationManager allocationManager = IAllocationManager(allocationManagerAddr); // Assert all addresses are not zero before deployment assertTrue(permissionControllerAddr != address(0), "PermissionController address not found"); @@ -425,6 +428,9 @@ contract EigenDATest is Test { address(permissionController) != address(0), "PermissionController address is zero" ); assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); + assertTrue(delegationManagerAddr != address(0), "DelegationManager address is zero"); + assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); + assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); newServiceManagerImpl = address( new TestServiceManager( @@ -439,17 +445,12 @@ contract EigenDATest is Test { newBlsApkRegistryImpl = address(new BLSApkRegistry(registryCoordinator)); newIndexRegistryImpl = address(new IndexRegistry(registryCoordinator)); - assertTrue( - address(registryCoordinator) != address(0), "RegistryCoordinator address is zero" - ); - assertTrue(delegationManagerAddr != address(0), "DelegationManager address is zero"); - assertTrue(address(avsDirectory) != address(0), "AVSDirectory address is zero"); - assertTrue(address(allocationManager) != address(0), "AllocationManager address is zero"); - - IDelegationManager delegationManager = IDelegationManager(delegationManagerAddr); newStakeRegistryImpl = address( new StakeRegistry( - registryCoordinator, delegationManager, avsDirectory, allocationManager + registryCoordinator, + IDelegationManager(address(delegationManager)), + avsDirectory, + allocationManager ) ); } From ef84225b5f57615f12d06ab53455b8f26e4336f0 Mon Sep 17 00:00:00 2001 From: steven Date: Thu, 3 Apr 2025 17:43:47 -0400 Subject: [PATCH 10/20] test: disable m2 quorum registration --- src/interfaces/IRegistryCoordinator.sol | 6 ++ test/fork/EigenDA.t.sol | 100 ++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/src/interfaces/IRegistryCoordinator.sol b/src/interfaces/IRegistryCoordinator.sol index e9116cb0..7dae857b 100644 --- a/src/interfaces/IRegistryCoordinator.sol +++ b/src/interfaces/IRegistryCoordinator.sol @@ -158,6 +158,12 @@ interface IRegistryCoordinator is uint8 quorumNumber ) external view returns (bool); + /** + * @notice Returns whether M2 quorum registration is disabled. + * @return True if M2 quorum registration is disabled, false otherwise. + */ + function isM2QuorumRegistrationDisabled() external view returns (bool); + /** * @notice Disables M2 quorum registration for the AVS. Once disabled, this cannot be enabled. * @dev When disabled, all registrations to M2 quorums will revert. Deregistrations are still possible. diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 9dac9f84..0653b8e0 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -354,6 +354,106 @@ contract EigenDATest is Test { console.log("Successfully created new operator set quorum."); } + function test_PostUpgrade_DisableM2() public { + _upgradeContracts(); + + // Verify the owner remained the same post-upgrade (sanity check) + require( + preUpgradeStates.serviceManager.owner + == OwnableUpgradeable(address(serviceManager)).owner(), + "Service Manager owner mismatch post-upgrade" + ); + + console.log("Configuring permissions for operator set creation..."); + + address serviceManagerOwner = preUpgradeStates.serviceManager.owner; + vm.startPrank(serviceManagerOwner); + + serviceManager.setAppointee( + address(registryCoordinator), + allocationManagerAddr, + IAllocationManager.createOperatorSets.selector + ); + + console.log("Appointee set for createOperatorSets"); + + serviceManager.setAppointee( + serviceManagerOwner, // Grant permission to the owner itself + allocationManagerAddr, + IAllocationManager.updateAVSMetadataURI.selector + ); + console.log("Appointee set for updateAVSMetadataURI"); + + // Update AVS metadata URI - required before creating operator sets + string memory metadataURI = "https://eigenda.xyz/metadata"; + console.log("Updating AVS metadata URI to:", metadataURI); + allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); + + vm.stopPrank(); + + // Set the AVS address in the Registry Coordinator (requires RC owner) - required before creating operator sets + address registryCoordinatorOwner = + OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); + console.log("Setting AVS address in Registry Coordinator..."); + vm.startPrank(registryCoordinatorOwner); + registryCoordinator.setAVS(address(serviceManager)); + vm.stopPrank(); // Stop impersonating registryCoordinatorOwner + + console.log("Creating a new slashable stake quorum (quorum 1)..."); + vm.startPrank(serviceManagerOwner); + + // Define parameters for the new quorum + ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = + ISlashingRegistryCoordinatorTypes.OperatorSetParam({ + maxOperatorCount: 100, + kickBIPsOfOperatorStake: 10500, // 105% + kickBIPsOfTotalStake: 100 // 1% + }); + + IStakeRegistryTypes.StrategyParams[] memory strategyParams = + new IStakeRegistryTypes.StrategyParams[](1); + strategyParams[0] = IStakeRegistryTypes.StrategyParams({ + strategy: IStrategy(address(0)), // TODO: Placeholder + multiplier: 1 * 1e18 + }); + + uint96 minimumStake = uint96(1 ether); + uint32 lookAheadPeriod = 10; + + registryCoordinator.createSlashableStakeQuorum( + operatorSetParam, minimumStake, strategyParams, lookAheadPeriod + ); + + vm.stopPrank(); + + // Verify that operator sets are enabled in the Registry Coordinator + console.log("Verifying operator sets are enabled..."); + bool operatorSetsEnabled = + IRegistryCoordinator(address(registryCoordinator)).operatorSetsEnabled(); + assertTrue( + operatorSetsEnabled, + "Operator sets should be enabled after creating a slashable stake quorum" + ); + + console.log("Verifying operator sets are enabled..."); + + // Disable M2 quorum registration in the Registry Coordinator + console.log("Disabling M2 quorum registration..."); + vm.startPrank(registryCoordinatorOwner); + IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); + vm.stopPrank(); + + // Verify M2 quorum registration is disabled + bool isM2QuorumRegistrationDisabled = + IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); + assertTrue( + isM2QuorumRegistrationDisabled, + "M2 quorum registration should be disabled" + ); + + console.log("Successfully disabled M2 quorum registration."); + } + function _captureAndStorePreUpgradeState() internal { preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); From f7a386c39e57296e1c4bd54b29997a133a99688c Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 11:09:11 -0400 Subject: [PATCH 11/20] test: create a new op set quourm and register operators to it --- test/fork/EigenDA.t.sol | 169 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 163 insertions(+), 6 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 0653b8e0..99bc7c8a 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -8,6 +8,8 @@ import {UpgradeableProxyLib} from "../unit/UpgradeableProxyLib.sol"; import {BN254} from "../../src/libraries/BN254.sol"; import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; +import {OperatorLib} from "../utils/OperatorLib.sol"; +import {BitmapUtils} from "../../src/libraries/BitmapUtils.sol"; import {IRegistryCoordinator} from "../../src/interfaces/IRegistryCoordinator.sol"; import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; @@ -22,6 +24,7 @@ import {IAllocationManager} from import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; +import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol"; import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; import {IRewardsCoordinator} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; @@ -32,6 +35,7 @@ import { OperatorSet, IAllocationManagerTypes } from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // Import concrete implementation for deployment import {RegistryCoordinator, IRegistryCoordinatorTypes} from "../../src/RegistryCoordinator.sol"; @@ -43,6 +47,11 @@ import {IndexRegistry} from "../../src/IndexRegistry.sol"; import {StakeRegistry, IStakeRegistryTypes} from "../../src/StakeRegistry.sol"; import {SocketRegistry} from "../../src/SocketRegistry.sol"; +// Import ERC20Mock contract +import {ERC20Mock} from "../mocks/ERC20Mock.sol"; +import {IStrategyFactory} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyFactory.sol"; +import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; + // Extended interface to get addresses of other contracts interface IServiceManagerExtended { function avsDirectory() external view returns (IAVSDirectory); @@ -54,6 +63,7 @@ interface StakeRegistryExtended { interface IDelegationManagerExtended { function allocationManager() external view returns (IAllocationManager); + function strategyManager() external view returns (IStrategyManager); } interface IAllocationManagerExtended { @@ -95,6 +105,7 @@ contract TestServiceManager is contract EigenDATest is Test { using stdJson for string; + using OperatorLib for *; struct EigenDADeploymentData { address blsApkRegistry; @@ -169,6 +180,12 @@ contract EigenDATest is Test { address public permissionControllerAddr; address public rewardsCoordinatorAddr; + // Constant for the number of operators + uint256 constant OPERATOR_COUNT = 5; + + // Operators array for testing + OperatorLib.Operator[OPERATOR_COUNT] public operators; + // New implementation addresses for upgrade address public newRegistryCoordinatorImpl; address public newServiceManagerImpl; @@ -188,6 +205,12 @@ contract EigenDATest is Test { IDelegationManagerExtended public delegationManager; IPermissionController public permissionController; + // Variables for token and strategy + address public token; + IStrategy public strategy; + IStrategyFactory public strategyFactory; + IStrategyManager public strategyManager; + // Test setup function that runs before each test function setUp() public virtual { // Setup the Holesky fork and load EigenDA deployment data @@ -217,6 +240,16 @@ contract EigenDATest is Test { avsDirectory = IAVSDirectory(avsDirectoryAddr); delegationManager = IDelegationManagerExtended(delegationManagerAddr); permissionController = IPermissionController(permissionControllerAddr); + // Initialize strategy manager and factory + strategyManager = delegationManager.strategyManager(); + strategyFactory = IStrategyFactory(strategyManager.strategyWhitelister()); + + // Create operators with static size + _createOperators(); + + // Setup tokens and strategy for operators + uint256 operatorTokenAmount = 10 ether; + (token, strategy) = _setupTokensForOperators(operatorTokenAmount); _verifyInitialSetup(); @@ -298,6 +331,12 @@ contract EigenDATest is Test { allocationManagerAddr, IAllocationManager.updateAVSMetadataURI.selector ); + + serviceManager.setAppointee( + serviceManagerOwner, // Grant permission to the owner itself + allocationManagerAddr, + IAllocationManager.setAVSRegistrar.selector + ); console.log("Appointee set for updateAVSMetadataURI"); // Update AVS metadata URI - required before creating operator sets @@ -315,8 +354,11 @@ contract EigenDATest is Test { registryCoordinator.setAVS(address(serviceManager)); vm.stopPrank(); // Stop impersonating registryCoordinatorOwner - console.log("Creating a new slashable stake quorum (quorum 1)..."); vm.startPrank(serviceManagerOwner); + allocationManager.setAVSRegistrar(address(serviceManager), IAVSRegistrar(address(registryCoordinator))); + vm.stopPrank(); + + console.log("Creating a new slashable stake quorum (quorum 1)..."); // Define parameters for the new quorum ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = @@ -329,19 +371,40 @@ contract EigenDATest is Test { IStakeRegistryTypes.StrategyParams[] memory strategyParams = new IStakeRegistryTypes.StrategyParams[](1); strategyParams[0] = IStakeRegistryTypes.StrategyParams({ - strategy: IStrategy(address(0)), // TODO: Placeholder + strategy: strategy, multiplier: 1 * 1e18 }); uint96 minimumStake = uint96(1 ether); - uint32 lookAheadPeriod = 10; - registryCoordinator.createSlashableStakeQuorum( - operatorSetParam, minimumStake, strategyParams, lookAheadPeriod + vm.startPrank(serviceManagerOwner); + registryCoordinator.createTotalDelegatedStakeQuorum( + operatorSetParam, minimumStake, strategyParams ); vm.stopPrank(); + // Register operators as EigenLayer operators + console.log("Registering operators in EigenLayer..."); + _registerOperatorsAsEigenLayerOperators(); + + // Register operators for the new quorum + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = 3; // Quorum 1 (slashable) + + console.log("Registering operators for quorum 1..."); + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + vm.startPrank(operators[i].key.addr); + OperatorLib.registerOperatorFromAVS_OpSet( + operators[i], + allocationManagerAddr, + address(registryCoordinator), + address(serviceManager), + operatorSetIds + ); + vm.stopPrank(); + } + // Verify that operator sets are enabled in the Registry Coordinator console.log("Verifying operator sets are enabled..."); bool operatorSetsEnabled = @@ -351,7 +414,11 @@ contract EigenDATest is Test { "Operator sets should be enabled after creating a slashable stake quorum" ); - console.log("Successfully created new operator set quorum."); + // Verify operators are registered + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(3); + assertEq(operatorCount, OPERATOR_COUNT, "All operators should be registered"); + + console.log("Successfully created new operator set quorum with %d operators", operatorCount); } function test_PostUpgrade_DisableM2() public { @@ -679,4 +746,94 @@ contract EigenDATest is Test { "Pauser Registry should be defined" ); } + + function _createTokenAndStrategy() internal returns (address token, IStrategy strategy) { + ERC20Mock tokenContract = new ERC20Mock(); + token = address(tokenContract); + strategy = IStrategyFactory(strategyFactory).deployNewStrategy(IERC20(token)); + } + + function _setupTokensForOperators(uint256 amount) internal returns (address token, IStrategy strategy) { + (token, strategy) = _createTokenAndStrategy(); + + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + OperatorLib.mintMockTokens(operators[i], token, amount); + vm.startPrank(operators[i].key.addr); + OperatorLib.depositTokenIntoStrategy( + operators[i], + address(strategyManager), + address(strategy), + token, + amount + ); + vm.stopPrank(); + } + } + + function _createOperators() internal { + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + operators[i] = OperatorLib.createOperator(string(abi.encodePacked("operator-", i + 1))); + } + } + + function _createOperators( + uint256 numOperators + ) internal returns (OperatorLib.Operator[] memory) { + OperatorLib.Operator[] memory ops = new OperatorLib.Operator[](numOperators); + for (uint256 i = 0; i < numOperators; i++) { + ops[i] = OperatorLib.createOperator(string(abi.encodePacked("operator-", i + 1))); + } + return ops; + } + + /** + * @dev Registers operators as EigenLayer operators + */ + function _registerOperatorsAsEigenLayerOperators() internal { + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + vm.startPrank(operators[i].key.addr); + OperatorLib.registerAsOperator(operators[i], delegationManagerAddr); + vm.stopPrank(); + } + } + + /** + * @dev Registers operators as EigenLayer operators + * @param operatorsToRegister Array of operators to register + */ + function _registerOperatorsAsEigenLayerOperators( + OperatorLib.Operator[] memory operatorsToRegister + ) internal { + for (uint256 i = 0; i < operatorsToRegister.length; i++) { + vm.startPrank(operatorsToRegister[i].key.addr); + OperatorLib.registerAsOperator(operatorsToRegister[i], delegationManagerAddr); + vm.stopPrank(); + } + } + + /** + * @dev Gets and sorts operator addresses for use in quorum updates + * @return Sorted two-dimensional array of operator addresses + */ + function _getAndSortOperators() internal view returns (address[][] memory) { + address[][] memory registeredOperators = new address[][](1); + registeredOperators[0] = new address[](OPERATOR_COUNT); + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + registeredOperators[0][i] = operators[i].key.addr; + } + + // Sort operator addresses + for (uint256 i = 0; i < registeredOperators[0].length - 1; i++) { + for (uint256 j = 0; j < registeredOperators[0].length - i - 1; j++) { + if (registeredOperators[0][j] > registeredOperators[0][j + 1]) { + address temp = registeredOperators[0][j]; + registeredOperators[0][j] = registeredOperators[0][j + 1]; + registeredOperators[0][j + 1] = temp; + } + } + } + + return registeredOperators; + } + } From 1adec21c514f51e1d211f7a689c5890ff7b6bf46 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 12:59:02 -0400 Subject: [PATCH 12/20] chore: refactor some shared setup for state and permissions --- test/fork/EigenDA.t.sol | 166 +++++++++++++++------------------------- 1 file changed, 60 insertions(+), 106 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 99bc7c8a..e676d6c6 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -180,6 +180,10 @@ contract EigenDATest is Test { address public permissionControllerAddr; address public rewardsCoordinatorAddr; + // Owner addresses for post-upgrade setup + address public registryCoordinatorOwner; + address public serviceManagerOwner; + // Constant for the number of operators uint256 constant OPERATOR_COUNT = 5; @@ -243,19 +247,22 @@ contract EigenDATest is Test { // Initialize strategy manager and factory strategyManager = delegationManager.strategyManager(); strategyFactory = IStrategyFactory(strategyManager.strategyWhitelister()); - - // Create operators with static size - _createOperators(); - - // Setup tokens and strategy for operators - uint256 operatorTokenAmount = 10 ether; - (token, strategy) = _setupTokensForOperators(operatorTokenAmount); + serviceManagerOwner = OwnableUpgradeable(eigenDAData.addresses.eigenDAServiceManager).owner(); + registryCoordinatorOwner = OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); _verifyInitialSetup(); _captureAndStorePreUpgradeState(); _deployNewImplementations(); + + _createOperators(); + + uint256 operatorTokenAmount = 10 ether; + (token, strategy) = _setupTokensForOperators(operatorTokenAmount); + + console.log("Registering operators in EigenLayer..."); + _registerOperatorsAsEigenLayerOperators(); } function test_Upgrade() public { @@ -265,6 +272,10 @@ contract EigenDATest is Test { function test_ValidatePostUpgradeState() public { _upgradeContracts(); console.log("Validating post-upgrade contract states"); + require( + serviceManagerOwner == OwnableUpgradeable(address(serviceManager)).owner(), + "Service Manager owner mismatch post-upgrade" + ); // Verify quorum count is maintained uint8 quorumCount = registryCoordinator.quorumCount(); @@ -306,57 +317,7 @@ contract EigenDATest is Test { function test_PostUpgrade_CreateOperatorSet() public { _upgradeContracts(); - // Verify the owner remained the same post-upgrade (sanity check) - require( - preUpgradeStates.serviceManager.owner - == OwnableUpgradeable(address(serviceManager)).owner(), - "Service Manager owner mismatch post-upgrade" - ); - - console.log("Configuring permissions for operator set creation..."); - - address serviceManagerOwner = preUpgradeStates.serviceManager.owner; - vm.startPrank(serviceManagerOwner); - - serviceManager.setAppointee( - address(registryCoordinator), - allocationManagerAddr, - IAllocationManager.createOperatorSets.selector - ); - - console.log("Appointee set for createOperatorSets"); - - serviceManager.setAppointee( - serviceManagerOwner, // Grant permission to the owner itself - allocationManagerAddr, - IAllocationManager.updateAVSMetadataURI.selector - ); - - serviceManager.setAppointee( - serviceManagerOwner, // Grant permission to the owner itself - allocationManagerAddr, - IAllocationManager.setAVSRegistrar.selector - ); - console.log("Appointee set for updateAVSMetadataURI"); - - // Update AVS metadata URI - required before creating operator sets - string memory metadataURI = "https://eigenda.xyz/metadata"; - console.log("Updating AVS metadata URI to:", metadataURI); - allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); - - vm.stopPrank(); - - // Set the AVS address in the Registry Coordinator (requires RC owner) - required before creating operator sets - address registryCoordinatorOwner = - OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); - console.log("Setting AVS address in Registry Coordinator..."); - vm.startPrank(registryCoordinatorOwner); - registryCoordinator.setAVS(address(serviceManager)); - vm.stopPrank(); // Stop impersonating registryCoordinatorOwner - - vm.startPrank(serviceManagerOwner); - allocationManager.setAVSRegistrar(address(serviceManager), IAVSRegistrar(address(registryCoordinator))); - vm.stopPrank(); + _configureUAMAppointees(); console.log("Creating a new slashable stake quorum (quorum 1)..."); @@ -384,13 +345,11 @@ contract EigenDATest is Test { vm.stopPrank(); - // Register operators as EigenLayer operators - console.log("Registering operators in EigenLayer..."); - _registerOperatorsAsEigenLayerOperators(); + // Register operators for the new quorum uint32[] memory operatorSetIds = new uint32[](1); - operatorSetIds[0] = 3; // Quorum 1 (slashable) + operatorSetIds[0] = 3; // Quorum 3 (totalDelegatedStake) console.log("Registering operators for quorum 1..."); for (uint256 i = 0; i < OPERATOR_COUNT; i++) { @@ -424,47 +383,7 @@ contract EigenDATest is Test { function test_PostUpgrade_DisableM2() public { _upgradeContracts(); - // Verify the owner remained the same post-upgrade (sanity check) - require( - preUpgradeStates.serviceManager.owner - == OwnableUpgradeable(address(serviceManager)).owner(), - "Service Manager owner mismatch post-upgrade" - ); - - console.log("Configuring permissions for operator set creation..."); - - address serviceManagerOwner = preUpgradeStates.serviceManager.owner; - vm.startPrank(serviceManagerOwner); - - serviceManager.setAppointee( - address(registryCoordinator), - allocationManagerAddr, - IAllocationManager.createOperatorSets.selector - ); - - console.log("Appointee set for createOperatorSets"); - - serviceManager.setAppointee( - serviceManagerOwner, // Grant permission to the owner itself - allocationManagerAddr, - IAllocationManager.updateAVSMetadataURI.selector - ); - console.log("Appointee set for updateAVSMetadataURI"); - - // Update AVS metadata URI - required before creating operator sets - string memory metadataURI = "https://eigenda.xyz/metadata"; - console.log("Updating AVS metadata URI to:", metadataURI); - allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); - - vm.stopPrank(); - - // Set the AVS address in the Registry Coordinator (requires RC owner) - required before creating operator sets - address registryCoordinatorOwner = - OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); - console.log("Setting AVS address in Registry Coordinator..."); - vm.startPrank(registryCoordinatorOwner); - registryCoordinator.setAVS(address(serviceManager)); - vm.stopPrank(); // Stop impersonating registryCoordinatorOwner + _configureUAMAppointees(); console.log("Creating a new slashable stake quorum (quorum 1)..."); vm.startPrank(serviceManagerOwner); @@ -524,9 +443,6 @@ contract EigenDATest is Test { function _captureAndStorePreUpgradeState() internal { preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); - OwnableUpgradeable serviceManagerOwnable = OwnableUpgradeable(address(serviceManager)); - preUpgradeStates.serviceManager.owner = serviceManagerOwnable.owner(); - Pausable serviceManagerPausable = Pausable(address(serviceManager)); preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); @@ -556,6 +472,44 @@ contract EigenDATest is Test { } } + function _configureUAMAppointees() internal { + console.log("Configuring permissions for operator set creation..."); + + console.log("Setting AVS address in Registry Coordinator..."); + vm.startPrank(registryCoordinatorOwner); + registryCoordinator.setAVS(address(serviceManager)); + vm.stopPrank(); + + console.log("Appointee set for createOperatorSets"); + vm.startPrank(serviceManagerOwner); + serviceManager.setAppointee( + address(registryCoordinator), + allocationManagerAddr, + IAllocationManager.createOperatorSets.selector + ); + serviceManager.setAppointee( + serviceManagerOwner, + allocationManagerAddr, + IAllocationManager.updateAVSMetadataURI.selector + ); + + serviceManager.setAppointee( + serviceManagerOwner, + allocationManagerAddr, + IAllocationManager.setAVSRegistrar.selector + ); + + console.log("Appointees set for required permissions"); + + string memory metadataURI = "https://eigenda.xyz/metadata"; + console.log("Updating AVS metadata URI to:", metadataURI); + allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); + + allocationManager.setAVSRegistrar(address(serviceManager), IAVSRegistrar(address(registryCoordinator))); + vm.stopPrank(); + console.log("AVS Registrar set"); + } + function _deployNewImplementations() internal { socketRegistry = address( new SocketRegistry( From c452b5e7fac7aec6cca22bf932838bf0e971c703 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 12:59:20 -0400 Subject: [PATCH 13/20] chore: forge fmt --- test/fork/EigenDA.t.sol | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index e676d6c6..072f4c87 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -247,8 +247,10 @@ contract EigenDATest is Test { // Initialize strategy manager and factory strategyManager = delegationManager.strategyManager(); strategyFactory = IStrategyFactory(strategyManager.strategyWhitelister()); - serviceManagerOwner = OwnableUpgradeable(eigenDAData.addresses.eigenDAServiceManager).owner(); - registryCoordinatorOwner = OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); + serviceManagerOwner = + OwnableUpgradeable(eigenDAData.addresses.eigenDAServiceManager).owner(); + registryCoordinatorOwner = + OwnableUpgradeable(eigenDAData.addresses.registryCoordinator).owner(); _verifyInitialSetup(); @@ -331,10 +333,8 @@ contract EigenDATest is Test { IStakeRegistryTypes.StrategyParams[] memory strategyParams = new IStakeRegistryTypes.StrategyParams[](1); - strategyParams[0] = IStakeRegistryTypes.StrategyParams({ - strategy: strategy, - multiplier: 1 * 1e18 - }); + strategyParams[0] = + IStakeRegistryTypes.StrategyParams({strategy: strategy, multiplier: 1 * 1e18}); uint96 minimumStake = uint96(1 ether); @@ -345,8 +345,6 @@ contract EigenDATest is Test { vm.stopPrank(); - - // Register operators for the new quorum uint32[] memory operatorSetIds = new uint32[](1); operatorSetIds[0] = 3; // Quorum 3 (totalDelegatedStake) @@ -432,10 +430,7 @@ contract EigenDATest is Test { // Verify M2 quorum registration is disabled bool isM2QuorumRegistrationDisabled = IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); - assertTrue( - isM2QuorumRegistrationDisabled, - "M2 quorum registration should be disabled" - ); + assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); console.log("Successfully disabled M2 quorum registration."); } @@ -494,9 +489,7 @@ contract EigenDATest is Test { ); serviceManager.setAppointee( - serviceManagerOwner, - allocationManagerAddr, - IAllocationManager.setAVSRegistrar.selector + serviceManagerOwner, allocationManagerAddr, IAllocationManager.setAVSRegistrar.selector ); console.log("Appointees set for required permissions"); @@ -505,7 +498,9 @@ contract EigenDATest is Test { console.log("Updating AVS metadata URI to:", metadataURI); allocationManager.updateAVSMetadataURI(address(serviceManager), metadataURI); - allocationManager.setAVSRegistrar(address(serviceManager), IAVSRegistrar(address(registryCoordinator))); + allocationManager.setAVSRegistrar( + address(serviceManager), IAVSRegistrar(address(registryCoordinator)) + ); vm.stopPrank(); console.log("AVS Registrar set"); } @@ -707,18 +702,16 @@ contract EigenDATest is Test { strategy = IStrategyFactory(strategyFactory).deployNewStrategy(IERC20(token)); } - function _setupTokensForOperators(uint256 amount) internal returns (address token, IStrategy strategy) { + function _setupTokensForOperators( + uint256 amount + ) internal returns (address token, IStrategy strategy) { (token, strategy) = _createTokenAndStrategy(); for (uint256 i = 0; i < OPERATOR_COUNT; i++) { OperatorLib.mintMockTokens(operators[i], token, amount); vm.startPrank(operators[i].key.addr); OperatorLib.depositTokenIntoStrategy( - operators[i], - address(strategyManager), - address(strategy), - token, - amount + operators[i], address(strategyManager), address(strategy), token, amount ); vm.stopPrank(); } @@ -789,5 +782,4 @@ contract EigenDATest is Test { return registeredOperators; } - } From 0173040317825f88026a12319f76e60189dcdbac Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 15:41:44 -0400 Subject: [PATCH 14/20] chore: enumerate each of the operators currently registered --- test/fork/EigenDA.t.sol | 73 +++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 072f4c87..4f3a3b63 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -161,6 +161,12 @@ contract EigenDATest is Test { uint32[] numStrategies; } + struct M2QuorumOperators { + uint8[] quorumNumbers; + address[][] operatorIds; + string placeholder; // Add a dummy field to avoid getter compiler error + } + struct ContractStates { RegistryCoordinatorState registryCoordinator; ServiceManagerState serviceManager; @@ -172,6 +178,7 @@ contract EigenDATest is Test { // Variables to hold our data EigenDAData public eigenDAData; ContractStates public preUpgradeStates; + M2QuorumOperators public m2QuorumOperators; // Core contract addresses from StakeRegistry address public delegationManagerAddr; @@ -180,17 +187,12 @@ contract EigenDATest is Test { address public permissionControllerAddr; address public rewardsCoordinatorAddr; - // Owner addresses for post-upgrade setup address public registryCoordinatorOwner; address public serviceManagerOwner; - // Constant for the number of operators uint256 constant OPERATOR_COUNT = 5; - - // Operators array for testing OperatorLib.Operator[OPERATOR_COUNT] public operators; - // New implementation addresses for upgrade address public newRegistryCoordinatorImpl; address public newServiceManagerImpl; address public newBlsApkRegistryImpl; @@ -198,7 +200,6 @@ contract EigenDATest is Test { address public newStakeRegistryImpl; address public socketRegistry; - // Contract instances ISlashingRegistryCoordinator public registryCoordinator; IBLSApkRegistry public apkRegistry; IIndexRegistry public indexRegistry; @@ -209,18 +210,15 @@ contract EigenDATest is Test { IDelegationManagerExtended public delegationManager; IPermissionController public permissionController; - // Variables for token and strategy address public token; IStrategy public strategy; IStrategyFactory public strategyFactory; IStrategyManager public strategyManager; - // Test setup function that runs before each test function setUp() public virtual { // Setup the Holesky fork and load EigenDA deployment data eigenDAData = _setupEigenDAFork("test/utils"); - // Store contract addresses delegationManagerAddr = address(StakeRegistryExtended(eigenDAData.addresses.stakeRegistry).delegation()); avsDirectoryAddr = address( @@ -233,7 +231,6 @@ contract EigenDATest is Test { /// TODO: rewardsCoordinatorAddr = address(0); - // Store contract instances registryCoordinator = ISlashingRegistryCoordinator(eigenDAData.addresses.registryCoordinator); apkRegistry = IBLSApkRegistry(eigenDAData.addresses.blsApkRegistry); @@ -465,6 +462,62 @@ contract EigenDATest is Test { } preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); } + + // Record operators for M2 quorums + _recordM2QuorumOperators(); + } + + /// @notice Record the operators in each M2 quorum before the upgrade + function _recordM2QuorumOperators() internal { + // Use the getM2QuorumOperators function to get M2 quorum operators + (uint8[] memory quorumNumbers, address[][] memory operatorLists) = getM2QuorumOperators(); + + // Set the values in the m2QuorumOperators struct + m2QuorumOperators.quorumNumbers = quorumNumbers; + m2QuorumOperators.operatorIds = operatorLists; + + for (uint8 i = 0; i < quorumNumbers.length; i++) { + console.log( + "Recorded %d operators for quorum %d", operatorLists[i].length, quorumNumbers[i] + ); + } + } + + /** + * @notice Gets the operators registered to quorums created before operator sets were enabled (M2 quorums) + * @return m2QuorumNumbers Array of M2 quorum numbers + * @return m2QuorumOperatorLists Array of operator ID arrays corresponding to each quorum number + */ + function getM2QuorumOperators() + public + view + returns (uint8[] memory m2QuorumNumbers, address[][] memory m2QuorumOperatorLists) + { + uint256 quorumCount = registryCoordinator.quorumCount(); + m2QuorumNumbers = new uint8[](quorumCount); + m2QuorumOperatorLists = new address[][](quorumCount); + + for (uint8 i = 0; i < quorumCount; i++) { + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(i); + + if (operatorCount > 0) { + // Get the current list of operators for this quorum using external call + bytes32[] memory operatorIds = + indexRegistry.getOperatorListAtBlockNumber(i, uint32(block.number)); + + // Convert bytes32 operatorIds to addresses + address[] memory operatorAddresses = new address[](operatorIds.length); + for (uint256 j = 0; j < operatorIds.length; j++) { + // Use the BLSApkRegistry to get the operator address from the ID + operatorAddresses[j] = apkRegistry.getOperatorFromPubkeyHash(operatorIds[j]); + } + + m2QuorumOperatorLists[i] = operatorAddresses; + m2QuorumNumbers[i] = i; + } + } + + return (m2QuorumNumbers, m2QuorumOperatorLists); } function _configureUAMAppointees() internal { From 52104ac82aa06139f64809ebe31f6ef087ad3591 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 16:40:38 -0400 Subject: [PATCH 15/20] feat: remove unnecessary param --- test/utils/OperatorLib.sol | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/test/utils/OperatorLib.sol b/test/utils/OperatorLib.sol index 828cba05..1b7ebb57 100644 --- a/test/utils/OperatorLib.sol +++ b/test/utils/OperatorLib.sol @@ -35,10 +35,12 @@ import {CoreDeployLib} from "./CoreDeployLib.sol"; import {ERC20Mock} from "../mocks/ERC20Mock.sol"; import {BN254} from "../../src/libraries/BN254.sol"; import {BN256G2} from "./BN256G2.sol"; +import {BitmapUtils} from "../../src/libraries/BitmapUtils.sol"; library OperatorLib { using BN254 for *; using Strings for uint256; + using BitmapUtils for *; Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); @@ -172,8 +174,7 @@ library OperatorLib { address avsDirectory, address serviceManager, address registryCoordinator, - bytes memory quorumNumbers, - string memory socket + uint8[] memory quorumNumbers ) internal { IAVSDirectory avsDirectoryInstance = IAVSDirectory(avsDirectory); RegistryCoordinator registryCoordinatorInstance = RegistryCoordinator(registryCoordinator); @@ -207,18 +208,32 @@ library OperatorLib { expiry: expiry }); + // Convert quorumNumbers to bytes using BitmapUtils + uint256 quorumBitmap = 0; + for (uint256 i = 0; i < quorumNumbers.length; i++) { + quorumBitmap = BitmapUtils.setBit(quorumBitmap, quorumNumbers[i]); + } + bytes memory quorumNumbersBytes = BitmapUtils.bitmapToBytesArray(quorumBitmap); + // Call the registerOperator function on the registry registryCoordinatorInstance.registerOperator( - quorumNumbers, socket, params, operatorSignature + quorumNumbersBytes, "socket", params, operatorSignature ); } function deregisterOperatorFromAVS_M2( Operator memory operator, - address registryCoordinator + address registryCoordinator, + uint8[] memory quorumNumbers ) internal { - vm.prank(operator.key.addr); - RegistryCoordinator(registryCoordinator).deregisterOperator(""); + // Convert quorumNumbers to bytes using BitmapUtils + uint256 quorumBitmap = 0; + for (uint256 i = 0; i < quorumNumbers.length; i++) { + quorumBitmap = BitmapUtils.setBit(quorumBitmap, quorumNumbers[i]); + } + bytes memory quorumNumbersBytes = BitmapUtils.bitmapToBytesArray(quorumBitmap); + + RegistryCoordinator(registryCoordinator).deregisterOperator(quorumNumbersBytes); } function registerOperatorFromAVS_OpSet( From b3b0ab17fbf5fd6470f5866a734bf090dec4c36b Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 16:40:55 -0400 Subject: [PATCH 16/20] test: m2 flows full dereg and registration --- test/fork/EigenDA.t.sol | 210 ++++++++++++++++++++++++++++++++-------- 1 file changed, 167 insertions(+), 43 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 4f3a3b63..7e98a2d0 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -259,6 +259,7 @@ contract EigenDATest is Test { uint256 operatorTokenAmount = 10 ether; (token, strategy) = _setupTokensForOperators(operatorTokenAmount); + _setUpTokensForExistingQuorums(1000 ether); console.log("Registering operators in EigenLayer..."); _registerOperatorsAsEigenLayerOperators(); @@ -375,6 +376,132 @@ contract EigenDATest is Test { console.log("Successfully created new operator set quorum with %d operators", operatorCount); } + function test_PostUpgrade_DeregisterM2Operators() public { + // Upgrade the contracts first + _upgradeContracts(); + + uint256 totalDeregisteredOperators = 0; + + console.log("Deregistering M2 quorum operators..."); + + // Iterate through quorums and deregister each operator + for (uint8 i = 0; i < m2QuorumOperators.quorumNumbers.length; i++) { + uint8 quorumNumber = m2QuorumOperators.quorumNumbers[i]; + address[] memory operatorAddresses = m2QuorumOperators.operatorIds[i]; + + console.log( + "Deregistering %d operators from quorum %d", operatorAddresses.length, quorumNumber + ); + + // Prepare quorum number array for deregistration + uint8[] memory quorumNumbersArray = new uint8[](1); + quorumNumbersArray[0] = quorumNumber; + + // Deregister each operator from the quorum + for (uint256 j = 0; j < operatorAddresses.length; j++) { + address operatorAddr = operatorAddresses[j]; + + OperatorLib.Wallet memory wallet; + wallet.addr = operatorAddr; + + OperatorLib.Operator memory operator; + operator.key = wallet; + + vm.startPrank(operatorAddr); + + OperatorLib.deregisterOperatorFromAVS_M2( + operator, address(registryCoordinator), quorumNumbersArray + ); + + vm.stopPrank(); + totalDeregisteredOperators++; + } + } + + console.log( + "Successfully deregistered %d operators from M2 quorums", totalDeregisteredOperators + ); + + // Verify operators are deregistered by checking the updated operator counts + for (uint8 i = 0; i < m2QuorumOperators.quorumNumbers.length; i++) { + uint8 quorumNumber = m2QuorumOperators.quorumNumbers[i]; + if (m2QuorumOperators.operatorIds[i].length > 0) { + uint32 operatorCountAfter = indexRegistry.totalOperatorsForQuorum(quorumNumber); + assertEq(operatorCountAfter, 0, "Operators should be deregistered from quorum"); + console.log("Verified quorum %d now has 0 operators", quorumNumber); + } + } + } + + function test_PostUpgrade_RegisterToM2Quorums() public { + // Upgrade contracts first + _upgradeContracts(); + + // Use existing operators that were created in setUp + console.log("Using %d existing operators", OPERATOR_COUNT); + + console.log("Registering operators to M2 quorums..."); + + uint256 quorumCount = 1; + uint8[] memory quorumsToRegister = new uint8[](quorumCount); + for (uint8 i = 0; i < quorumCount; i++) { + quorumsToRegister[i] = 0; + } + + // Register each operator to the existing M2 quorums + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + vm.startPrank(operators[i].key.addr); + + OperatorLib.registerOperatorToAVS_M2( + operators[i], + address(avsDirectory), + address(serviceManager), + address(registryCoordinator), + quorumsToRegister + ); + + vm.stopPrank(); + console.log("Registered operator %d to M2 quorums", i + 1); + } + + console.log("Successfully registered %d operators to M2 quorums", OPERATOR_COUNT); + } + + function _captureAndStorePreUpgradeState() internal { + preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); + + Pausable serviceManagerPausable = Pausable(address(serviceManager)); + preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); + + uint8 quorumCount = registryCoordinator.quorumCount(); + preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); + preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); + preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); + + // For each quorum, gather data from all registries + for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { + // Get operator count for each quorum from IndexRegistry + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(quorumIndex); + preUpgradeStates.indexRegistry.operatorCounts[quorumIndex] = operatorCount; + + // Get APK hash for each quorum from BLSApkRegistry + // Store the hash of the APK as bytes32 + preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = + BN254.hashG1Point(apkRegistry.getApk(quorumIndex)); + + // Get strategy count for each quorum from StakeRegistry + uint256 strategyCount = 0; + // Check if quorum exists in StakeRegistry before querying + if (stakeRegistry.getTotalStakeHistoryLength(quorumIndex) > 0) { + strategyCount = stakeRegistry.strategyParamsLength(quorumIndex); + } + preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); + } + + // Record operators for M2 quorums + _recordM2QuorumOperators(); + } + function test_PostUpgrade_DisableM2() public { _upgradeContracts(); @@ -432,45 +559,9 @@ contract EigenDATest is Test { console.log("Successfully disabled M2 quorum registration."); } - function _captureAndStorePreUpgradeState() internal { - preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); - - Pausable serviceManagerPausable = Pausable(address(serviceManager)); - preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); - - uint8 quorumCount = registryCoordinator.quorumCount(); - preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); - preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); - preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); - - // For each quorum, gather data from all registries - for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { - // Get operator count for each quorum from IndexRegistry - uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(quorumIndex); - preUpgradeStates.indexRegistry.operatorCounts[quorumIndex] = operatorCount; - - // Get APK hash for each quorum from BLSApkRegistry - // Store the hash of the APK as bytes32 - preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = - BN254.hashG1Point(apkRegistry.getApk(quorumIndex)); - - // Get strategy count for each quorum from StakeRegistry - uint256 strategyCount = 0; - // Check if quorum exists in StakeRegistry before querying - if (stakeRegistry.getTotalStakeHistoryLength(quorumIndex) > 0) { - strategyCount = stakeRegistry.strategyParamsLength(quorumIndex); - } - preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); - } - - // Record operators for M2 quorums - _recordM2QuorumOperators(); - } - - /// @notice Record the operators in each M2 quorum before the upgrade function _recordM2QuorumOperators() internal { // Use the getM2QuorumOperators function to get M2 quorum operators - (uint8[] memory quorumNumbers, address[][] memory operatorLists) = getM2QuorumOperators(); + (uint8[] memory quorumNumbers, address[][] memory operatorLists) = _getM2QuorumOperators(); // Set the values in the m2QuorumOperators struct m2QuorumOperators.quorumNumbers = quorumNumbers; @@ -483,12 +574,7 @@ contract EigenDATest is Test { } } - /** - * @notice Gets the operators registered to quorums created before operator sets were enabled (M2 quorums) - * @return m2QuorumNumbers Array of M2 quorum numbers - * @return m2QuorumOperatorLists Array of operator ID arrays corresponding to each quorum number - */ - function getM2QuorumOperators() + function _getM2QuorumOperators() public view returns (uint8[] memory m2QuorumNumbers, address[][] memory m2QuorumOperatorLists) @@ -755,6 +841,44 @@ contract EigenDATest is Test { strategy = IStrategyFactory(strategyFactory).deployNewStrategy(IERC20(token)); } + function _setUpTokensForExistingQuorums( + uint256 amount + ) internal { + uint8 quorumNumber = 0; + uint8 strategyIndex = 2; + /// Strategy with a token we can deal with foundry + IStakeRegistry.StrategyParams memory stratParams = + stakeRegistry.strategyParamsByIndex(quorumNumber, strategyIndex); + + address strategyAddress = address(stratParams.strategy); + + console.log("Using strategy %s for quorum %d", strategyAddress, quorumNumber); + + // For each operator, deposit tokens into each strategy + for (uint256 opIndex = 0; opIndex < OPERATOR_COUNT; opIndex++) { + // Get the underlying token for this strategy + IERC20 underlyingTokenIERC20 = IStrategy(strategyAddress).underlyingToken(); + address tokenAddress = address(underlyingTokenIERC20); + + deal(tokenAddress, operators[opIndex].key.addr, amount, true); + + vm.startPrank(operators[opIndex].key.addr); + // Deposit tokens into the strategy + OperatorLib.depositTokenIntoStrategy( + operators[opIndex], address(strategyManager), strategyAddress, tokenAddress, amount + ); + + console.log( + "Deposited %d tokens into strategy %s for operator %s", + amount, + strategyAddress, + operators[opIndex].key.addr + ); + + vm.stopPrank(); + } + } + function _setupTokensForOperators( uint256 amount ) internal returns (address token, IStrategy strategy) { From 1855247769706b5852865220a2169f3480464608 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 16:49:02 -0400 Subject: [PATCH 17/20] chore: refactor setup --- test/fork/EigenDA.t.sol | 169 +++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 79 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 7e98a2d0..713fdd97 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -319,29 +319,7 @@ contract EigenDATest is Test { _configureUAMAppointees(); - console.log("Creating a new slashable stake quorum (quorum 1)..."); - - // Define parameters for the new quorum - ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = - ISlashingRegistryCoordinatorTypes.OperatorSetParam({ - maxOperatorCount: 100, - kickBIPsOfOperatorStake: 10500, // 105% - kickBIPsOfTotalStake: 100 // 1% - }); - - IStakeRegistryTypes.StrategyParams[] memory strategyParams = - new IStakeRegistryTypes.StrategyParams[](1); - strategyParams[0] = - IStakeRegistryTypes.StrategyParams({strategy: strategy, multiplier: 1 * 1e18}); - - uint96 minimumStake = uint96(1 ether); - - vm.startPrank(serviceManagerOwner); - registryCoordinator.createTotalDelegatedStakeQuorum( - operatorSetParam, minimumStake, strategyParams - ); - - vm.stopPrank(); + _createTotalDelegatedStakeOpSet(); // Register operators for the new quorum uint32[] memory operatorSetIds = new uint32[](1); @@ -379,6 +357,9 @@ contract EigenDATest is Test { function test_PostUpgrade_DeregisterM2Operators() public { // Upgrade the contracts first _upgradeContracts(); + _configureUAMAppointees(); + + _createTotalDelegatedStakeOpSet(); uint256 totalDeregisteredOperators = 0; @@ -437,6 +418,10 @@ contract EigenDATest is Test { // Upgrade contracts first _upgradeContracts(); + _configureUAMAppointees(); + + _createTotalDelegatedStakeOpSet(); + // Use existing operators that were created in setUp console.log("Using %d existing operators", OPERATOR_COUNT); @@ -467,48 +452,66 @@ contract EigenDATest is Test { console.log("Successfully registered %d operators to M2 quorums", OPERATOR_COUNT); } - function _captureAndStorePreUpgradeState() internal { - preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); + function test_PostUpgrade_DisableM2() public { + _upgradeContracts(); - Pausable serviceManagerPausable = Pausable(address(serviceManager)); - preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); + _configureUAMAppointees(); - uint8 quorumCount = registryCoordinator.quorumCount(); - preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); - preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); - preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); + // Create a slashable stake quorum with lookAheadPeriod + _createSlashableStakeOpSet(10); - // For each quorum, gather data from all registries - for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { - // Get operator count for each quorum from IndexRegistry - uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(quorumIndex); - preUpgradeStates.indexRegistry.operatorCounts[quorumIndex] = operatorCount; + // Verify that operator sets are enabled in the Registry Coordinator + console.log("Verifying operator sets are enabled..."); + bool operatorSetsEnabled = + IRegistryCoordinator(address(registryCoordinator)).operatorSetsEnabled(); + assertTrue( + operatorSetsEnabled, + "Operator sets should be enabled after creating a slashable stake quorum" + ); - // Get APK hash for each quorum from BLSApkRegistry - // Store the hash of the APK as bytes32 - preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = - BN254.hashG1Point(apkRegistry.getApk(quorumIndex)); + // Disable M2 quorum registration in the Registry Coordinator + console.log("Disabling M2 quorum registration..."); + vm.startPrank(registryCoordinatorOwner); + IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); + vm.stopPrank(); - // Get strategy count for each quorum from StakeRegistry - uint256 strategyCount = 0; - // Check if quorum exists in StakeRegistry before querying - if (stakeRegistry.getTotalStakeHistoryLength(quorumIndex) > 0) { - strategyCount = stakeRegistry.strategyParamsLength(quorumIndex); - } - preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); - } + // Verify M2 quorum registration is disabled + bool isM2QuorumRegistrationDisabled = + IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); + assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); - // Record operators for M2 quorums - _recordM2QuorumOperators(); + console.log("Successfully disabled M2 quorum registration."); } - function test_PostUpgrade_DisableM2() public { - _upgradeContracts(); + function _createTotalDelegatedStakeOpSet() internal { + console.log("Creating a new slashable stake quorum (quorum 1)..."); - _configureUAMAppointees(); + // Define parameters for the new quorum + ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = + ISlashingRegistryCoordinatorTypes.OperatorSetParam({ + maxOperatorCount: 100, + kickBIPsOfOperatorStake: 10500, // 105% + kickBIPsOfTotalStake: 100 // 1% + }); + + IStakeRegistryTypes.StrategyParams[] memory strategyParams = + new IStakeRegistryTypes.StrategyParams[](1); + strategyParams[0] = + IStakeRegistryTypes.StrategyParams({strategy: strategy, multiplier: 1 * 1e18}); + + uint96 minimumStake = uint96(1 ether); - console.log("Creating a new slashable stake quorum (quorum 1)..."); vm.startPrank(serviceManagerOwner); + registryCoordinator.createTotalDelegatedStakeQuorum( + operatorSetParam, minimumStake, strategyParams + ); + vm.stopPrank(); + } + + function _createSlashableStakeOpSet( + uint32 lookAheadPeriod + ) internal { + console.log("Creating a new slashable stake quorum with look ahead period..."); // Define parameters for the new quorum ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = @@ -520,43 +523,51 @@ contract EigenDATest is Test { IStakeRegistryTypes.StrategyParams[] memory strategyParams = new IStakeRegistryTypes.StrategyParams[](1); - strategyParams[0] = IStakeRegistryTypes.StrategyParams({ - strategy: IStrategy(address(0)), // TODO: Placeholder - multiplier: 1 * 1e18 - }); + strategyParams[0] = + IStakeRegistryTypes.StrategyParams({strategy: strategy, multiplier: 1 * 1e18}); uint96 minimumStake = uint96(1 ether); - uint32 lookAheadPeriod = 10; + vm.startPrank(serviceManagerOwner); registryCoordinator.createSlashableStakeQuorum( operatorSetParam, minimumStake, strategyParams, lookAheadPeriod ); - vm.stopPrank(); + } - // Verify that operator sets are enabled in the Registry Coordinator - console.log("Verifying operator sets are enabled..."); - bool operatorSetsEnabled = - IRegistryCoordinator(address(registryCoordinator)).operatorSetsEnabled(); - assertTrue( - operatorSetsEnabled, - "Operator sets should be enabled after creating a slashable stake quorum" - ); + function _captureAndStorePreUpgradeState() internal { + preUpgradeStates.registryCoordinator.numQuorums = registryCoordinator.quorumCount(); - console.log("Verifying operator sets are enabled..."); + Pausable serviceManagerPausable = Pausable(address(serviceManager)); + preUpgradeStates.serviceManager.paused = serviceManagerPausable.paused(); - // Disable M2 quorum registration in the Registry Coordinator - console.log("Disabling M2 quorum registration..."); - vm.startPrank(registryCoordinatorOwner); - IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); - vm.stopPrank(); + uint8 quorumCount = registryCoordinator.quorumCount(); + preUpgradeStates.blsApkRegistry.currentApkHashes = new bytes32[](quorumCount); + preUpgradeStates.indexRegistry.operatorCounts = new uint32[](quorumCount); + preUpgradeStates.stakeRegistry.numStrategies = new uint32[](quorumCount); - // Verify M2 quorum registration is disabled - bool isM2QuorumRegistrationDisabled = - IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); - assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); + // For each quorum, gather data from all registries + for (uint8 quorumIndex = 0; quorumIndex < quorumCount; quorumIndex++) { + // Get operator count for each quorum from IndexRegistry + uint32 operatorCount = indexRegistry.totalOperatorsForQuorum(quorumIndex); + preUpgradeStates.indexRegistry.operatorCounts[quorumIndex] = operatorCount; - console.log("Successfully disabled M2 quorum registration."); + // Get APK hash for each quorum from BLSApkRegistry + // Store the hash of the APK as bytes32 + preUpgradeStates.blsApkRegistry.currentApkHashes[quorumIndex] = + BN254.hashG1Point(apkRegistry.getApk(quorumIndex)); + + // Get strategy count for each quorum from StakeRegistry + uint256 strategyCount = 0; + // Check if quorum exists in StakeRegistry before querying + if (stakeRegistry.getTotalStakeHistoryLength(quorumIndex) > 0) { + strategyCount = stakeRegistry.strategyParamsLength(quorumIndex); + } + preUpgradeStates.stakeRegistry.numStrategies[quorumIndex] = uint32(strategyCount); + } + + // Record operators for M2 quorums + _recordM2QuorumOperators(); } function _recordM2QuorumOperators() internal { From 639b77693f0d7936db5745326a6e5eaf799859a7 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 17:03:51 -0400 Subject: [PATCH 18/20] test: eigen da flows --- test/fork/EigenDA.t.sol | 79 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 713fdd97..a07f9c25 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -415,11 +415,8 @@ contract EigenDATest is Test { } function test_PostUpgrade_RegisterToM2Quorums() public { - // Upgrade contracts first _upgradeContracts(); - _configureUAMAppointees(); - _createTotalDelegatedStakeOpSet(); // Use existing operators that were created in setUp @@ -483,6 +480,82 @@ contract EigenDATest is Test { console.log("Successfully disabled M2 quorum registration."); } + function test_PostUpgrade_DisableM2_Registration() public { + _upgradeContracts(); + _configureUAMAppointees(); + _createTotalDelegatedStakeOpSet(); + + // First disable M2 quorum registration + console.log("Disabling M2 quorum registration..."); + vm.startPrank(registryCoordinatorOwner); + IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); + vm.stopPrank(); + + // Verify M2 quorum registration is disabled + bool isM2QuorumRegistrationDisabled = + IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); + assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); + + uint8[] memory quorumsToRegister = new uint8[](1); + quorumsToRegister[0] = 0; // Quorum 0 is an M2 quorum + + // Attempt to register to M2 quorums - this should fail + console.log("Attempting to register to M2 quorums after disabling M2 registration..."); + vm.startPrank(operators[0].key.addr); + vm.expectRevert(); + OperatorLib.registerOperatorToAVS_M2( + operators[0], + address(avsDirectory), + address(serviceManager), + address(registryCoordinator), + quorumsToRegister + ); + + vm.stopPrank(); + console.log("Successfully verified M2 registration is disabled"); + } + + function test_PostUpgrade_DisableM2_Deregistration() public { + _upgradeContracts(); + _configureUAMAppointees(); + + // Register operators to M2 quorums before disabling M2 registration + console.log("Registering operators to M2 quorums before disabling registration..."); + uint8[] memory quorumsToRegister = new uint8[](1); + quorumsToRegister[0] = 0; // Quorum 0 is an M2 quorum + + // Now disable M2 quorum registration + console.log("Disabling M2 quorum registration..."); + vm.startPrank(registryCoordinatorOwner); + IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); + vm.stopPrank(); + + // Verify M2 quorum registration is disabled + bool isM2QuorumRegistrationDisabled = + IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); + assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); + + // Attempt to deregister operator from M2 quorums - this should succeed + console.log("Attempting to deregister from M2 quorums after disabling M2 registration..."); + address operatorAddr = m2QuorumOperators.operatorIds[0][0]; + + OperatorLib.Wallet memory wallet; + wallet.addr = operatorAddr; + + OperatorLib.Operator memory operator; + operator.key = wallet; + + vm.startPrank(operatorAddr); + OperatorLib.deregisterOperatorFromAVS_M2( + operators[0], address(registryCoordinator), quorumsToRegister + ); + vm.stopPrank(); + + console.log( + "Successfully verified deregistration from M2 quorums is still possible after disabling registration" + ); + } + function _createTotalDelegatedStakeOpSet() internal { console.log("Creating a new slashable stake quorum (quorum 1)..."); From 2e1554410831eb6d5a7b8716eb4dd6ae6ff14946 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 4 Apr 2025 17:13:13 -0400 Subject: [PATCH 19/20] test: disabled m2 quorums --- test/fork/EigenDA.t.sol | 58 ++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index a07f9c25..4eae2a3e 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -14,7 +14,7 @@ import {BitmapUtils} from "../../src/libraries/BitmapUtils.sol"; import {IRegistryCoordinator} from "../../src/interfaces/IRegistryCoordinator.sol"; import {IServiceManager} from "../../src/interfaces/IServiceManager.sol"; import {IStakeRegistry} from "../../src/interfaces/IStakeRegistry.sol"; -import {IBLSApkRegistry} from "../../src/interfaces/IBLSApkRegistry.sol"; +import {IBLSApkRegistry, IBLSApkRegistryTypes} from "../../src/interfaces/IBLSApkRegistry.sol"; import {IIndexRegistry} from "../../src/interfaces/IIndexRegistry.sol"; import {ISlashingRegistryCoordinator} from "../../src/interfaces/ISlashingRegistryCoordinator.sol"; import {ISocketRegistry} from "../../src/interfaces/ISocketRegistry.sol"; @@ -36,6 +36,10 @@ import { IAllocationManagerTypes } from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { + ISignatureUtilsMixin, + ISignatureUtilsMixinTypes +} from "eigenlayer-contracts/src/contracts/interfaces/ISignatureUtilsMixin.sol"; // Import concrete implementation for deployment import {RegistryCoordinator, IRegistryCoordinatorTypes} from "../../src/RegistryCoordinator.sol"; @@ -485,13 +489,11 @@ contract EigenDATest is Test { _configureUAMAppointees(); _createTotalDelegatedStakeOpSet(); - // First disable M2 quorum registration console.log("Disabling M2 quorum registration..."); vm.startPrank(registryCoordinatorOwner); IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); vm.stopPrank(); - // Verify M2 quorum registration is disabled bool isM2QuorumRegistrationDisabled = IRegistryCoordinator(address(registryCoordinator)).isM2QuorumRegistrationDisabled(); assertTrue(isM2QuorumRegistrationDisabled, "M2 quorum registration should be disabled"); @@ -499,16 +501,49 @@ contract EigenDATest is Test { uint8[] memory quorumsToRegister = new uint8[](1); quorumsToRegister[0] = 0; // Quorum 0 is an M2 quorum - // Attempt to register to M2 quorums - this should fail console.log("Attempting to register to M2 quorums after disabling M2 registration..."); vm.startPrank(operators[0].key.addr); - vm.expectRevert(); - OperatorLib.registerOperatorToAVS_M2( - operators[0], - address(avsDirectory), - address(serviceManager), - address(registryCoordinator), - quorumsToRegister + + bytes32 salt = keccak256(abi.encodePacked(block.timestamp, operators[0].key.addr)); + uint256 expiry = block.timestamp + 1 hours; + + bytes32 operatorRegistrationDigestHash = avsDirectory + .calculateOperatorAVSRegistrationDigestHash( + operators[0].key.addr, address(serviceManager), salt, expiry + ); + + bytes memory signature = + OperatorLib.signWithOperatorKey(operators[0], operatorRegistrationDigestHash); + + bytes32 pubkeyRegistrationMessageHash = + registryCoordinator.calculatePubkeyRegistrationMessageHash(operators[0].key.addr); + + BN254.G1Point memory blsSig = + OperatorLib.signMessage(operators[0].signingKey, pubkeyRegistrationMessageHash); + + IBLSApkRegistryTypes.PubkeyRegistrationParams memory params = IBLSApkRegistryTypes + .PubkeyRegistrationParams({ + pubkeyG1: operators[0].signingKey.publicKeyG1, + pubkeyG2: operators[0].signingKey.publicKeyG2, + pubkeyRegistrationSignature: blsSig + }); + + ISignatureUtilsMixinTypes.SignatureWithSaltAndExpiry memory operatorSignature = + ISignatureUtilsMixinTypes.SignatureWithSaltAndExpiry({ + signature: signature, + salt: salt, + expiry: expiry + }); + + uint256 quorumBitmap = 0; + for (uint256 i = 0; i < quorumsToRegister.length; i++) { + quorumBitmap = BitmapUtils.setBit(quorumBitmap, quorumsToRegister[i]); + } + bytes memory quorumNumbersBytes = BitmapUtils.bitmapToBytesArray(quorumBitmap); + + vm.expectRevert(bytes4(keccak256("M2QuorumRegistrationIsDisabled()"))); + IRegistryCoordinator(address(registryCoordinator)).registerOperator( + quorumNumbersBytes, "socket", params, operatorSignature ); vm.stopPrank(); @@ -559,7 +594,6 @@ contract EigenDATest is Test { function _createTotalDelegatedStakeOpSet() internal { console.log("Creating a new slashable stake quorum (quorum 1)..."); - // Define parameters for the new quorum ISlashingRegistryCoordinatorTypes.OperatorSetParam memory operatorSetParam = ISlashingRegistryCoordinatorTypes.OperatorSetParam({ maxOperatorCount: 100, From d7a29f684cb0fbe2a2b59e7040cb9d0f31342770 Mon Sep 17 00:00:00 2001 From: steven <12021290+stevennevins@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:36:03 -0400 Subject: [PATCH 20/20] test: add test for registering after m2 disabled (#454) **Motivation:** Add test after m2 is disabled for eigenda to verify registration **Modifications:** add a test for verify operator set registration after m2 quorums disabled **Result:** --- test/fork/EigenDA.t.sol | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/fork/EigenDA.t.sol b/test/fork/EigenDA.t.sol index 4eae2a3e..419c1492 100644 --- a/test/fork/EigenDA.t.sol +++ b/test/fork/EigenDA.t.sol @@ -591,6 +591,56 @@ contract EigenDATest is Test { ); } + function test_TotalDelegatedStakeQuorumRegistration() public { + _upgradeContracts(); + _configureUAMAppointees(); + _createTotalDelegatedStakeOpSet(); + vm.startPrank(registryCoordinatorOwner); + IRegistryCoordinator(address(registryCoordinator)).disableM2QuorumRegistration(); + vm.stopPrank(); + + uint8 quorumCount = registryCoordinator.quorumCount(); + uint8 totalDelegatedStakeQuorumId = quorumCount - 1; + + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = totalDelegatedStakeQuorumId; + + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + vm.startPrank(operators[i].key.addr); + + console.log("Registering operator %d: %s", i, operators[i].key.addr); + + OperatorLib.registerOperatorFromAVS_OpSet( + operators[i], + allocationManagerAddr, + address(registryCoordinator), + address(serviceManager), + operatorSetIds + ); + + vm.stopPrank(); + } + + uint32 registeredOperatorCount = + indexRegistry.totalOperatorsForQuorum(totalDelegatedStakeQuorumId); + assertEq( + registeredOperatorCount, + OPERATOR_COUNT, + "All operators should be registered to operatorset" + ); + + for (uint256 i = 0; i < OPERATOR_COUNT; i++) { + // Check operator registration status in RegistryCoordinator + ISlashingRegistryCoordinatorTypes.OperatorStatus status = + registryCoordinator.getOperatorStatus(operators[i].key.addr); + + assertTrue( + status == ISlashingRegistryCoordinatorTypes.OperatorStatus.REGISTERED, + "Operator should be registered" + ); + } + } + function _createTotalDelegatedStakeOpSet() internal { console.log("Creating a new slashable stake quorum (quorum 1)...");