diff --git a/contracts/README.md b/contracts/README.md index a472253d0..49cc07a94 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -48,6 +48,26 @@ This changelog tracks "core" contract deployments on the mev-commit chain. This | July 22nd 2025, 20:10:39 UTC | BidderRegistry | BidderRegistryV2 | `v1.1.5` in `release/v1.1.x`. | | July 22nd 2025, 20:10:39 UTC | ProviderRegistry | ProviderRegistryV2 | `v1.1.5` in `release/v1.1.x`. | +## Hoodi Testnet (L1) Contract Changelog + +This changelog tracks deployments of **Hoodi Testnet** contracts. This changelog is only valid from the `main` branch. + +### Current Deployments + +| Contract | Proxy Address | Initial Commit | +|-----------------------|----------------------------------------------|---------------------| +| ValidatorOptInRouter | `0xa380ba6d6083a4Cb2a3B62b0a81Ea8727861c13e` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' | +| VanillaRegistry | `0x536f0792c5d5ed592e67a9260606c85f59c312f0` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' | +| MevCommitAVS | `0xdF8649d298ad05f019eE4AdBD6210867B8AB225F` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' | +| MevCommitMiddleware | `0x8E847EC4a36c8332652aB3b2B7D5c54dE29c7fde` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' | + +### Upgrade History + +| Timestamp (UTC) | Contract | New Impl Version | Commmit | +|-----------------------------|---------------------|-----------------------|-------------------| +| N/A | | | | + + ## L1 Deployer CLI > **After completing any L1 deployment, immediately record it in the “Current Deployments” table above.** diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 1048f5d7a..1ff3b09e5 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -9,4 +9,4 @@ cache_path = 'cache_forge' ffi = true ast = true build_info = true -extra_output = ["storageLayout"] +extra_output = ["storageLayout"] \ No newline at end of file diff --git a/contracts/l1-deployer-cli.sh b/contracts/l1-deployer-cli.sh index 4540cc92d..8afe9395b 100755 --- a/contracts/l1-deployer-cli.sh +++ b/contracts/l1-deployer-cli.sh @@ -26,7 +26,7 @@ help() { echo " deploy-router Deploy and verify the ValidatorOptInRouter contract to L1." echo echo "Required Options:" - echo " --chain, -c Specify the chain to deploy to ('mainnet' or 'holesky')." + echo " --chain, -c Specify the chain to deploy to ('mainnet', 'holesky', or 'hoodi')." echo echo "Wallet Options (exactly one required):" echo " --keystore Use a keystore for deployment." @@ -128,8 +128,8 @@ parse_args() { exit 1 fi chain="$2" - if [[ "$chain" != "mainnet" && "$chain" != "holesky" ]]; then - echo "Error: Unknown chain '$chain'. Valid options are 'mainnet' or 'holesky'." + if [[ "$chain" != "mainnet" && "$chain" != "holesky" && "$chain" != "hoodi" ]]; then + echo "Error: Unknown chain '$chain'. Valid options are 'mainnet', 'holesky', or hoodi." exit 1 fi shift 2 @@ -248,6 +248,9 @@ get_chain_params() { elif [[ "$chain" == "holesky" ]]; then chain_id=17000 deploy_contract="DeployHolesky" + elif [[ "$chain" == "hoodi" ]]; then + chain_id=560048 + deploy_contract="DeployHoodi" fi } diff --git a/contracts/scripts/validator-registry/DeployValidatorOptInRouter.s.sol b/contracts/scripts/validator-registry/DeployValidatorOptInRouter.s.sol index 0c93443e9..0a23b9a10 100644 --- a/contracts/scripts/validator-registry/DeployValidatorOptInRouter.s.sol +++ b/contracts/scripts/validator-registry/DeployValidatorOptInRouter.s.sol @@ -74,3 +74,25 @@ contract DeployHolesky is BaseDeploy { vm.stopBroadcast(); } } + +contract DeployHoodi is BaseDeploy { + address constant public VANILLA_REGISTRY = 0x536F0792c5D5Ed592e67a9260606c85F59C312F0; + address constant public MEV_COMMIT_AVS = 0xdF8649d298ad05f019eE4AdBD6210867B8AB225F; + address constant public MEV_COMMIT_MIDDLEWARE = 0x8E847EC4a36c8332652aB3b2B7D5c54dE29c7fde; + + //This is the most important field. On mainnet it'll be the primev multisig. + address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a; + + function run() external { + require(block.chainid == 560048, "must deploy on Hoodi"); + + vm.startBroadcast(); + deployValidatorOptInRouter( + VANILLA_REGISTRY, + MEV_COMMIT_AVS, + MEV_COMMIT_MIDDLEWARE, + OWNER + ); + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/validator-registry/DeployVanillaRegistry.s.sol b/contracts/scripts/validator-registry/DeployVanillaRegistry.s.sol index 996437610..5ccefa0ec 100644 --- a/contracts/scripts/validator-registry/DeployVanillaRegistry.s.sol +++ b/contracts/scripts/validator-registry/DeployVanillaRegistry.s.sol @@ -82,3 +82,21 @@ contract DeployAnvil is BaseDeploy { vm.stopBroadcast(); } } + +contract DeployHoodi is BaseDeploy { + uint256 constant public MIN_STAKE = 0.0001 ether; // 10k vals = 1 ETH cost + address constant public SLASH_ORACLE = 0x1623fE21185c92BB43bD83741E226288B516134a; + address constant public SLASH_RECEIVER = 0x1623fE21185c92BB43bD83741E226288B516134a; + uint256 constant public UNSTAKE_PERIOD_BLOCKS = 32 * 3; // 2 epoch finalization time + settlement buffer + uint256 constant public PAYOUT_PERIOD = 10000; // 10k * 12s = 1.39 days + + // This is the most important field. On mainnet it'll be the primev multisig. + address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a; + + function run() external { + require(block.chainid == 560048, "must deploy on Hoodi"); + vm.startBroadcast(); + deployVanillaRegistry(MIN_STAKE, SLASH_ORACLE, SLASH_RECEIVER, UNSTAKE_PERIOD_BLOCKS, PAYOUT_PERIOD, OWNER); + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/validator-registry/avs/DeployAVS.s.sol b/contracts/scripts/validator-registry/avs/DeployAVS.s.sol index 35b0c4e0d..ed13cb1ed 100644 --- a/contracts/scripts/validator-registry/avs/DeployAVS.s.sol +++ b/contracts/scripts/validator-registry/avs/DeployAVS.s.sol @@ -13,8 +13,7 @@ import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/ import {IEigenPodManager} from "eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol"; import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol"; import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol"; -import {EigenHoleskyReleaseConsts} from "./ReleaseAddrConsts.sol"; -import {EigenMainnetReleaseConsts} from "./ReleaseAddrConsts.sol"; +import {EigenHoodiReleaseConsts, EigenHoleskyReleaseConsts, EigenMainnetReleaseConsts} from "./ReleaseAddrConsts.sol"; import {MainnetConstants} from "../../MainnetConstants.sol"; contract BaseDeploy is Script { @@ -166,3 +165,48 @@ contract DeployHolesky is BaseDeploy { vm.stopBroadcast(); } } + +contract DeployHoodi is BaseDeploy { + // This is the most important field. On mainnet it'll be the primev multisig. + address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a; + + IDelegationManager constant public DELEGATION_MANAGER = IDelegationManager(EigenHoodiReleaseConsts.DELEGATION_MANAGER); + IEigenPodManager constant public EIGENPOD_MANAGER = IEigenPodManager(EigenHoodiReleaseConsts.EIGENPOD_MANAGER); + IStrategyManager constant public STRATEGY_MANAGER = IStrategyManager(EigenHoodiReleaseConsts.STRATEGY_MANAGER); + IAVSDirectory constant public AVS_DIRECTORY = IAVSDirectory(EigenHoodiReleaseConsts.AVS_DIRECTORY); + address constant public FREEZE_ORACLE = 0x1623fE21185c92BB43bD83741E226288B516134a; // Temporary freeze oracle + uint256 constant public UNFREEZE_FEE = 0.1 ether; + address constant public UNFREEZE_RECEIVER = 0x1623fE21185c92BB43bD83741E226288B516134a; // Temporary unfreezeReceiver + uint256 constant public UNFREEZE_PERIOD_BLOCKS = 12000; // ~ 1 day + uint256 constant public OPERATOR_DEREG_PERIOD_BLOCKS = 12000; // ~ 1 day + uint256 constant public VALIDATOR_DEREG_PERIOD_BLOCKS = 32 * 3; // 2 epoch finalization time + settlement buffer + uint256 constant public LST_RESTARKER_DEREG_PERIOD_BLOCKS = 12000; // ~ 1 day + + function run() external { + require(block.chainid == 560048, "must deploy on Hoodi"); + + address[] memory restakeableStrategies = new address[](5); + restakeableStrategies[0] = EigenHoodiReleaseConsts.STRATEGY_BASE_STETH; + restakeableStrategies[1] = EigenHoodiReleaseConsts.STRATEGY_BASE_WETH; + restakeableStrategies[3] = EigenHoodiReleaseConsts.STRATEGY_BASE_EIGEN; + restakeableStrategies[4] = EigenHoodiReleaseConsts.BEACON_CHAIN_ETH; + + vm.startBroadcast(); + deployMevCommitAVS( + OWNER, + DELEGATION_MANAGER, + EIGENPOD_MANAGER, + STRATEGY_MANAGER, + AVS_DIRECTORY, + restakeableStrategies, + FREEZE_ORACLE, + UNFREEZE_FEE, + UNFREEZE_RECEIVER, + UNFREEZE_PERIOD_BLOCKS, + OPERATOR_DEREG_PERIOD_BLOCKS, + VALIDATOR_DEREG_PERIOD_BLOCKS, + LST_RESTARKER_DEREG_PERIOD_BLOCKS + ); + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/validator-registry/avs/ReleaseAddrConsts.sol b/contracts/scripts/validator-registry/avs/ReleaseAddrConsts.sol index 07486a29f..a0ea4a458 100644 --- a/contracts/scripts/validator-registry/avs/ReleaseAddrConsts.sol +++ b/contracts/scripts/validator-registry/avs/ReleaseAddrConsts.sol @@ -54,3 +54,29 @@ library EigenHoleskyReleaseConsts { address internal constant STRATEGY_BASE_ANKRETH = 0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac; address internal constant BEACON_CHAIN_ETH = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; } + +/// @notice Constants from https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-testnet-deployment +/// @notice Last updated 07-25-2025 — for HOODI testnet +library EigenHoodiReleaseConsts { + // Core + address internal constant DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; + address internal constant STRATEGY_MANAGER = 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41; + address internal constant EIGENPOD_MANAGER = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; + address internal constant AVS_DIRECTORY = 0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926; + address internal constant REWARDS_COORDINATOR = 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7; + address internal constant ALLOCATION_MANAGER = 0x95a7431400F362F3647a69535C5666cA0133CAA0; + address internal constant PERMISSION_CONTROLLER = 0xdcCF401fD121d8C542E96BC1d0078884422aFAD2; + + // Strategies - Deployed via StrategyFactory + address internal constant STRATEGY_FACTORY = 0xfB7d94501E4d4ACC264833Ef4ede70a11517422B; + address internal constant STRATEGY_BASE = 0x6d28cEC1659BC3a9BC814c3EFc1412878B406579; + address internal constant STRATEGY_BASE_STETH = 0xF8a1a66130D614c7360e868576D5E59203475FE0; + address internal constant STRATEGY_BASE_WETH = 0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d; + // Special strategies + address internal constant STRATEGY_BASE_EIGEN = 0xB27b10291DBFE6576d17afF3e251c954Ae14f1D3; + // Beacon Chain ETH placeholder (not a real contract) + address internal constant BEACON_CHAIN_ETH = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; + // Tokens + address internal constant EIGEN_TOKEN = 0x8ae2520954db7D80D66835cB71E692835bbA45bf; + address internal constant BACKING_EIGEN = 0x6e60888132Cc7e637488379B4B40c42b3751f63a; +} diff --git a/contracts/scripts/validator-registry/middleware/DeployMiddleware.s.sol b/contracts/scripts/validator-registry/middleware/DeployMiddleware.s.sol index ca7c96c90..a733f71f6 100644 --- a/contracts/scripts/validator-registry/middleware/DeployMiddleware.s.sol +++ b/contracts/scripts/validator-registry/middleware/DeployMiddleware.s.sol @@ -11,7 +11,7 @@ import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol"; import {MevCommitMiddleware} from "../../../contracts/validator-registry/middleware/MevCommitMiddleware.sol"; import {IRegistry} from "symbiotic-core/interfaces/common/IRegistry.sol"; import {INetworkRegistry} from "symbiotic-core/interfaces/INetworkRegistry.sol"; -import {SymbioticHoleskyDevnetConsts, SymbioticMainnetConsts} from "./ReleaseAddrConsts.s.sol"; +import {SymbioticHoodiDevnetConsts, SymbioticHoleskyDevnetConsts, SymbioticMainnetConsts} from "./ReleaseAddrConsts.s.sol"; import {IBaseDelegator} from "symbiotic-core/interfaces/delegator/IBaseDelegator.sol"; import {INetworkMiddlewareService} from "symbiotic-core/interfaces/service/INetworkMiddlewareService.sol"; import {MainnetConstants} from "../../MainnetConstants.sol"; @@ -163,3 +163,64 @@ contract DeployHolesky is BaseDeploy { vm.stopBroadcast(); } } + + +contract DeployHoodi is BaseDeploy { + + IRegistry constant public NETWORK_REGISTRY = IRegistry(SymbioticHoodiDevnetConsts.NETWORK_REGISTRY); + IRegistry constant public OPERATOR_REGISTRY = IRegistry(SymbioticHoodiDevnetConsts.OPERATOR_REGISTRY); + IRegistry constant public VAULT_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.VAULT_FACTORY); + IRegistry constant public DELEGATOR_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.DELEGATOR_FACTORY); + IRegistry constant public SLASHER_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.SLASHER_FACTORY); + IRegistry constant public BURNER_ROUTER_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.BURNER_ROUTER_FACTORY); + + // On Hoodi, use dev keystore account. On mainnet these will be the primev multisig. + address constant public EXPECTED_MSG_SENDER = 0x1623fE21185c92BB43bD83741E226288B516134a; + address constant public OWNER = EXPECTED_MSG_SENDER; + address constant public NETWORK = EXPECTED_MSG_SENDER; + address constant public SLASH_ORACLE = EXPECTED_MSG_SENDER; // Temporary placeholder until oracle implements slashing. + address constant public SLASH_RECEIVER = EXPECTED_MSG_SENDER; + uint256 constant public MIN_BURNER_ROUTER_DELAY = 2 days; + + uint96 constant public SUBNETWORK_ID = 1; + uint256 constant public VAULT1_MAX_NETWORK_LIMIT = 100000 ether; + uint256 constant public SLASH_PERIOD_SECONDS = 1 days; // compiles to seconds + + function run() external { + require(block.chainid == 560048, "must deploy on Hoodi"); + require(msg.sender == EXPECTED_MSG_SENDER, "incorrect msg.sender"); + + vm.startBroadcast(); + + INetworkRegistry networkRegistry = INetworkRegistry(address(NETWORK_REGISTRY)); + if (!networkRegistry.isEntity(NETWORK)) { + networkRegistry.registerNetwork(); + } + + address mevCommitMiddlewareProxy = deployMevCommitMiddleware( + NETWORK_REGISTRY, + OPERATOR_REGISTRY, + VAULT_FACTORY, + DELEGATOR_FACTORY, + SLASHER_FACTORY, + BURNER_ROUTER_FACTORY, + NETWORK, + SLASH_PERIOD_SECONDS, + SLASH_ORACLE, + SLASH_RECEIVER, + MIN_BURNER_ROUTER_DELAY, + OWNER + ); + + INetworkMiddlewareService networkMiddlewareService = INetworkMiddlewareService(address(SymbioticHoodiDevnetConsts.NETWORK_MIDDLEWARE_SERVICE)); + if (networkMiddlewareService.middleware(msg.sender) != address(0)) { + console.log("WARNING: overwriting existing middleware registration for network:", msg.sender); + } + networkMiddlewareService.setMiddleware(mevCommitMiddlewareProxy); + + // No Hoodi Vaults in Symbiotic docs so hold off on Vault registration + // One created here but not verified or used: https://hoodi.etherscan.io/tx/0x3f9e9651b912bf9ac85bfe8e852183f062049b4410a7a94f7dffececb92140bb + + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/validator-registry/middleware/ReleaseAddrConsts.s.sol b/contracts/scripts/validator-registry/middleware/ReleaseAddrConsts.s.sol index 9205acda9..c4a327626 100644 --- a/contracts/scripts/validator-registry/middleware/ReleaseAddrConsts.s.sol +++ b/contracts/scripts/validator-registry/middleware/ReleaseAddrConsts.s.sol @@ -36,3 +36,23 @@ library SymbioticHoleskyDevnetConsts { address internal constant BURNER_ROUTER_FACTORY = 0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b; } + +/// @notice Constants from https://docs.symbiotic.fi/deployments/testnet#hoodi +/// @notice Last updated 07-25-2025 +library SymbioticHoodiDevnetConsts { + address internal constant VAULT_FACTORY = 0x407A039D94948484D356eFB765b3c74382A050B4; + address internal constant DELEGATOR_FACTORY = 0x890CA3f95E0f40a79885B7400926544B2214B03f; + address internal constant SLASHER_FACTORY = 0xbf34bf75bb779c383267736c53a4ae86ac7bB299; + address internal constant NETWORK_REGISTRY = 0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9; + + address internal constant NETWORK_MIDDLEWARE_SERVICE = 0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3; + address internal constant OPERATOR_REGISTRY = 0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548; + + address internal constant VAULT_OPT_IN_SERVICE = 0x95CC0a052ae33941877c9619835A233D21D57351; + address internal constant NETWORK_OPT_IN_SERVICE = 0x58973d16FFA900D11fC22e5e2B6840d9f7e13401; + address internal constant VAULT_CONFIGURATOR = 0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f; + address internal constant DEFAULT_STAKER_REWARDS_FACTORY = 0x1eA0b919721C20dae19aBc4391850D94eDbe9b1c; + address internal constant DEFAULT_OPERATOR_REWARDS_FACTORY = 0xE7e597655C3F76117302ea6103f5F2B3F3D75c5d; + + address internal constant BURNER_ROUTER_FACTORY = 0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a; +}