From 89aff0069a2a6809bdb410578edd19e46a69a621 Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 18 Oct 2023 09:46:17 -0400 Subject: [PATCH 01/11] add back scripts --- script/AVSContractsDeploy.s.sol | 769 ++++++++++++++++++++++++++++++ script/DeployOpenEigenLayer.s.sol | 204 ++++++++ 2 files changed, 973 insertions(+) create mode 100644 script/AVSContractsDeploy.s.sol create mode 100644 script/DeployOpenEigenLayer.s.sol diff --git a/script/AVSContractsDeploy.s.sol b/script/AVSContractsDeploy.s.sol new file mode 100644 index 00000000..304d1181 --- /dev/null +++ b/script/AVSContractsDeploy.s.sol @@ -0,0 +1,769 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; +import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; + +import "eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol"; + +import "eigenlayer-contracts/src/contracts/core/StrategyManager.sol"; +import "eigenlayer-contracts/src/contracts/core/Slasher.sol"; +import "eigenlayer-contracts/src/contracts/core/DelegationManager.sol"; + +import "eigenlayer-contracts/src/contracts/strategies/StrategyBaseTVLLimits.sol"; + +import "eigenlayer-contracts/src/contracts/pods/EigenPod.sol"; +import "eigenlayer-contracts/src/contracts/pods/EigenPodManager.sol"; +import "eigenlayer-contracts/src/contracts/pods/DelayedWithdrawalRouter.sol"; + +import "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; +import "eigenlayer-contracts/src/contracts/middleware/BLSPublicKeyCompendium.sol"; + +import "eigenlayer-contracts/src/test/mocks/EmptyContract.sol"; +import "eigenlayer-contracts/src/test/mocks/ETHDepositMock.sol"; +import "eigenlayer-contracts/src/test/mocks/ERC20Mock.sol"; + +import "forge-std/Script.sol"; +import "forge-std/Test.sol"; + +// # To load the variables in the .env file +// source .env + +// # To deploy and verify our contract +// forge script script/EigenLayerDeploy.s.sol --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv +contract EigenLayerDeploy is Script, Test { + Vm cheats = Vm(HEVM_ADDRESS); + + // struct used to encode token info in config file + struct StrategyConfig { + uint256 maxDeposits; + uint256 maxPerDeposit; + address tokenAddress; + string tokenSymbol; + } + + // EigenLayer Contracts + ProxyAdmin public eigenLayerProxyAdmin; + PauserRegistry public eigenLayerPauserReg; + Slasher public slasher; + Slasher public slasherImplementation; + DelegationManager public delegation; + DelegationManager public delegationImplementation; + StrategyManager public strategyManager; + StrategyManager public strategyManagerImplementation; + EigenPodManager public eigenPodManager; + EigenPodManager public eigenPodManagerImplementation; + DelayedWithdrawalRouter public delayedWithdrawalRouter; + DelayedWithdrawalRouter public delayedWithdrawalRouterImplementation; + UpgradeableBeacon public eigenPodBeacon; + EigenPod public eigenPodImplementation; + StrategyBase public ERC20MockStrategy; + StrategyBase public ERC20MockStrategyImplementation; + + EmptyContract public emptyContract; + + address alphaMultisig; + + // the ETH2 deposit contract -- if not on mainnet, we deploy a mock as stand-in + IETHPOSDeposit public ethPOSDeposit; + + // strategies deployed + + // IMMUTABLES TO SET + uint256 REQUIRED_BALANCE_WEI; + + // OTHER DEPLOYMENT PARAMETERS + uint256 STRATEGY_MANAGER_INIT_PAUSED_STATUS; + uint256 SLASHER_INIT_PAUSED_STATUS; + uint256 DELEGATION_INIT_PAUSED_STATUS; + uint256 EIGENPOD_MANAGER_INIT_PAUSED_STATUS; + uint256 EIGENPOD_MANAGER_MAX_PODS; + uint256 DELAYED_WITHDRAWAL_ROUTER_INIT_PAUSED_STATUS; + + // one week in blocks -- 50400 + uint32 STRATEGY_MANAGER_INIT_WITHDRAWAL_DELAY_BLOCKS; + uint32 DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS; + string public deployConfigPath = string(bytes("script/configs/AVSContractsDeploy.json")); + + function run() external { + // read and log the chainID + uint256 chainId = block.chainid; + emit log_named_uint("You are deploying on ChainID", chainId); + + // READ JSON CONFIG DATA + string memory config_data = vm.readFile(deployConfigPath); + + STRATEGY_MANAGER_INIT_PAUSED_STATUS = stdJson.readUint( + config_data, + ".strategyManager.init_paused_status" + ); + SLASHER_INIT_PAUSED_STATUS = stdJson.readUint( + config_data, + ".slasher.init_paused_status" + ); + DELEGATION_INIT_PAUSED_STATUS = stdJson.readUint( + config_data, + ".delegation.init_paused_status" + ); + EIGENPOD_MANAGER_MAX_PODS = stdJson.readUint( + config_data, + ".eigenPodManager.max_pods" + ); + EIGENPOD_MANAGER_INIT_PAUSED_STATUS = stdJson.readUint( + config_data, + ".eigenPodManager.init_paused_status" + ); + DELAYED_WITHDRAWAL_ROUTER_INIT_PAUSED_STATUS = stdJson.readUint( + config_data, + ".delayedWithdrawalRouter.init_paused_status" + ); + + STRATEGY_MANAGER_INIT_WITHDRAWAL_DELAY_BLOCKS = uint32( + stdJson.readUint( + config_data, + ".strategyManager.init_withdrawal_delay_blocks" + ) + ); + DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS = uint32( + stdJson.readUint( + config_data, + ".strategyManager.init_withdrawal_delay_blocks" + ) + ); + + REQUIRED_BALANCE_WEI = stdJson.readUint( + config_data, + ".eigenPod.REQUIRED_BALANCE_WEI" + ); + + + alphaMultisig = stdJson.readAddress( + config_data, + ".multisig_addresses.alphaMultisig" + ); + + require( + alphaMultisig != address(0), + "alphaMultisig address not configured correctly!" + ); + + // START RECORDING TRANSACTIONS FOR DEPLOYMENT + vm.startBroadcast(); + + // deploy proxy admin for ability to upgrade proxy contracts + eigenLayerProxyAdmin = new ProxyAdmin(); + + //deploy pauser registry + { + address[] memory pausers = new address[](1); + pausers[0] = alphaMultisig; + eigenLayerPauserReg = new PauserRegistry(pausers, alphaMultisig); + } + + /** + * First, deploy upgradeable proxy contracts that **will point** to the implementations. Since the implementation contracts are + * not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code. + */ + emptyContract = new EmptyContract(); + delegation = DelegationManager( + address( + new TransparentUpgradeableProxy( + address(emptyContract), + address(eigenLayerProxyAdmin), + "" + ) + ) + ); + strategyManager = StrategyManager( + address( + new TransparentUpgradeableProxy( + address(emptyContract), + address(eigenLayerProxyAdmin), + "" + ) + ) + ); + slasher = Slasher( + address( + new TransparentUpgradeableProxy( + address(emptyContract), + address(eigenLayerProxyAdmin), + "" + ) + ) + ); + eigenPodManager = EigenPodManager( + address( + new TransparentUpgradeableProxy( + address(emptyContract), + address(eigenLayerProxyAdmin), + "" + ) + ) + ); + delayedWithdrawalRouter = DelayedWithdrawalRouter( + address( + new TransparentUpgradeableProxy( + address(emptyContract), + address(eigenLayerProxyAdmin), + "" + ) + ) + ); + + // if on mainnet, use the ETH2 deposit contract address + if (chainId == 1) { + ethPOSDeposit = IETHPOSDeposit( + 0x00000000219ab540356cBB839Cbe05303d7705Fa + ); + // if not on mainnet, deploy a mock + } else { + ethPOSDeposit = IETHPOSDeposit( + stdJson.readAddress(config_data, ".ethPOSDepositAddress") + ); + } + eigenPodImplementation = new EigenPod( + ethPOSDeposit, + delayedWithdrawalRouter, + eigenPodManager, + uint64(REQUIRED_BALANCE_WEI), + uint64(REQUIRED_BALANCE_WEI), + 1000 // temp genesis time, TODO: set if needed + ); + + eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation)); + + // Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs + delegationImplementation = new DelegationManager( + strategyManager, + slasher, + eigenPodManager + ); + strategyManagerImplementation = new StrategyManager( + delegation, + eigenPodManager, + slasher + ); + slasherImplementation = new Slasher(strategyManager, delegation); + eigenPodManagerImplementation = new EigenPodManager( + ethPOSDeposit, + eigenPodBeacon, + strategyManager, + slasher, + delegation + ); + delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter( + eigenPodManager + ); + + // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(delegation))), + address(delegationImplementation), + abi.encodeWithSelector( + DelegationManager.initialize.selector, + alphaMultisig, + eigenLayerPauserReg, + DELEGATION_INIT_PAUSED_STATUS + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(strategyManager))), + address(strategyManagerImplementation), + abi.encodeWithSelector( + StrategyManager.initialize.selector, + alphaMultisig, + alphaMultisig, + eigenLayerPauserReg, + STRATEGY_MANAGER_INIT_PAUSED_STATUS, + STRATEGY_MANAGER_INIT_WITHDRAWAL_DELAY_BLOCKS + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(slasher))), + address(slasherImplementation), + abi.encodeWithSelector( + Slasher.initialize.selector, + alphaMultisig, + eigenLayerPauserReg, + SLASHER_INIT_PAUSED_STATUS + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(eigenPodManager))), + address(eigenPodManagerImplementation), + abi.encodeWithSelector( + EigenPodManager.initialize.selector, + EIGENPOD_MANAGER_MAX_PODS, + IBeaconChainOracle(address(0)), + alphaMultisig, + eigenLayerPauserReg, + EIGENPOD_MANAGER_INIT_PAUSED_STATUS + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy( + payable(address(delayedWithdrawalRouter)) + ), + address(delayedWithdrawalRouterImplementation), + abi.encodeWithSelector( + DelayedWithdrawalRouter.initialize.selector, + alphaMultisig, + eigenLayerPauserReg, + DELAYED_WITHDRAWAL_ROUTER_INIT_PAUSED_STATUS, + DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS + ) + ); + + IERC20 mockToken = new ERC20Mock(); + + // ERC20MockStrategy = StrategyBase( + // address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + // ); + + // deploy StrategyBaseTVLLimits contract implementation + ERC20MockStrategyImplementation = new StrategyBase(strategyManager); + // create upgradeable proxies that each point to the implementation and initialize them + + // eigenLayerProxyAdmin.upgradeAndCall( + // TransparentUpgradeableProxy(payable(address(ERC20MockStrategy))), + // address(ERC20MockStrategyImplementation), + // abi.encodeWithSelector( + // EigenPodManager.initialize.selector, + // EIGENPOD_MANAGER_MAX_PODS, + // IBeaconChainOracle(address(0)), + // alphaMultisig, + // eigenLayerPauserReg, + // EIGENPOD_MANAGER_INIT_PAUSED_STATUS + // ) + // ); + + ERC20MockStrategy = StrategyBase( + address( + new TransparentUpgradeableProxy( + address(ERC20MockStrategyImplementation), + address(eigenLayerProxyAdmin), + abi.encodeWithSelector( + StrategyBase.initialize.selector, + mockToken, + eigenLayerPauserReg + ) + ) + ) + ); + + eigenLayerProxyAdmin.transferOwnership(alphaMultisig); + eigenPodBeacon.transferOwnership(alphaMultisig); + + // STOP RECORDING TRANSACTIONS FOR DEPLOYMENT + vm.stopBroadcast(); + + // CHECK CORRECTNESS OF DEPLOYMENT + _verifyContractsPointAtOneAnother( + delegationImplementation, + strategyManagerImplementation, + slasherImplementation, + eigenPodManagerImplementation, + delayedWithdrawalRouterImplementation + ); + _verifyContractsPointAtOneAnother( + delegation, + strategyManager, + slasher, + eigenPodManager, + delayedWithdrawalRouter + ); + _verifyImplementationsSetCorrectly(); + _verifyInitialOwners(); + _checkPauserInitializations(); + _verifyInitializationParams(); + + // WRITE JSON DATA + string memory parent_object = "parent object"; + + string memory deployed_addresses = "addresses"; + vm.serializeAddress( + deployed_addresses, + "eigenLayerProxyAdmin", + address(eigenLayerProxyAdmin) + ); + vm.serializeAddress( + deployed_addresses, + "eigenLayerPauserReg", + address(eigenLayerPauserReg) + ); + vm.serializeAddress(deployed_addresses, "slasher", address(slasher)); + vm.serializeAddress( + deployed_addresses, + "slasherImplementation", + address(slasherImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "delegation", + address(delegation) + ); + vm.serializeAddress( + deployed_addresses, + "delegationImplementation", + address(delegationImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "strategyManager", + address(strategyManager) + ); + vm.serializeAddress( + deployed_addresses, + "strategyManagerImplementation", + address(strategyManagerImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "eigenPodManager", + address(eigenPodManager) + ); + vm.serializeAddress( + deployed_addresses, + "eigenPodManagerImplementation", + address(eigenPodManagerImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "delayedWithdrawalRouter", + address(delayedWithdrawalRouter) + ); + vm.serializeAddress( + deployed_addresses, + "delayedWithdrawalRouterImplementation", + address(delayedWithdrawalRouterImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "eigenPodBeacon", + address(eigenPodBeacon) + ); + vm.serializeAddress( + deployed_addresses, + "eigenPodImplementation", + address(eigenPodImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "ERC20MockStrategy", + address(ERC20MockStrategy) + ); + vm.serializeAddress( + deployed_addresses, + "ERC20MockStrategyImplementation", + address(ERC20MockStrategyImplementation) + ); + vm.serializeAddress( + deployed_addresses, + "ERC20Mock", + address(mockToken) + ); + string memory deployed_addresses_output = vm.serializeAddress( + deployed_addresses, + "emptyContract", + address(emptyContract) + ); + + string memory parameters = "parameters"; + + string memory parameters_output = vm.serializeAddress( + parameters, + "alphaMultisig", + alphaMultisig + ); + + string memory chain_info = "chainInfo"; + vm.serializeUint(chain_info, "deploymentBlock", block.number); + string memory chain_info_output = vm.serializeUint( + chain_info, + "chainId", + chainId + ); + + // serialize all the data + vm.serializeString( + parent_object, + deployed_addresses, + deployed_addresses_output + ); + vm.serializeString( + parent_object, + chain_info, + chain_info_output + ); + string memory finalJson = vm.serializeString( + parent_object, + parameters, + parameters_output + ); + vm.writeJson(finalJson, "script/output/deployment_output.json"); + } + + function _verifyContractsPointAtOneAnother( + DelegationManager delegationContract, + StrategyManager strategyManagerContract, + Slasher slasherContract, + EigenPodManager eigenPodManagerContract, + DelayedWithdrawalRouter delayedWithdrawalRouterContract + ) internal view { + require( + delegationContract.slasher() == slasher, + "delegation: slasher address not set correctly" + ); + require( + delegationContract.strategyManager() == strategyManager, + "delegation: strategyManager address not set correctly" + ); + + require( + strategyManagerContract.slasher() == slasher, + "strategyManager: slasher address not set correctly" + ); + require( + strategyManagerContract.delegation() == delegation, + "strategyManager: delegation address not set correctly" + ); + require( + strategyManagerContract.eigenPodManager() == eigenPodManager, + "strategyManager: eigenPodManager address not set correctly" + ); + + require( + slasherContract.strategyManager() == strategyManager, + "slasher: strategyManager not set correctly" + ); + require( + slasherContract.delegation() == delegation, + "slasher: delegation not set correctly" + ); + + require( + eigenPodManagerContract.ethPOS() == ethPOSDeposit, + " eigenPodManager: ethPOSDeposit contract address not set correctly" + ); + require( + eigenPodManagerContract.eigenPodBeacon() == eigenPodBeacon, + "eigenPodManager: eigenPodBeacon contract address not set correctly" + ); + require( + eigenPodManagerContract.strategyManager() == strategyManager, + "eigenPodManager: strategyManager contract address not set correctly" + ); + require( + eigenPodManagerContract.slasher() == slasher, + "eigenPodManager: slasher contract address not set correctly" + ); + + require( + delayedWithdrawalRouterContract.eigenPodManager() == + eigenPodManager, + "delayedWithdrawalRouterContract: eigenPodManager address not set correctly" + ); + } + + function _verifyImplementationsSetCorrectly() internal view { + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(delegation))) + ) == address(delegationImplementation), + "delegation: implementation set incorrectly" + ); + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(strategyManager))) + ) == address(strategyManagerImplementation), + "strategyManager: implementation set incorrectly" + ); + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(slasher))) + ) == address(slasherImplementation), + "slasher: implementation set incorrectly" + ); + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(eigenPodManager))) + ) == address(eigenPodManagerImplementation), + "eigenPodManager: implementation set incorrectly" + ); + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy( + payable(address(delayedWithdrawalRouter)) + ) + ) == address(delayedWithdrawalRouterImplementation), + "delayedWithdrawalRouter: implementation set incorrectly" + ); + + require( + eigenLayerProxyAdmin.getProxyImplementation( + TransparentUpgradeableProxy(payable(address(ERC20MockStrategy))) + ) == address(ERC20MockStrategyImplementation), + "strategy: implementation set incorrectly" + ); + + require( + eigenPodBeacon.implementation() == address(eigenPodImplementation), + "eigenPodBeacon: implementation set incorrectly" + ); + } + + function _verifyInitialOwners() internal view { + require( + strategyManager.owner() == alphaMultisig, + "strategyManager: owner not set correctly" + ); + require( + delegation.owner() == alphaMultisig, + "delegation: owner not set correctly" + ); + require( + slasher.owner() == alphaMultisig, + "slasher: owner not set correctly" + ); + require( + eigenPodManager.owner() == alphaMultisig, + "delegation: owner not set correctly" + ); + + require( + eigenLayerProxyAdmin.owner() == alphaMultisig, + "eigenLayerProxyAdmin: owner not set correctly" + ); + require( + eigenPodBeacon.owner() == alphaMultisig, + "eigenPodBeacon: owner not set correctly" + ); + require( + delayedWithdrawalRouter.owner() == alphaMultisig, + "delayedWithdrawalRouter: owner not set correctly" + ); + } + + function _checkPauserInitializations() internal view { + require( + delegation.pauserRegistry() == eigenLayerPauserReg, + "delegation: pauser registry not set correctly" + ); + require( + strategyManager.pauserRegistry() == eigenLayerPauserReg, + "strategyManager: pauser registry not set correctly" + ); + require( + slasher.pauserRegistry() == eigenLayerPauserReg, + "slasher: pauser registry not set correctly" + ); + require( + eigenPodManager.pauserRegistry() == eigenLayerPauserReg, + "eigenPodManager: pauser registry not set correctly" + ); + require( + delayedWithdrawalRouter.pauserRegistry() == eigenLayerPauserReg, + "delayedWithdrawalRouter: pauser registry not set correctly" + ); + + require( + eigenLayerPauserReg.isPauser(alphaMultisig), + "pauserRegistry: alphaMultisig is not pauser" + ); + + require( + eigenLayerPauserReg.unpauser() == alphaMultisig, + "pauserRegistry: unpauser not set correctly" + ); + + require( + ERC20MockStrategy.pauserRegistry() == eigenLayerPauserReg, + "StrategyBaseTVLLimits: pauser registry not set correctly" + ); + require( + ERC20MockStrategy.paused() == 0, + "StrategyBaseTVLLimits: init paused status set incorrectly" + ); + + // // pause *nothing* + // uint256 STRATEGY_MANAGER_INIT_PAUSED_STATUS = 0; + // // pause *everything* + // uint256 SLASHER_INIT_PAUSED_STATUS = type(uint256).max; + // // pause *everything* + // uint256 DELEGATION_INIT_PAUSED_STATUS = type(uint256).max; + // // pause *all of the proof-related functionality* (everything that can be paused other than creation of EigenPods) + // uint256 EIGENPOD_MANAGER_INIT_PAUSED_STATUS = (2**1) + (2**2) + (2**3) + (2**4); /* = 30 */ + // // pause *nothing* + // uint256 DELAYED_WITHDRAWAL_ROUTER_INIT_PAUSED_STATUS = 0; + require( + strategyManager.paused() == 0, + "strategyManager: init paused status set incorrectly" + ); + require( + slasher.paused() == 0, + "slasher: init paused status set incorrectly" + ); + require( + delegation.paused() == 0, + "delegation: init paused status set incorrectly" + ); + require( + eigenPodManager.paused() == 30, + "eigenPodManager: init paused status set incorrectly" + ); + require( + delayedWithdrawalRouter.paused() == 0, + "delayedWithdrawalRouter: init paused status set incorrectly" + ); + } + + function _verifyInitializationParams() internal view { + // // one week in blocks -- 50400 + // uint32 STRATEGY_MANAGER_INIT_WITHDRAWAL_DELAY_BLOCKS = 7 days / 12 seconds; + // uint32 DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS = 7 days / 12 seconds; + // require(strategyManager.withdrawalDelayBlocks() == 7 days / 12 seconds, + // "strategyManager: withdrawalDelayBlocks initialized incorrectly"); + // require(delayedWithdrawalRouter.withdrawalDelayBlocks() == 7 days / 12 seconds, + // "delayedWithdrawalRouter: withdrawalDelayBlocks initialized incorrectly"); + // uint256 REQUIRED_BALANCE_WEI = 31 ether; + + require( + strategyManager.strategyWhitelister() == alphaMultisig, + "strategyManager: strategyWhitelister address not set correctly" + ); + + require( + eigenPodManager.beaconChainOracle() == + IBeaconChainOracle(address(0)), + "eigenPodManager: eigenPodBeacon contract address not set correctly" + ); + + require( + delayedWithdrawalRouter.eigenPodManager() == eigenPodManager, + "delayedWithdrawalRouter: eigenPodManager set incorrectly" + ); + + require( + ERC20MockStrategyImplementation.strategyManager() == strategyManager, + "ERC20MockStrategyImplementation: strategyManager set incorrectly" + ); + + require( + eigenPodImplementation.ethPOS() == ethPOSDeposit, + "eigenPodImplementation: ethPOSDeposit contract address not set correctly" + ); + require( + eigenPodImplementation.eigenPodManager() == eigenPodManager, + " eigenPodImplementation: eigenPodManager contract address not set correctly" + ); + require( + eigenPodImplementation.delayedWithdrawalRouter() == + delayedWithdrawalRouter, + " eigenPodImplementation: delayedWithdrawalRouter contract address not set correctly" + ); + } +} diff --git a/script/DeployOpenEigenLayer.s.sol b/script/DeployOpenEigenLayer.s.sol new file mode 100644 index 00000000..0e852a88 --- /dev/null +++ b/script/DeployOpenEigenLayer.s.sol @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity =0.8.12; + +import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; +import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; + +import "eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol"; + +import "eigenlayer-contracts/src/contracts/core/StrategyManager.sol"; +import "eigenlayer-contracts/src/contracts/core/Slasher.sol"; +import "eigenlayer-contracts/src/contracts/core/DelegationManager.sol"; + +import "eigenlayer-contracts/src/contracts/strategies/StrategyBaseTVLLimits.sol"; + +import "eigenlayer-contracts/src/contracts/pods/EigenPod.sol"; +import "eigenlayer-contracts/src/contracts/pods/EigenPodManager.sol"; +import "eigenlayer-contracts/src/contracts/pods/DelayedWithdrawalRouter.sol"; + +import "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; +import "src/BLSPublicKeyCompendium.sol"; + +import "eigenlayer-contracts/src/test/mocks/EmptyContract.sol"; +import "eigenlayer-contracts/src/test/mocks/ETHDepositMock.sol"; + +import "forge-std/Script.sol"; +import "forge-std/Test.sol"; + +// # To load the variables in the .env file +// source .env + +// # To deploy and verify our contract +// forge script script/M1_Deploy.s.sol:Deployer_M1 --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv +contract DeployOpenEigenLayer is Script, Test { + Vm cheats = Vm(HEVM_ADDRESS); + + // struct used to encode token info in config file + struct StrategyConfig { + uint256 maxDeposits; + uint256 maxPerDeposit; + address tokenAddress; + string tokenSymbol; + } + + // EigenLayer Contracts + ProxyAdmin public eigenLayerProxyAdmin; + PauserRegistry public eigenLayerPauserReg; + Slasher public slasher; + Slasher public slasherImplementation; + DelegationManager public delegation; + DelegationManager public delegationImplementation; + StrategyManager public strategyManager; + StrategyManager public strategyManagerImplementation; + EigenPodManager public eigenPodManager; + EigenPodManager public eigenPodManagerImplementation; + DelayedWithdrawalRouter public delayedWithdrawalRouter; + DelayedWithdrawalRouter public delayedWithdrawalRouterImplementation; + UpgradeableBeacon public eigenPodBeacon; + EigenPod public eigenPodImplementation; + StrategyBase public baseStrategyImplementation; + + EmptyContract public emptyContract; + + // the ETH2 deposit contract -- if not on mainnet, we deploy a mock as stand-in + IETHPOSDeposit public ethPOSDeposit; + + // strategies deployed + StrategyBaseTVLLimits[] public deployedStrategyArray; + + function _deployEigenLayer(address executorMultisig, address operationsMultisig, address pauserMultisig, StrategyConfig[] memory strategyConfigs) internal { + require(executorMultisig != address(0), "executorMultisig address not configured correctly!"); + require(operationsMultisig != address(0), "operationsMultisig address not configured correctly!"); + + // deploy proxy admin for ability to upgrade proxy contracts + eigenLayerProxyAdmin = new ProxyAdmin(); + + //deploy pauser registry + { + address[] memory pausers = new address[](3); + pausers[0] = executorMultisig; + pausers[1] = operationsMultisig; + pausers[2] = pauserMultisig; + eigenLayerPauserReg = new PauserRegistry(pausers, executorMultisig); + } + + /** + * First, deploy upgradeable proxy contracts that **will point** to the implementations. Since the implementation contracts are + * not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code. + */ + emptyContract = new EmptyContract(); + delegation = DelegationManager( + address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + ); + strategyManager = StrategyManager( + address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + ); + slasher = Slasher( + address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + ); + eigenPodManager = EigenPodManager( + address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + ); + delayedWithdrawalRouter = DelayedWithdrawalRouter( + address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) + ); + + // ETH POS deposit is 0 address + eigenPodImplementation = new EigenPod( + ethPOSDeposit, + delayedWithdrawalRouter, + eigenPodManager, + // uint64(MAX_VALIDATOR_BALANCE_GWEI), + uint64(31 gwei), + // uint64(EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI) + uint64(0.75 gwei), + 1000 // temp genesis time + ); + + eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation)); + + // Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs + delegationImplementation = new DelegationManager(strategyManager, slasher, eigenPodManager); + strategyManagerImplementation = new StrategyManager(delegation, eigenPodManager, slasher); + slasherImplementation = new Slasher(strategyManager, delegation); + eigenPodManagerImplementation = new EigenPodManager(ethPOSDeposit, eigenPodBeacon, strategyManager, slasher, delegation); + delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter(eigenPodManager); + + // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(delegation))), + address(delegationImplementation), + abi.encodeWithSelector( + DelegationManager.initialize.selector, + executorMultisig, + eigenLayerPauserReg, + 0 + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(strategyManager))), + address(strategyManagerImplementation), + abi.encodeWithSelector( + StrategyManager.initialize.selector, + executorMultisig, + operationsMultisig, + eigenLayerPauserReg, + 0, + 0 + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(slasher))), + address(slasherImplementation), + abi.encodeWithSelector( + Slasher.initialize.selector, + executorMultisig, + eigenLayerPauserReg, + 0 + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(eigenPodManager))), + address(eigenPodManagerImplementation), + abi.encodeWithSelector( + EigenPodManager.initialize.selector, + type(uint256).max, + IBeaconChainOracle(address(0)), + executorMultisig, + eigenLayerPauserReg, + 0 + ) + ); + eigenLayerProxyAdmin.upgradeAndCall( + TransparentUpgradeableProxy(payable(address(delayedWithdrawalRouter))), + address(delayedWithdrawalRouterImplementation), + abi.encodeWithSelector(DelayedWithdrawalRouter.initialize.selector, + executorMultisig, + eigenLayerPauserReg, + 0, + 0 + ) + ); + + // deploy StrategyBaseTVLLimits contract implementation + baseStrategyImplementation = new StrategyBaseTVLLimits(strategyManager); + // create upgradeable proxies that each point to the implementation and initialize them + for (uint256 i = 0; i < strategyConfigs.length; ++i) { + deployedStrategyArray.push( + StrategyBaseTVLLimits(address( + new TransparentUpgradeableProxy( + address(baseStrategyImplementation), + address(eigenLayerProxyAdmin), + abi.encodeWithSelector(StrategyBaseTVLLimits.initialize.selector, strategyConfigs[i].maxPerDeposit, strategyConfigs[i].maxDeposits, IERC20(strategyConfigs[i].tokenAddress), eigenLayerPauserReg) + ) + )) + ); + } + + eigenLayerProxyAdmin.transferOwnership(executorMultisig); + eigenPodBeacon.transferOwnership(executorMultisig); + } +} From d571dd86b47ce2f96ba85468f88a91caed7f2b0a Mon Sep 17 00:00:00 2001 From: steven Date: Wed, 18 Oct 2023 15:45:54 -0400 Subject: [PATCH 02/11] add go operations --- foundry.toml | 2 ++ go.mod | 12 ++++++++++++ go.sum | 14 ++++++++++++++ test/ffi/util/G2Operations.sol | 2 +- 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/foundry.toml b/foundry.toml index 25b918f9..15ffb7fc 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,4 +3,6 @@ src = "src" out = "out" libs = ["lib"] +ffi = true + # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..e3390d9c --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module github.com/Layr-Labs/ffi + +go 1.20 + +require ( + github.com/bits-and-blooms/bitset v1.5.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.11.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + golang.org/x/sys v0.2.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..0bc3f8d7 --- /dev/null +++ b/go.sum @@ -0,0 +1,14 @@ +github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8= +github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.11.1 h1:pt2nLbntYZA5IXnSw21vcQgoUCRPn6J/xylWQpK8gtM= +github.com/consensys/gnark-crypto v0.11.1/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/test/ffi/util/G2Operations.sol b/test/ffi/util/G2Operations.sol index 9617f871..bc4d67d8 100644 --- a/test/ffi/util/G2Operations.sol +++ b/test/ffi/util/G2Operations.sol @@ -12,7 +12,7 @@ contract G2Operations is Test { string[] memory inputs = new string[](5); inputs[0] = "go"; inputs[1] = "run"; - inputs[2] = "src/test/ffi/go/g2mul.go"; + inputs[2] = "test/ffi/go/g2mul.go"; inputs[3] = x.toString(); inputs[4] = "1"; From b503dc33f02b38308d9751c609692e98d6d30bfd Mon Sep 17 00:00:00 2001 From: Yash Patil <40046473+ypatil12@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:26:24 -0400 Subject: [PATCH 03/11] split up operatorIndexUpdate struct into two --- docs/middleware/IndexRegistry.md | 17 ++++-- src/IndexRegistry.sol | 38 ++++++------- src/IndexRegistryStorage.sol | 2 +- src/interfaces/IIndexRegistry.sol | 15 +++-- test/unit/IndexRegistryUnit.t.sol | 92 +++++++++++++++---------------- 5 files changed, 90 insertions(+), 74 deletions(-) diff --git a/docs/middleware/IndexRegistry.md b/docs/middleware/IndexRegistry.md index 0f958ed7..ad7c3f1e 100644 --- a/docs/middleware/IndexRegistry.md +++ b/docs/middleware/IndexRegistry.md @@ -9,18 +9,27 @@ This contract assigns each operator an index (0 indexed) within each of its quor The RegistryCoordinator for the AVS makes call to the IndexRegistry to register an operator for a certain set of quorums. The IndexRegistry will assign the next index in each of the quorums the operator is registering for to the operator storing the following struct: ```solidity // struct used to give definitive ordering to operators at each blockNumber. -// NOTE: this struct is slightly abused for also storing the total number of operators for each quorum over time struct OperatorIndexUpdate { // blockNumber number from which `index` was the operators index - // the operator's index or the total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber` + // the operator's index is the first entry such that `blockNumber >= entry.fromBlockNumber` uint32 fromBlockNumber; - // index of the operator in array of operators, or the total number of operators if in the 'totalOperatorsHistory' + // index of the operator in array of operators // index = type(uint32).max = OPERATOR_DEREGISTERED_INDEX implies the operator was deregistered uint32 index; } ``` -The IndexRegistry also adds the operator's id to the append only list of operators that have registered for the middleware and it stores the total number of operators after the registering operator has registered for each of the quorums the operator is registering for by pushing the above struct to a growing array. +The IndexRegistry also adds the operator's id to the append only list of operators that have registered for the middleware and it stores the total number of operators after the registering operator has registered for each of the quorums the operator is registering for by pushing the below struct to a growing array. + +```solidity +// struct used to denote the number of operators in a quorum at a given blockNumber +struct QuorumUpdate { + // The total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber` + uint32 fromBlockNumber; + // The number of operators at `fromBlockNumber` + uint32 numOperators; +} +``` ### deregisterOperator diff --git a/src/IndexRegistry.sol b/src/IndexRegistry.sol index 348903cf..b44be066 100644 --- a/src/IndexRegistry.sol +++ b/src/IndexRegistry.sol @@ -50,7 +50,7 @@ contract IndexRegistry is IndexRegistryStorage { //this is the would-be index of the operator being registered, the total number of operators for that quorum (which is last index + 1) uint256 quorumHistoryLength = _totalOperatorsHistory[quorumNumber].length; - uint32 numOperators = quorumHistoryLength > 0 ? _totalOperatorsHistory[quorumNumber][quorumHistoryLength - 1].index : 0; + uint32 numOperators = quorumHistoryLength > 0 ? _totalOperatorsHistory[quorumNumber][quorumHistoryLength - 1].numOperators : 0; _updateOperatorIdToIndexHistory({ operatorId: operatorId, quorumNumber: quorumNumber, @@ -101,7 +101,7 @@ contract IndexRegistry is IndexRegistryStorage { }); _updateTotalOperatorHistory({ quorumNumber: quorumNumber, - numOperators: _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].index - 1 + numOperators: _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].numOperators - 1 }); } } @@ -116,12 +116,12 @@ contract IndexRegistry is IndexRegistryStorage { * @param numOperators is the number of operators in the quorum */ function _updateTotalOperatorHistory(uint8 quorumNumber, uint32 numOperators) internal { - OperatorIndexUpdate memory totalOperatorUpdate; + QuorumUpdate memory quorumUpdate; // In the case of totalOperatorsHistory, the index parameter is the number of operators in the quorum - totalOperatorUpdate.index = numOperators; - totalOperatorUpdate.fromBlockNumber = uint32(block.number); + quorumUpdate.numOperators = numOperators; + quorumUpdate.fromBlockNumber = uint32(block.number); - _totalOperatorsHistory[quorumNumber].push(totalOperatorUpdate); + _totalOperatorsHistory[quorumNumber].push(quorumUpdate); } /** @@ -152,7 +152,7 @@ contract IndexRegistry is IndexRegistryStorage { ) internal { uint32 operatorIdToSwapIndex = _operatorIdToIndexHistory[operatorIdToSwap][quorumNumber][_operatorIdToIndexHistory[operatorIdToSwap][quorumNumber].length - 1].index; require( - _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].index - 1 == operatorIdToSwapIndex, + _totalOperatorsHistory[quorumNumber][_totalOperatorsHistory[quorumNumber].length - 1].numOperators - 1 == operatorIdToSwapIndex, "IndexRegistry._processOperatorRemoval: operatorIdToSwap is not the last operator in the quorum" ); @@ -198,13 +198,13 @@ contract IndexRegistry is IndexRegistryStorage { // loop backwards through the total operator history to find the total number of operators at the given block number for (uint256 i = 0; i <= totalOperatorsHistoryLength - 1; i++) { uint256 listIndex = (totalOperatorsHistoryLength - 1) - i; - OperatorIndexUpdate memory totalOperatorUpdate = _totalOperatorsHistory[quorumNumber][listIndex]; + QuorumUpdate memory quorumUpdate = _totalOperatorsHistory[quorumNumber][listIndex]; // look for the first update that began before or at `blockNumber` - if (totalOperatorUpdate.fromBlockNumber <= blockNumber) { - return _totalOperatorsHistory[quorumNumber][listIndex].index; + if (quorumUpdate.fromBlockNumber <= blockNumber) { + return _totalOperatorsHistory[quorumNumber][listIndex].numOperators; } } - return _totalOperatorsHistory[quorumNumber][0].index; + return _totalOperatorsHistory[quorumNumber][0].numOperators; } /** @@ -251,10 +251,10 @@ contract IndexRegistry is IndexRegistryStorage { } /// @notice Returns the _totalOperatorsHistory entry for the specified `quorumNumber` at the specified `index` - function getTotalOperatorsUpdateForQuorumAtIndex( + function getQuorumUpdateAtIndex( uint8 quorumNumber, uint32 index - ) external view returns (OperatorIndexUpdate memory) { + ) external view returns (QuorumUpdate memory) { return _totalOperatorsHistory[quorumNumber][index]; } @@ -305,23 +305,23 @@ contract IndexRegistry is IndexRegistryStorage { uint32 blockNumber, uint32 index ) external view returns (uint32){ - OperatorIndexUpdate memory operatorIndexToCheck = _totalOperatorsHistory[quorumNumber][index]; + QuorumUpdate memory quorumUpdate = _totalOperatorsHistory[quorumNumber][index]; // blocknumber must be at or after the "index'th" entry's fromBlockNumber require( - blockNumber >= operatorIndexToCheck.fromBlockNumber, + blockNumber >= quorumUpdate.fromBlockNumber, "IndexRegistry.getTotalOperatorsForQuorumAtBlockNumberByIndex: provided index is too far in the past for provided block number" ); // if there is an index update after the "index'th" update, the blocknumber must be before the next entry's fromBlockNumber if (index != _totalOperatorsHistory[quorumNumber].length - 1){ - OperatorIndexUpdate memory nextOperatorIndex = _totalOperatorsHistory[quorumNumber][index + 1]; + QuorumUpdate memory nextQuorumUpdate = _totalOperatorsHistory[quorumNumber][index + 1]; require( - blockNumber < nextOperatorIndex.fromBlockNumber, + blockNumber < nextQuorumUpdate.fromBlockNumber, "IndexRegistry.getTotalOperatorsForQuorumAtBlockNumberByIndex: provided index is too far in the future for provided block number" ); } - return operatorIndexToCheck.index; + return quorumUpdate.numOperators; } /// @notice Returns an ordered list of operators of the services for the given `quorumNumber` at the given `blockNumber` @@ -347,6 +347,6 @@ contract IndexRegistry is IndexRegistryStorage { if (totalOperatorsHistoryLength == 0) { return 0; } - return _totalOperatorsHistory[quorumNumber][totalOperatorsHistoryLength - 1].index; + return _totalOperatorsHistory[quorumNumber][totalOperatorsHistoryLength - 1].numOperators; } } diff --git a/src/IndexRegistryStorage.sol b/src/IndexRegistryStorage.sol index 8582678a..31ff71b8 100644 --- a/src/IndexRegistryStorage.sol +++ b/src/IndexRegistryStorage.sol @@ -25,7 +25,7 @@ abstract contract IndexRegistryStorage is Initializable, IIndexRegistry { /// @notice mapping of operatorId => quorumNumber => index history of that operator mapping(bytes32 => mapping(uint8 => OperatorIndexUpdate[])) internal _operatorIdToIndexHistory; /// @notice mapping of quorumNumber => history of numbers of unique registered operators - mapping(uint8 => OperatorIndexUpdate[]) internal _totalOperatorsHistory; + mapping(uint8 => QuorumUpdate[]) internal _totalOperatorsHistory; constructor( IRegistryCoordinator _registryCoordinator diff --git a/src/interfaces/IIndexRegistry.sol b/src/interfaces/IIndexRegistry.sol index 30a95998..1028c9ba 100644 --- a/src/interfaces/IIndexRegistry.sol +++ b/src/interfaces/IIndexRegistry.sol @@ -16,16 +16,23 @@ interface IIndexRegistry is IRegistry { // DATA STRUCTURES // struct used to give definitive ordering to operators at each blockNumber. - // NOTE: this struct is slightly abused for also storing the total number of operators for each quorum over time struct OperatorIndexUpdate { // blockNumber number from which `index` was the operators index - // the operator's index or the total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber` + // the operator's index is the first entry such that `blockNumber >= entry.fromBlockNumber` uint32 fromBlockNumber; - // index of the operator in array of operators, or the total number of operators if in the 'totalOperatorsHistory' + // index of the operator in array of operators // index = type(uint32).max = OPERATOR_DEREGISTERED_INDEX implies the operator was deregistered uint32 index; } + // struct used to denote the number of operators in a quorum at a given blockNumber + struct QuorumUpdate { + // The total number of operators at a `blockNumber` is the first entry such that `blockNumber >= entry.fromBlockNumber` + uint32 fromBlockNumber; + // The number of operators at `fromBlockNumber` + uint32 numOperators; + } + /** * @notice Registers the operator with the specified `operatorId` for the quorums specified by `quorumNumbers`. * @param operatorId is the id of the operator that is being registered @@ -63,7 +70,7 @@ interface IIndexRegistry is IRegistry { function getOperatorIndexUpdateOfOperatorIdForQuorumAtIndex(bytes32 operatorId, uint8 quorumNumber, uint32 index) external view returns (OperatorIndexUpdate memory); /// @notice Returns the _totalOperatorsHistory entry for the specified `quorumNumber` at the specified `index` - function getTotalOperatorsUpdateForQuorumAtIndex(uint8 quorumNumber, uint32 index) external view returns (OperatorIndexUpdate memory); + function getQuorumUpdateAtIndex(uint8 quorumNumber, uint32 index) external view returns (QuorumUpdate memory); /** * @notice Looks up the `operator`'s index for `quorumNumber` at the specified `blockNumber` using the `index`. diff --git a/test/unit/IndexRegistryUnit.t.sol b/test/unit/IndexRegistryUnit.t.sol index db1d80bd..a065e7d0 100644 --- a/test/unit/IndexRegistryUnit.t.sol +++ b/test/unit/IndexRegistryUnit.t.sol @@ -80,14 +80,14 @@ contract IndexRegistryUnitTests is Test { ); // Check _totalOperatorsHistory updates - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(1, 0); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(1, 0); require( - totalOperatorUpdate.index == 1, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 1" + quorumUpdate.numOperators == 1, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not 1" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -135,14 +135,14 @@ contract IndexRegistryUnitTests is Test { ); // Check _totalOperatorsHistory updates - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(2, 0); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(2, 0); require( - totalOperatorUpdate.index == 1, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 1" + quorumUpdate.numOperators == 1, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not 1" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -188,14 +188,14 @@ contract IndexRegistryUnitTests is Test { ); // Check _totalOperatorsHistory updates for quorum 1 - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(1, 0); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(1, 0); require( - totalOperatorUpdate.index == 1, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 1" + quorumUpdate.numOperators == 1, + "IndexRegistry.registerOperator: totalOperatorsHistory numOperators not 1" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -212,13 +212,13 @@ contract IndexRegistryUnitTests is Test { ); // Check _totalOperatorsHistory updates for quorum 2 - totalOperatorUpdate = indexRegistry.getTotalOperatorsUpdateForQuorumAtIndex(2, 0); + quorumUpdate = indexRegistry.getQuorumUpdateAtIndex(2, 0); require( - totalOperatorUpdate.index == 1, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 1" + quorumUpdate.numOperators == 1, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not 1" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -265,14 +265,14 @@ contract IndexRegistryUnitTests is Test { ); // Check _totalOperatorsHistory updates - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(1, 1); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(1, 1); require( - totalOperatorUpdate.index == 2, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 2" + quorumUpdate.numOperators == 2, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not 2" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -316,10 +316,10 @@ contract IndexRegistryUnitTests is Test { require(indexUpdate.index == type(uint32).max, "incorrect index"); // Check total operators - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(defaultQuorumNumber, 1); - require(totalOperatorUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); - require(totalOperatorUpdate.index == 0, "incorrect total number of operators"); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(defaultQuorumNumber, 1); + require(quorumUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); + require(quorumUpdate.numOperators == 0, "incorrect total number of operators"); require(indexRegistry.totalOperatorsForQuorum(1) == 0, "operator not deregistered correctly"); } @@ -373,10 +373,10 @@ contract IndexRegistryUnitTests is Test { // Check total operators for removed quorums for (uint256 i = 0; i < quorumsToRemove.length; i++) { - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(uint8(quorumsToRemove[i]), 3); // 4 updates total - require(totalOperatorUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); - require(totalOperatorUpdate.index == 2, "incorrect total number of operators"); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(uint8(quorumsToRemove[i]), 3); // 4 updates total + require(quorumUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); + require(quorumUpdate.numOperators == 2, "incorrect total number of operators"); require( indexRegistry.totalOperatorsForQuorum(uint8(quorumsToRemove[i])) == 2, "operator not deregistered correctly" @@ -664,15 +664,15 @@ contract IndexRegistryUnitTests is Test { } // Check _totalOperatorsHistory updates - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate; + IIndexRegistry.QuorumUpdate memory quorumUpdate; for (uint256 i = 0; i < quorumNumbers.length; i++) { - totalOperatorUpdate = indexRegistry.getTotalOperatorsUpdateForQuorumAtIndex(uint8(quorumNumbers[i]), 0); + quorumUpdate = indexRegistry.getQuorumUpdateAtIndex(uint8(quorumNumbers[i]), 0); require( - totalOperatorUpdate.index == 1, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not 1" + quorumUpdate.numOperators == 1, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not 1" ); require( - totalOperatorUpdate.fromBlockNumber == block.number, + quorumUpdate.fromBlockNumber == block.number, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); require( @@ -703,20 +703,20 @@ contract IndexRegistryUnitTests is Test { ); // Check history of _totalOperatorsHistory updates at each blockNumber - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate; + IIndexRegistry.QuorumUpdate memory quorumUpdate; uint256 numOperators = 1; for (uint256 blockNumber = block.number - 20; blockNumber <= block.number; blockNumber += 10) { for (uint256 i = 0; i < quorumNumbers.length; i++) { - totalOperatorUpdate = indexRegistry.getTotalOperatorsUpdateForQuorumAtIndex( + quorumUpdate = indexRegistry.getQuorumUpdateAtIndex( uint8(quorumNumbers[i]), uint32(numOperators - 1) ); require( - totalOperatorUpdate.index == numOperators, - "IndexRegistry.registerOperator: totalOperatorsHistory index (num operators) not correct" + quorumUpdate.numOperators == numOperators, + "IndexRegistry.registerOperator: totalOperatorsHistory num operators not correct" ); require( - totalOperatorUpdate.fromBlockNumber == blockNumber, + quorumUpdate.fromBlockNumber == blockNumber, "IndexRegistry.registerOperator: totalOperatorsHistory fromBlockNumber not correct" ); } @@ -781,10 +781,10 @@ contract IndexRegistryUnitTests is Test { // Check total operators for removed quorums for (uint256 i = 0; i < quorumsToRemove.length; i++) { - IIndexRegistry.OperatorIndexUpdate memory totalOperatorUpdate = indexRegistry - .getTotalOperatorsUpdateForQuorumAtIndex(uint8(quorumsToRemove[i]), 2); // 3 updates total - require(totalOperatorUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); - require(totalOperatorUpdate.index == 1, "incorrect total number of operators"); + IIndexRegistry.QuorumUpdate memory quorumUpdate = indexRegistry + .getQuorumUpdateAtIndex(uint8(quorumsToRemove[i]), 2); // 3 updates total + require(quorumUpdate.fromBlockNumber == block.number, "fromBlockNumber not set correctly"); + require(quorumUpdate.numOperators == 1, "incorrect total number of operators"); require( indexRegistry.totalOperatorsForQuorum(uint8(quorumsToRemove[i])) == 1, "operator not deregistered correctly" From 439ca83a38ac01e86d351d110d6ef60d952f5da2 Mon Sep 17 00:00:00 2001 From: Yash Patil <40046473+ypatil12@users.noreply.github.com> Date: Thu, 19 Oct 2023 01:33:41 -0400 Subject: [PATCH 04/11] fix layout alignment --- src/IndexRegistry.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IndexRegistry.sol b/src/IndexRegistry.sol index b44be066..c3b5ed5b 100644 --- a/src/IndexRegistry.sol +++ b/src/IndexRegistry.sol @@ -107,7 +107,7 @@ contract IndexRegistry is IndexRegistryStorage { } /******************************************************************************* - INTERNAL FUNCTIONS + INTERNAL FUNCTIONS *******************************************************************************/ /** @@ -233,7 +233,7 @@ contract IndexRegistry is IndexRegistryStorage { } /******************************************************************************* - VIEW FUNCTIONS + VIEW FUNCTIONS *******************************************************************************/ /// @notice Returns the length of the globalOperatorList From cea4fc3d1aca80ff4b31553839efe47a5ba36f0f Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 20 Oct 2023 12:24:14 -0400 Subject: [PATCH 05/11] create interface shims --- src/BLSOperatorStateRetriever.sol | 10 +- src/BLSPubkeyRegistryStorage.sol | 8 +- src/BLSRegistryCoordinatorWithIndices.sol | 30 ++-- src/BLSSignatureChecker.sol | 14 +- src/ServiceManagerBase.sol | 16 +-- src/interfaces/IRegistry.sol | 13 +- src/interfaces/IRegistryCoordinator.sol | 95 +------------ src/interfaces/IServiceManager.sol | 37 +---- src/interfaces/IStakeRegistry.sol | 158 +--------------------- src/interfaces/IVoteWeigher.sol | 94 +------------ 10 files changed, 44 insertions(+), 431 deletions(-) diff --git a/src/BLSOperatorStateRetriever.sol b/src/BLSOperatorStateRetriever.sol index 3ed09104..85656e4c 100644 --- a/src/BLSOperatorStateRetriever.sol +++ b/src/BLSOperatorStateRetriever.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; -import {IStakeRegistry} from "src/interfaces/IStakeRegistry.sol"; -import {IBLSPubkeyRegistry} from "src/interfaces/IBLSPubkeyRegistry.sol"; -import {IIndexRegistry} from "src/interfaces/IIndexRegistry.sol"; -import {IBLSRegistryCoordinatorWithIndices} from "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; -import {BitmapUtils} from "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; +import "src/interfaces/IStakeRegistry.sol"; +import "src/interfaces/IBLSPubkeyRegistry.sol"; +import "src/interfaces/IIndexRegistry.sol"; +import "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; /** * @title BLSOperatorStateRetriever with view functions that allow to retrieve the state of an AVSs registry system. diff --git a/src/BLSPubkeyRegistryStorage.sol b/src/BLSPubkeyRegistryStorage.sol index f70a037a..22d4751a 100644 --- a/src/BLSPubkeyRegistryStorage.sol +++ b/src/BLSPubkeyRegistryStorage.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; -import {IBLSPubkeyRegistry} from "src/interfaces/IBLSPubkeyRegistry.sol"; -import {IRegistryCoordinator} from "src/interfaces/IRegistryCoordinator.sol"; -import {IBLSPublicKeyCompendium} from "src/interfaces/IBLSPublicKeyCompendium.sol"; -import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; +import "src/interfaces/IBLSPubkeyRegistry.sol"; +import "src/interfaces/IRegistryCoordinator.sol"; +import "src/interfaces/IBLSPublicKeyCompendium.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; diff --git a/src/BLSRegistryCoordinatorWithIndices.sol b/src/BLSRegistryCoordinatorWithIndices.sol index 0404891b..33dd131f 100644 --- a/src/BLSRegistryCoordinatorWithIndices.sol +++ b/src/BLSRegistryCoordinatorWithIndices.sol @@ -4,21 +4,21 @@ pragma solidity =0.8.12; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; -import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; -import {ISlasher} from "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; -import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; -import {EIP1271SignatureUtils} from "eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol"; -import {BitmapUtils} from "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; -import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; - -import {IBLSRegistryCoordinatorWithIndices} from "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; -import {ISocketUpdater} from "src/interfaces/ISocketUpdater.sol"; -import {IServiceManager} from "src/interfaces/IServiceManager.sol"; -import {IBLSPubkeyRegistry} from "src/interfaces/IBLSPubkeyRegistry.sol"; -import {IVoteWeigher} from "src/interfaces/IVoteWeigher.sol"; -import {IStakeRegistry} from "src/interfaces/IStakeRegistry.sol"; -import {IIndexRegistry} from "src/interfaces/IIndexRegistry.sol"; -import {IRegistryCoordinator} from "src/interfaces/IRegistryCoordinator.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; +import "eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; +import "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; + +import "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; +import "src/interfaces/ISocketUpdater.sol"; +import "src/interfaces/IServiceManager.sol"; +import "src/interfaces/IBLSPubkeyRegistry.sol"; +import "src/interfaces/IVoteWeigher.sol"; +import "src/interfaces/IStakeRegistry.sol"; +import "src/interfaces/IIndexRegistry.sol"; +import "src/interfaces/IRegistryCoordinator.sol"; diff --git a/src/BLSSignatureChecker.sol b/src/BLSSignatureChecker.sol index bddcbd5b..fdad60a9 100644 --- a/src/BLSSignatureChecker.sol +++ b/src/BLSSignatureChecker.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; -import {IBLSSignatureChecker} from "src/interfaces/IBLSSignatureChecker.sol"; -import {BitmapUtils} from "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; -import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; -import {IRegistryCoordinator} from "src/interfaces/IRegistryCoordinator.sol"; -import {IStakeRegistry} from "src/interfaces/IStakeRegistry.sol"; -import {IBLSPubkeyRegistry} from "src/interfaces/IBLSPubkeyRegistry.sol"; -import {IBLSRegistryCoordinatorWithIndices} from "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; +import "src/interfaces/IBLSSignatureChecker.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BitmapUtils.sol"; +import "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; +import "src/interfaces/IRegistryCoordinator.sol"; +import "src/interfaces/IStakeRegistry.sol"; +import "src/interfaces/IBLSPubkeyRegistry.sol"; +import "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; /** * @title Used for checking BLS aggregate signatures from the operators of a `BLSRegistry`. diff --git a/src/ServiceManagerBase.sol b/src/ServiceManagerBase.sol index 92e3371a..b49373ee 100644 --- a/src/ServiceManagerBase.sol +++ b/src/ServiceManagerBase.sol @@ -3,15 +3,15 @@ pragma solidity ^0.8.9; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; -import {BLSSignatureChecker} from "src/BLSSignatureChecker.sol"; -import {IBLSRegistryCoordinatorWithIndices} from "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; -import {IServiceManager} from "src/interfaces/IServiceManager.sol"; +import "src/BLSSignatureChecker.sol"; +import "src/interfaces/IBLSRegistryCoordinatorWithIndices.sol"; +import "src/interfaces/IServiceManager.sol"; -import {Pausable} from "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; -import {IPauserRegistry} from "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; -import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; -import {ISlasher} from "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; -import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; +import "eigenlayer-contracts/src/contracts/permissions/Pausable.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; +import "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; /** * @title Base implementation of `IServiceManager` interface, designed to be inherited from by more complex ServiceManagers. diff --git a/src/interfaces/IRegistry.sol b/src/interfaces/IRegistry.sol index 49e7d545..0b8bb3c0 100644 --- a/src/interfaces/IRegistry.sol +++ b/src/interfaces/IRegistry.sol @@ -1,15 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "./IRegistryCoordinator.sol"; - -/** - * @title Minimal interface for a `Registry`-type contract. - * @author Layr Labs, Inc. - * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service - * @notice Functions related to the registration process itself have been intentionally excluded - * because their function signatures may vary significantly. - */ -interface IRegistry { - function registryCoordinator() external view returns (IRegistryCoordinator); -} +import "eigenlayer-contracts/src/contracts/interfaces/IRegistry.sol"; diff --git a/src/interfaces/IRegistryCoordinator.sol b/src/interfaces/IRegistryCoordinator.sol index 3ee5b1a9..7bbad67e 100644 --- a/src/interfaces/IRegistryCoordinator.sol +++ b/src/interfaces/IRegistryCoordinator.sol @@ -1,97 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; -/** - * @title Interface for a contract that coordinates between various registries for an AVS. - * @author Layr Labs, Inc. - */ -interface IRegistryCoordinator { - // EVENTS - /// Emits when an operator is registered - event OperatorRegistered(address indexed operator, bytes32 indexed operatorId); - - /// Emits when an operator is deregistered - event OperatorDeregistered(address indexed operator, bytes32 indexed operatorId); - - // DATA STRUCTURES - enum OperatorStatus - { - // default is NEVER_REGISTERED - NEVER_REGISTERED, - REGISTERED, - DEREGISTERED - } - - // STRUCTS - - /** - * @notice Data structure for storing info on operators - */ - struct Operator { - // the id of the operator, which is likely the keccak256 hash of the operator's public key if using BLSRegsitry - bytes32 operatorId; - // indicates whether the operator is actively registered for serving the middleware or not - OperatorStatus status; - } - - /** - * @notice Data structure for storing info on quorum bitmap updates where the `quorumBitmap` is the bitmap of the - * quorums the operator is registered for starting at (inclusive)`updateBlockNumber` and ending at (exclusive) `nextUpdateBlockNumber` - * @dev nextUpdateBlockNumber is initialized to 0 for the latest update - */ - struct QuorumBitmapUpdate { - uint32 updateBlockNumber; - uint32 nextUpdateBlockNumber; - uint192 quorumBitmap; - } - - /// @notice Returns the operator struct for the given `operator` - function getOperator(address operator) external view returns (Operator memory); - - /// @notice Returns the operatorId for the given `operator` - function getOperatorId(address operator) external view returns (bytes32); - - /// @notice Returns the operator address for the given `operatorId` - function getOperatorFromId(bytes32 operatorId) external view returns (address operator); - - /// @notice Returns the status for the given `operator` - function getOperatorStatus(address operator) external view returns (IRegistryCoordinator.OperatorStatus); - - /// @notice Returns the indices of the quorumBitmaps for the provided `operatorIds` at the given `blockNumber` - function getQuorumBitmapIndicesByOperatorIdsAtBlockNumber(uint32 blockNumber, bytes32[] memory operatorIds) external view returns (uint32[] memory); - - /** - * @notice Returns the quorum bitmap for the given `operatorId` at the given `blockNumber` via the `index` - * @dev reverts if `index` is incorrect - */ - function getQuorumBitmapByOperatorIdAtBlockNumberByIndex(bytes32 operatorId, uint32 blockNumber, uint256 index) external view returns (uint192); - - /// @notice Returns the `index`th entry in the operator with `operatorId`'s bitmap history - function getQuorumBitmapUpdateByOperatorIdByIndex(bytes32 operatorId, uint256 index) external view returns (QuorumBitmapUpdate memory); - - /// @notice Returns the current quorum bitmap for the given `operatorId` - function getCurrentQuorumBitmapByOperatorId(bytes32 operatorId) external view returns (uint192); - - /// @notice Returns the length of the quorum bitmap history for the given `operatorId` - function getQuorumBitmapUpdateByOperatorIdLength(bytes32 operatorId) external view returns (uint256); - - /// @notice Returns the registry at the desired index - function registries(uint256) external view returns (address); - - /// @notice Returns the number of registries - function numRegistries() external view returns (uint256); - - /** - * @notice Registers msg.sender as an operator with the middleware - * @param quorumNumbers are the bytes representing the quorum numbers that the operator is registering for - * @param registrationData is the data that is decoded to get the operator's registration information - */ - function registerOperatorWithCoordinator(bytes memory quorumNumbers, bytes calldata registrationData) external; - - /** - * @notice Deregisters the msg.sender as an operator from the middleware - * @param quorumNumbers are the bytes representing the quorum numbers that the operator is registered for - * @param deregistrationData is the the data that is decoded to get the operator's deregistration information - */ - function deregisterOperatorWithCoordinator(bytes calldata quorumNumbers, bytes calldata deregistrationData) external; -} \ No newline at end of file +import "eigenlayer-contracts/src/contracts/interfaces/IRegistryCoordinator.sol"; diff --git a/src/interfaces/IServiceManager.sol b/src/interfaces/IServiceManager.sol index 5a36f7da..378f82b8 100644 --- a/src/interfaces/IServiceManager.sol +++ b/src/interfaces/IServiceManager.sol @@ -1,39 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ISlasher} from "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; - -/** - * @title Interface for a `ServiceManager`-type contract. - * @author Layr Labs, Inc. - * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service - */ -interface IServiceManager { - - // ServiceManager proxies to the slasher - function slasher() external view returns (ISlasher); - - /// @notice Returns the current 'taskNumber' for the middleware - function taskNumber() external view returns (uint32); - - /// @notice function that causes the ServiceManager to freeze the operator on EigenLayer, through a call to the Slasher contract - /// @dev this function should contain slashing logic, to make sure operators are not needlessly being slashed - function freezeOperator(address operator) external; - - /// @notice proxy call to the slasher, recording an initial stake update (on operator registration) - function recordFirstStakeUpdate(address operator, uint32 serveUntilBlock) external; - - /// @notice proxy call to the slasher, recording a stake update - function recordStakeUpdate(address operator, uint32 updateBlock, uint32 serveUntilBlock, uint256 prevElement) external; - - /// @notice proxy call to the slasher, recording a final stake update (on operator deregistration) - function recordLastStakeUpdateAndRevokeSlashingAbility(address operator, uint32 serveUntilBlock) external; - - /// @notice Returns the latest block until which operators must serve (could be in the past or future). - /// @dev this should be called and the response passed to the recordStakeUpdate functionss' serveUntilBlock parameter - function latestServeUntilBlock() external view returns (uint32); - - /// @notice required since the registry contract will call this function to permission its upgrades to be done by the same owner as the service manager - function owner() external view returns (address); -} +import "eigenlayer-contracts/src/contracts/interfaces/IServiceManager.sol"; diff --git a/src/interfaces/IStakeRegistry.sol b/src/interfaces/IStakeRegistry.sol index 4420d58d..713df01e 100644 --- a/src/interfaces/IStakeRegistry.sol +++ b/src/interfaces/IStakeRegistry.sol @@ -1,160 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity =0.8.12; -import {IRegistry} from "src/interfaces/IRegistry.sol"; - -/** - * @title Interface for a `Registry` that keeps track of stakes of operators for up to 256 quorums. - * @author Layr Labs, Inc. - */ -interface IStakeRegistry is IRegistry { - // EVENTS - /// @notice emitted whenever the stake of `operator` is updated - event StakeUpdate( - bytes32 indexed operatorId, - uint8 quorumNumber, - uint96 stake - ); - - // DATA STRUCTURES - - /// @notice struct used to store the stakes of an individual operator or the sum of all operators' stakes, for storage - struct OperatorStakeUpdate { - // the block number at which the stake amounts were updated and stored - uint32 updateBlockNumber; - // the block number at which the *next update* occurred. - /// @notice This entry has the value **0** until another update takes place. - uint32 nextUpdateBlockNumber; - // stake weight for the quorum - uint96 stake; - } - - // EVENTS - event MinimumStakeForQuorumUpdated(uint8 indexed quorumNumber, uint96 minimumStake); - - /** - * @notice Registers the `operator` with `operatorId` for the specified `quorumNumbers`. - * @param operator The address of the operator to register. - * @param operatorId The id of the operator to register. - * @param quorumNumbers The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber. - * @dev access restricted to the RegistryCoordinator - * @dev Preconditions (these are assumed, not validated in this contract): - * 1) `quorumNumbers` has no duplicates - * 2) `quorumNumbers.length` != 0 - * 3) `quorumNumbers` is ordered in ascending order - * 4) the operator is not already registered - */ - function registerOperator(address operator, bytes32 operatorId, bytes memory quorumNumbers) external; - - /** - * @notice Deregisters the operator with `operatorId` for the specified `quorumNumbers`. - * @param operatorId The id of the operator to deregister. - * @param quorumNumbers The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber. - * @dev access restricted to the RegistryCoordinator - * @dev Preconditions (these are assumed, not validated in this contract): - * 1) `quorumNumbers` has no duplicates - * 2) `quorumNumbers.length` != 0 - * 3) `quorumNumbers` is ordered in ascending order - * 4) the operator is not already deregistered - * 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for - */ - function deregisterOperator(bytes32 operatorId, bytes memory quorumNumbers) external; - - /// @notice In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]` - function minimumStakeForQuorum(uint256 quorumNumber) external view returns (uint96); - - /** - * @notice Returns the entire `operatorIdToStakeHistory[operatorId][quorumNumber]` array. - * @param operatorId The id of the operator of interest. - * @param quorumNumber The quorum number to get the stake for. - */ - function getOperatorIdToStakeHistory(bytes32 operatorId, uint8 quorumNumber) external view returns (OperatorStakeUpdate[] memory); - - function getLengthOfTotalStakeHistoryForQuorum(uint8 quorumNumber) external view returns (uint256); - - /** - * @notice Returns the `index`-th entry in the dynamic array of total stake, `totalStakeHistory` for quorum `quorumNumber`. - * @param quorumNumber The quorum number to get the stake for. - * @param index Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`. - */ - function getTotalStakeUpdateForQuorumFromIndex(uint8 quorumNumber, uint256 index) external view returns (OperatorStakeUpdate memory); - - /// @notice Returns the indices of the operator stakes for the provided `quorumNumber` at the given `blockNumber` - function getStakeUpdateIndexForOperatorIdForQuorumAtBlockNumber(bytes32 operatorId, uint8 quorumNumber, uint32 blockNumber) - external - view - returns (uint32); - - /// @notice Returns the indices of the total stakes for the provided `quorumNumbers` at the given `blockNumber` - function getTotalStakeIndicesByQuorumNumbersAtBlockNumber(uint32 blockNumber, bytes calldata quorumNumbers) external view returns(uint32[] memory) ; - - /** - * @notice Returns the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array. - * @param quorumNumber The quorum number to get the stake for. - * @param operatorId The id of the operator of interest. - * @param index Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`. - * @dev Function will revert if `index` is out-of-bounds. - */ - function getStakeUpdateForQuorumFromOperatorIdAndIndex(uint8 quorumNumber, bytes32 operatorId, uint256 index) - external - view - returns (OperatorStakeUpdate memory); - - /** - * @notice Returns the most recent stake weight for the `operatorId` for a certain quorum - * @dev Function returns an OperatorStakeUpdate struct with **every entry equal to 0** in the event that the operator has no stake history - */ - function getMostRecentStakeUpdateByOperatorId(bytes32 operatorId, uint8 quorumNumber) external view returns (OperatorStakeUpdate memory); - - /** - * @notice Returns the stake weight corresponding to `operatorId` for quorum `quorumNumber`, at the - * `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array if the entry - * corresponds to the operator's stake at `blockNumber`. Reverts otherwise. - * @param quorumNumber The quorum number to get the stake for. - * @param operatorId The id of the operator of interest. - * @param index Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`. - * @param blockNumber Block number to make sure the stake is from. - * @dev Function will revert if `index` is out-of-bounds. - * @dev used the BLSSignatureChecker to get past stakes of signing operators - */ - function getStakeForQuorumAtBlockNumberFromOperatorIdAndIndex(uint8 quorumNumber, uint32 blockNumber, bytes32 operatorId, uint256 index) - external - view - returns (uint96); - - /** - * @notice Returns the total stake weight for quorum `quorumNumber`, at the `index`-th entry in the - * `totalStakeHistory[quorumNumber]` array if the entry corresponds to the total stake at `blockNumber`. - * Reverts otherwise. - * @param quorumNumber The quorum number to get the stake for. - * @param index Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`. - * @param blockNumber Block number to make sure the stake is from. - * @dev Function will revert if `index` is out-of-bounds. - * @dev used the BLSSignatureChecker to get past stakes of signing operators - */ - function getTotalStakeAtBlockNumberFromIndex(uint8 quorumNumber, uint32 blockNumber, uint256 index) external view returns (uint96); - - /** - * @notice Returns the most recent stake weight for the `operatorId` for quorum `quorumNumber` - * @dev Function returns weight of **0** in the event that the operator has no stake history - */ - function getCurrentOperatorStakeForQuorum(bytes32 operatorId, uint8 quorumNumber) external view returns (uint96); - - /// @notice Returns the stake of the operator for the provided `quorumNumber` at the given `blockNumber` - function getStakeForOperatorIdForQuorumAtBlockNumber(bytes32 operatorId, uint8 quorumNumber, uint32 blockNumber) - external - view - returns (uint96); - - /** - * @notice Returns the stake weight from the latest entry in `_totalStakeHistory` for quorum `quorumNumber`. - * @dev Will revert if `_totalStakeHistory[quorumNumber]` is empty. - */ - function getCurrentTotalStakeForQuorum(uint8 quorumNumber) external view returns (uint96); - - /** - * @notice Used for updating information on deposits of nodes. - * @param operators are the addresses of the operators whose stake information is getting updated - */ - function updateStakes(address[] memory operators) external; -} +import "eigenlayer-contracts/src/contracts/interfaces/IStakeRegistry.sol"; diff --git a/src/interfaces/IVoteWeigher.sol b/src/interfaces/IVoteWeigher.sol index 1059eccc..4ae103cb 100644 --- a/src/interfaces/IVoteWeigher.sol +++ b/src/interfaces/IVoteWeigher.sol @@ -1,96 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; -import "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; -import "src/interfaces/IServiceManager.sol"; -import "eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol"; -import "eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol"; - -/** - * @title Interface for a `VoteWeigher`-type contract. - * @author Layr Labs, Inc. - * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service - * @notice Note that `NUMBER_OF_QUORUMS` is expected to remain constant, as suggested by its uppercase formatting. - */ -interface IVoteWeigher { - /// @notice emitted when a new quorum is created - event QuorumCreated(uint8 indexed quorumNumber); - /// @notice emitted when `strategy` has been added to the array at `strategiesConsideredAndMultipliers[quorumNumber]` - event StrategyAddedToQuorum(uint8 indexed quorumNumber, IStrategy strategy); - /// @notice emitted when `strategy` has removed from the array at `strategiesConsideredAndMultipliers[quorumNumber]` - event StrategyRemovedFromQuorum(uint8 indexed quorumNumber, IStrategy strategy); - /// @notice emitted when `strategy` has its `multiplier` updated in the array at `strategiesConsideredAndMultipliers[quorumNumber]` - event StrategyMultiplierUpdated(uint8 indexed quorumNumber, IStrategy strategy, uint256 multiplier); - - /** - * @notice In weighing a particular strategy, the amount of underlying asset for that strategy is - * multiplied by its multiplier, then divided by WEIGHTING_DIVISOR - */ - struct StrategyAndWeightingMultiplier { - IStrategy strategy; - uint96 multiplier; - } - - /// @notice Constant used as a divisor in calculating weights. - function WEIGHTING_DIVISOR() external pure returns (uint256); - - /// @notice Returns the EigenLayer strategy manager contract. - function strategyManager() external view returns (IStrategyManager); - /// @notice Returns the EigenLayer slasher contract. - function slasher() external view returns (ISlasher); - /// @notice Returns the EigenLayer delegation manager contract. - function delegation() external view returns (IDelegationManager); - /// @notice Returns the AVS service manager contract. - function serviceManager() external view returns (IServiceManager); - - /** - * @notice This function computes the total weight of the @param operator in the quorum @param quorumNumber. - * @dev reverts in the case that `quorumNumber` is greater than or equal to `quorumCount` - */ - function weightOfOperatorForQuorum(uint8 quorumNumber, address operator) external view returns (uint96); - - /// @notice Number of quorums that are being used by the middleware. - function quorumCount() external view returns (uint16); - - /// @notice Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber` - function strategyAndWeightingMultiplierForQuorumByIndex(uint8 quorumNumber, uint256 index) external view returns (StrategyAndWeightingMultiplier memory); - - /// @notice Create a new quorum and add the strategies and their associated weights to the quorum. - function createQuorum( - StrategyAndWeightingMultiplier[] memory _strategiesConsideredAndMultipliers - ) external; - - /// @notice Adds new strategies and the associated multipliers to the @param quorumNumber. - function addStrategiesConsideredAndMultipliers( - uint8 quorumNumber, - StrategyAndWeightingMultiplier[] memory _newStrategiesConsideredAndMultipliers - ) external; - - /** - * @notice This function is used for removing strategies and their associated weights from the - * mapping strategiesConsideredAndMultipliers for a specific @param quorumNumber. - * @dev higher indices should be *first* in the list of @param indicesToRemove, since otherwise - * the removal of lower index entries will cause a shift in the indices of the other strategiesToRemove - */ - function removeStrategiesConsideredAndMultipliers( - uint8 quorumNumber, - uint256[] calldata indicesToRemove - ) external; - - /** - * @notice This function is used for modifying the weights of strategies that are already in the - * mapping strategiesConsideredAndMultipliers for a specific - * @param quorumNumber is the quorum number to change the strategy for - * @param strategyIndices are the indices of the strategies to change - * @param newMultipliers are the new multipliers for the strategies - */ - function modifyStrategyWeights( - uint8 quorumNumber, - uint256[] calldata strategyIndices, - uint96[] calldata newMultipliers - ) external; - - /// @notice Returns the length of the dynamic array stored in `strategiesConsideredAndMultipliers[quorumNumber]`. - function strategiesConsideredAndMultipliersLength(uint8 quorumNumber) external view returns (uint256); -} +import "eigenlayer-contracts/src/contracts/interfaces/IVoteWeigher.sol"; From 84b5a5df09b90cd1a8958441f7b637ff0595c2df Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 20 Oct 2023 12:32:01 -0400 Subject: [PATCH 06/11] add view methods for compatability with core temporarily --- src/VoteWeigherBase.sol | 6 ++++++ test/harnesses/StakeRegistryHarness.sol | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/VoteWeigherBase.sol b/src/VoteWeigherBase.sol index 0be3d60e..24e06faf 100644 --- a/src/VoteWeigherBase.sol +++ b/src/VoteWeigherBase.sol @@ -192,6 +192,12 @@ contract VoteWeigherBase is VoteWeigherBaseStorage { return strategiesConsideredAndMultipliers[quorumNumber][index]; } + + /// TODO remove when core gets updated + function weightOfOperatorForQuorumView( + uint8 quorumNumber, + address operator + ) public virtual view validQuorumNumber(quorumNumber) returns (uint96) {} /** * @notice This function computes the total weight of the @param operator in the quorum @param quorumNumber. * @dev reverts in the case that `quorumNumber` is greater than or equal to `quorumCount` diff --git a/test/harnesses/StakeRegistryHarness.sol b/test/harnesses/StakeRegistryHarness.sol index 4cc8be9d..1a61a47b 100644 --- a/test/harnesses/StakeRegistryHarness.sol +++ b/test/harnesses/StakeRegistryHarness.sol @@ -31,6 +31,11 @@ contract StakeRegistryHarness is StakeRegistry { return _weightOfOperatorForQuorum[quorumNumber][operator]; } + /// TODO remove when core gets updated + function weightOfOperatorForQuorumView(uint8 quorumNumber, address operator) public override view returns(uint96) { + return _weightOfOperatorForQuorum[quorumNumber][operator]; + } + // mocked function so we can set this arbitrarily without having to mock other elements function setOperatorWeight(uint8 quorumNumber, address operator, uint96 weight) external { _weightOfOperatorForQuorum[quorumNumber][operator] = weight; From 1aacc07ec465dbd433d848925313bb0dda687d1a Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 20 Oct 2023 12:54:23 -0400 Subject: [PATCH 07/11] IBLSRegistry --- src/interfaces/IBLSRegistry.sol | 68 +-------------------------------- 1 file changed, 1 insertion(+), 67 deletions(-) diff --git a/src/interfaces/IBLSRegistry.sol b/src/interfaces/IBLSRegistry.sol index 1d366b5a..6e787968 100644 --- a/src/interfaces/IBLSRegistry.sol +++ b/src/interfaces/IBLSRegistry.sol @@ -1,70 +1,4 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; -import "src/interfaces/IQuorumRegistry.sol"; -import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol"; - - -/** - * @title Minimal interface extension to `IQuorumRegistry`. - * @author Layr Labs, Inc. - * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service - * @notice Adds BLS-specific functions to the base interface. - */ -interface IBLSRegistry is IQuorumRegistry { - /// @notice Data structure used to track the history of the Aggregate Public Key of all operators - struct ApkUpdate { - // keccak256(apk_x0, apk_x1, apk_y0, apk_y1) - bytes32 apkHash; - // block number at which the update occurred - uint32 blockNumber; - } - - // EVENTS - /** - * @notice Emitted upon the registration of a new operator for the middleware - * @param operator Address of the new operator - * @param pkHash The keccak256 hash of the operator's public key - * @param pk The operator's public key itself - * @param apkHashIndex The index of the latest (i.e. the new) APK update - * @param apkHash The keccak256 hash of the new Aggregate Public Key - */ - event Registration( - address indexed operator, - bytes32 pkHash, - BN254.G1Point pk, - uint32 apkHashIndex, - bytes32 apkHash, - string socket - ); - - /// @notice Emitted when the `operatorWhitelister` role is transferred. - event OperatorWhitelisterTransferred(address previousAddress, address newAddress); - - /** - * @notice get hash of a historical aggregated public key corresponding to a given index; - * called by checkSignatures in BLSSignatureChecker.sol. - */ - function getCorrectApkHash(uint256 index, uint32 blockNumber) external returns (bytes32); - - /// @notice returns the `ApkUpdate` struct at `index` in the list of APK updates - function apkUpdates(uint256 index) external view returns (ApkUpdate memory); - - /// @notice returns the APK hash that resulted from the `index`th APK update - function apkHashes(uint256 index) external view returns (bytes32); - - /// @notice returns the block number at which the `index`th APK update occurred - function apkUpdateBlockNumbers(uint256 index) external view returns (uint32); - - function operatorWhitelister() external view returns (address); - - function operatorWhitelistEnabled() external view returns (bool); - - function whitelisted(address) external view returns (bool); - - function setOperatorWhitelistStatus(bool _operatorWhitelistEnabled) external; - - function addToOperatorWhitelist(address[] calldata) external; - - function removeFromWhitelist(address[] calldata operators) external; -} +import "eigenlayer-contracts/src/contracts/interfaces/IBLSRegistry.sol"; From 43780f401414b190febda3c83f62b6c1783ca148 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 20 Oct 2023 14:00:14 -0400 Subject: [PATCH 08/11] move back to core --- script/DeployOpenEigenLayer.s.sol | 204 ------------------------------ 1 file changed, 204 deletions(-) delete mode 100644 script/DeployOpenEigenLayer.s.sol diff --git a/script/DeployOpenEigenLayer.s.sol b/script/DeployOpenEigenLayer.s.sol deleted file mode 100644 index 0e852a88..00000000 --- a/script/DeployOpenEigenLayer.s.sol +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity =0.8.12; - -import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; -import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; - -import "eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol"; -import "eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol"; - -import "eigenlayer-contracts/src/contracts/core/StrategyManager.sol"; -import "eigenlayer-contracts/src/contracts/core/Slasher.sol"; -import "eigenlayer-contracts/src/contracts/core/DelegationManager.sol"; - -import "eigenlayer-contracts/src/contracts/strategies/StrategyBaseTVLLimits.sol"; - -import "eigenlayer-contracts/src/contracts/pods/EigenPod.sol"; -import "eigenlayer-contracts/src/contracts/pods/EigenPodManager.sol"; -import "eigenlayer-contracts/src/contracts/pods/DelayedWithdrawalRouter.sol"; - -import "eigenlayer-contracts/src/contracts/permissions/PauserRegistry.sol"; -import "src/BLSPublicKeyCompendium.sol"; - -import "eigenlayer-contracts/src/test/mocks/EmptyContract.sol"; -import "eigenlayer-contracts/src/test/mocks/ETHDepositMock.sol"; - -import "forge-std/Script.sol"; -import "forge-std/Test.sol"; - -// # To load the variables in the .env file -// source .env - -// # To deploy and verify our contract -// forge script script/M1_Deploy.s.sol:Deployer_M1 --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv -contract DeployOpenEigenLayer is Script, Test { - Vm cheats = Vm(HEVM_ADDRESS); - - // struct used to encode token info in config file - struct StrategyConfig { - uint256 maxDeposits; - uint256 maxPerDeposit; - address tokenAddress; - string tokenSymbol; - } - - // EigenLayer Contracts - ProxyAdmin public eigenLayerProxyAdmin; - PauserRegistry public eigenLayerPauserReg; - Slasher public slasher; - Slasher public slasherImplementation; - DelegationManager public delegation; - DelegationManager public delegationImplementation; - StrategyManager public strategyManager; - StrategyManager public strategyManagerImplementation; - EigenPodManager public eigenPodManager; - EigenPodManager public eigenPodManagerImplementation; - DelayedWithdrawalRouter public delayedWithdrawalRouter; - DelayedWithdrawalRouter public delayedWithdrawalRouterImplementation; - UpgradeableBeacon public eigenPodBeacon; - EigenPod public eigenPodImplementation; - StrategyBase public baseStrategyImplementation; - - EmptyContract public emptyContract; - - // the ETH2 deposit contract -- if not on mainnet, we deploy a mock as stand-in - IETHPOSDeposit public ethPOSDeposit; - - // strategies deployed - StrategyBaseTVLLimits[] public deployedStrategyArray; - - function _deployEigenLayer(address executorMultisig, address operationsMultisig, address pauserMultisig, StrategyConfig[] memory strategyConfigs) internal { - require(executorMultisig != address(0), "executorMultisig address not configured correctly!"); - require(operationsMultisig != address(0), "operationsMultisig address not configured correctly!"); - - // deploy proxy admin for ability to upgrade proxy contracts - eigenLayerProxyAdmin = new ProxyAdmin(); - - //deploy pauser registry - { - address[] memory pausers = new address[](3); - pausers[0] = executorMultisig; - pausers[1] = operationsMultisig; - pausers[2] = pauserMultisig; - eigenLayerPauserReg = new PauserRegistry(pausers, executorMultisig); - } - - /** - * First, deploy upgradeable proxy contracts that **will point** to the implementations. Since the implementation contracts are - * not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code. - */ - emptyContract = new EmptyContract(); - delegation = DelegationManager( - address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) - ); - strategyManager = StrategyManager( - address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) - ); - slasher = Slasher( - address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) - ); - eigenPodManager = EigenPodManager( - address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) - ); - delayedWithdrawalRouter = DelayedWithdrawalRouter( - address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), "")) - ); - - // ETH POS deposit is 0 address - eigenPodImplementation = new EigenPod( - ethPOSDeposit, - delayedWithdrawalRouter, - eigenPodManager, - // uint64(MAX_VALIDATOR_BALANCE_GWEI), - uint64(31 gwei), - // uint64(EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI) - uint64(0.75 gwei), - 1000 // temp genesis time - ); - - eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation)); - - // Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs - delegationImplementation = new DelegationManager(strategyManager, slasher, eigenPodManager); - strategyManagerImplementation = new StrategyManager(delegation, eigenPodManager, slasher); - slasherImplementation = new Slasher(strategyManager, delegation); - eigenPodManagerImplementation = new EigenPodManager(ethPOSDeposit, eigenPodBeacon, strategyManager, slasher, delegation); - delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter(eigenPodManager); - - // Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them. - eigenLayerProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy(payable(address(delegation))), - address(delegationImplementation), - abi.encodeWithSelector( - DelegationManager.initialize.selector, - executorMultisig, - eigenLayerPauserReg, - 0 - ) - ); - eigenLayerProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy(payable(address(strategyManager))), - address(strategyManagerImplementation), - abi.encodeWithSelector( - StrategyManager.initialize.selector, - executorMultisig, - operationsMultisig, - eigenLayerPauserReg, - 0, - 0 - ) - ); - eigenLayerProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy(payable(address(slasher))), - address(slasherImplementation), - abi.encodeWithSelector( - Slasher.initialize.selector, - executorMultisig, - eigenLayerPauserReg, - 0 - ) - ); - eigenLayerProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy(payable(address(eigenPodManager))), - address(eigenPodManagerImplementation), - abi.encodeWithSelector( - EigenPodManager.initialize.selector, - type(uint256).max, - IBeaconChainOracle(address(0)), - executorMultisig, - eigenLayerPauserReg, - 0 - ) - ); - eigenLayerProxyAdmin.upgradeAndCall( - TransparentUpgradeableProxy(payable(address(delayedWithdrawalRouter))), - address(delayedWithdrawalRouterImplementation), - abi.encodeWithSelector(DelayedWithdrawalRouter.initialize.selector, - executorMultisig, - eigenLayerPauserReg, - 0, - 0 - ) - ); - - // deploy StrategyBaseTVLLimits contract implementation - baseStrategyImplementation = new StrategyBaseTVLLimits(strategyManager); - // create upgradeable proxies that each point to the implementation and initialize them - for (uint256 i = 0; i < strategyConfigs.length; ++i) { - deployedStrategyArray.push( - StrategyBaseTVLLimits(address( - new TransparentUpgradeableProxy( - address(baseStrategyImplementation), - address(eigenLayerProxyAdmin), - abi.encodeWithSelector(StrategyBaseTVLLimits.initialize.selector, strategyConfigs[i].maxPerDeposit, strategyConfigs[i].maxDeposits, IERC20(strategyConfigs[i].tokenAddress), eigenLayerPauserReg) - ) - )) - ); - } - - eigenLayerProxyAdmin.transferOwnership(executorMultisig); - eigenPodBeacon.transferOwnership(executorMultisig); - } -} From 02fea8f83517673f28048e90c083fc9c1e076057 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 20 Oct 2023 14:22:18 -0400 Subject: [PATCH 09/11] add remappings.txt --- remappings.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 remappings.txt diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..831928f9 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,8 @@ +@openzeppelin-upgrades/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/ +@openzeppelin/=lib/eigenlayer-contracts/lib/openzeppelin-contracts/ +ds-test/=lib/forge-std/lib/ds-test/src/ +eigenlayer-contracts/=lib/eigenlayer-contracts/ +erc4626-tests/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ +forge-std/=lib/forge-std/src/ +openzeppelin-contracts-upgradeable/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/ +openzeppelin-contracts/=lib/eigenlayer-contracts/lib/openzeppelin-contracts/ From 458777b3da67371e916e1a3bbc0b6210838f5811 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 23 Oct 2023 10:35:17 -0400 Subject: [PATCH 10/11] forge install: ds-test --- .gitmodules | 3 +++ lib/ds-test | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/ds-test diff --git a/.gitmodules b/.gitmodules index 7b9862a2..635af195 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/eigenlayer-contracts"] path = lib/eigenlayer-contracts url = https://github.com/Layr-labs/eigenlayer-contracts +[submodule "lib/ds-test"] + path = lib/ds-test + url = https://github.com/dapphub/ds-test diff --git a/lib/ds-test b/lib/ds-test new file mode 160000 index 00000000..e282159d --- /dev/null +++ b/lib/ds-test @@ -0,0 +1 @@ +Subproject commit e282159d5170298eb2455a6c05280ab5a73a4ef0 From 8ca6faaed3ba3abeeb5baf41c158c1279510d0a0 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 23 Oct 2023 10:36:58 -0400 Subject: [PATCH 11/11] add ds-test to remappings --- remappings.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/remappings.txt b/remappings.txt index 831928f9..26950b6a 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,8 +1,7 @@ @openzeppelin-upgrades/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/ @openzeppelin/=lib/eigenlayer-contracts/lib/openzeppelin-contracts/ -ds-test/=lib/forge-std/lib/ds-test/src/ +ds-test/=lib/ds-test/src/ eigenlayer-contracts/=lib/eigenlayer-contracts/ -erc4626-tests/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ forge-std/=lib/forge-std/src/ openzeppelin-contracts-upgradeable/=lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable/ openzeppelin-contracts/=lib/eigenlayer-contracts/lib/openzeppelin-contracts/