Skip to content

Commit b0c7e5c

Browse files
owen-ethOwen Raman
andauthored
feat: add hoodi support to L1 contracts (#743)
* add hoodi support to L1 contracts * fix: correct hoodi chainId * feat: added hoodi support to old foundry, minor testnet deployment script fix, logged hoodi deployments in README * reverted foundry.toml changes --------- Co-authored-by: Owen Raman <owenraman@Owens-MacBook-Pro.local>
1 parent d098edf commit b0c7e5c

File tree

9 files changed

+221
-7
lines changed

9 files changed

+221
-7
lines changed

contracts/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ This changelog tracks "core" contract deployments on the mev-commit chain. This
4848
| July 22nd 2025, 20:10:39 UTC | BidderRegistry | BidderRegistryV2 | `v1.1.5` in `release/v1.1.x`. |
4949
| July 22nd 2025, 20:10:39 UTC | ProviderRegistry | ProviderRegistryV2 | `v1.1.5` in `release/v1.1.x`. |
5050

51+
## Hoodi Testnet (L1) Contract Changelog
52+
53+
This changelog tracks deployments of **Hoodi Testnet** contracts. This changelog is only valid from the `main` branch.
54+
55+
### Current Deployments
56+
57+
| Contract | Proxy Address | Initial Commit |
58+
|-----------------------|----------------------------------------------|---------------------|
59+
| ValidatorOptInRouter | `0xa380ba6d6083a4Cb2a3B62b0a81Ea8727861c13e` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' |
60+
| VanillaRegistry | `0x536f0792c5d5ed592e67a9260606c85f59c312f0` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' |
61+
| MevCommitAVS | `0xdF8649d298ad05f019eE4AdBD6210867B8AB225F` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' |
62+
| MevCommitMiddleware | `0x8E847EC4a36c8332652aB3b2B7D5c54dE29c7fde` | `13cf068477e6efdbb5c4fe5ce53a11af30bf8b47` in 'main' |
63+
64+
### Upgrade History
65+
66+
| Timestamp (UTC) | Contract | New Impl Version | Commmit |
67+
|-----------------------------|---------------------|-----------------------|-------------------|
68+
| N/A | | | |
69+
70+
5171
## L1 Deployer CLI
5272

5373
> **After completing any L1 deployment, immediately record it in the “Current Deployments” table above.**

contracts/foundry.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ cache_path = 'cache_forge'
99
ffi = true
1010
ast = true
1111
build_info = true
12-
extra_output = ["storageLayout"]
12+
extra_output = ["storageLayout"]

contracts/l1-deployer-cli.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ help() {
2626
echo " deploy-router Deploy and verify the ValidatorOptInRouter contract to L1."
2727
echo
2828
echo "Required Options:"
29-
echo " --chain, -c <chain> Specify the chain to deploy to ('mainnet' or 'holesky')."
29+
echo " --chain, -c <chain> Specify the chain to deploy to ('mainnet', 'holesky', or 'hoodi')."
3030
echo
3131
echo "Wallet Options (exactly one required):"
3232
echo " --keystore Use a keystore for deployment."
@@ -128,8 +128,8 @@ parse_args() {
128128
exit 1
129129
fi
130130
chain="$2"
131-
if [[ "$chain" != "mainnet" && "$chain" != "holesky" ]]; then
132-
echo "Error: Unknown chain '$chain'. Valid options are 'mainnet' or 'holesky'."
131+
if [[ "$chain" != "mainnet" && "$chain" != "holesky" && "$chain" != "hoodi" ]]; then
132+
echo "Error: Unknown chain '$chain'. Valid options are 'mainnet', 'holesky', or hoodi."
133133
exit 1
134134
fi
135135
shift 2
@@ -248,6 +248,9 @@ get_chain_params() {
248248
elif [[ "$chain" == "holesky" ]]; then
249249
chain_id=17000
250250
deploy_contract="DeployHolesky"
251+
elif [[ "$chain" == "hoodi" ]]; then
252+
chain_id=560048
253+
deploy_contract="DeployHoodi"
251254
fi
252255
}
253256

contracts/scripts/validator-registry/DeployValidatorOptInRouter.s.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,25 @@ contract DeployHolesky is BaseDeploy {
7474
vm.stopBroadcast();
7575
}
7676
}
77+
78+
contract DeployHoodi is BaseDeploy {
79+
address constant public VANILLA_REGISTRY = 0x536F0792c5D5Ed592e67a9260606c85F59C312F0;
80+
address constant public MEV_COMMIT_AVS = 0xdF8649d298ad05f019eE4AdBD6210867B8AB225F;
81+
address constant public MEV_COMMIT_MIDDLEWARE = 0x8E847EC4a36c8332652aB3b2B7D5c54dE29c7fde;
82+
83+
//This is the most important field. On mainnet it'll be the primev multisig.
84+
address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a;
85+
86+
function run() external {
87+
require(block.chainid == 560048, "must deploy on Hoodi");
88+
89+
vm.startBroadcast();
90+
deployValidatorOptInRouter(
91+
VANILLA_REGISTRY,
92+
MEV_COMMIT_AVS,
93+
MEV_COMMIT_MIDDLEWARE,
94+
OWNER
95+
);
96+
vm.stopBroadcast();
97+
}
98+
}

contracts/scripts/validator-registry/DeployVanillaRegistry.s.sol

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,21 @@ contract DeployAnvil is BaseDeploy {
8282
vm.stopBroadcast();
8383
}
8484
}
85+
86+
contract DeployHoodi is BaseDeploy {
87+
uint256 constant public MIN_STAKE = 0.0001 ether; // 10k vals = 1 ETH cost
88+
address constant public SLASH_ORACLE = 0x1623fE21185c92BB43bD83741E226288B516134a;
89+
address constant public SLASH_RECEIVER = 0x1623fE21185c92BB43bD83741E226288B516134a;
90+
uint256 constant public UNSTAKE_PERIOD_BLOCKS = 32 * 3; // 2 epoch finalization time + settlement buffer
91+
uint256 constant public PAYOUT_PERIOD = 10000; // 10k * 12s = 1.39 days
92+
93+
// This is the most important field. On mainnet it'll be the primev multisig.
94+
address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a;
95+
96+
function run() external {
97+
require(block.chainid == 560048, "must deploy on Hoodi");
98+
vm.startBroadcast();
99+
deployVanillaRegistry(MIN_STAKE, SLASH_ORACLE, SLASH_RECEIVER, UNSTAKE_PERIOD_BLOCKS, PAYOUT_PERIOD, OWNER);
100+
vm.stopBroadcast();
101+
}
102+
}

contracts/scripts/validator-registry/avs/DeployAVS.s.sol

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import {IDelegationManager} from "eigenlayer-contracts/src/contracts/interfaces/
1313
import {IEigenPodManager} from "eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol";
1414
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
1515
import {IAVSDirectory} from "eigenlayer-contracts/src/contracts/interfaces/IAVSDirectory.sol";
16-
import {EigenHoleskyReleaseConsts} from "./ReleaseAddrConsts.sol";
17-
import {EigenMainnetReleaseConsts} from "./ReleaseAddrConsts.sol";
16+
import {EigenHoodiReleaseConsts, EigenHoleskyReleaseConsts, EigenMainnetReleaseConsts} from "./ReleaseAddrConsts.sol";
1817
import {MainnetConstants} from "../../MainnetConstants.sol";
1918

2019
contract BaseDeploy is Script {
@@ -166,3 +165,48 @@ contract DeployHolesky is BaseDeploy {
166165
vm.stopBroadcast();
167166
}
168167
}
168+
169+
contract DeployHoodi is BaseDeploy {
170+
// This is the most important field. On mainnet it'll be the primev multisig.
171+
address constant public OWNER = 0x1623fE21185c92BB43bD83741E226288B516134a;
172+
173+
IDelegationManager constant public DELEGATION_MANAGER = IDelegationManager(EigenHoodiReleaseConsts.DELEGATION_MANAGER);
174+
IEigenPodManager constant public EIGENPOD_MANAGER = IEigenPodManager(EigenHoodiReleaseConsts.EIGENPOD_MANAGER);
175+
IStrategyManager constant public STRATEGY_MANAGER = IStrategyManager(EigenHoodiReleaseConsts.STRATEGY_MANAGER);
176+
IAVSDirectory constant public AVS_DIRECTORY = IAVSDirectory(EigenHoodiReleaseConsts.AVS_DIRECTORY);
177+
address constant public FREEZE_ORACLE = 0x1623fE21185c92BB43bD83741E226288B516134a; // Temporary freeze oracle
178+
uint256 constant public UNFREEZE_FEE = 0.1 ether;
179+
address constant public UNFREEZE_RECEIVER = 0x1623fE21185c92BB43bD83741E226288B516134a; // Temporary unfreezeReceiver
180+
uint256 constant public UNFREEZE_PERIOD_BLOCKS = 12000; // ~ 1 day
181+
uint256 constant public OPERATOR_DEREG_PERIOD_BLOCKS = 12000; // ~ 1 day
182+
uint256 constant public VALIDATOR_DEREG_PERIOD_BLOCKS = 32 * 3; // 2 epoch finalization time + settlement buffer
183+
uint256 constant public LST_RESTARKER_DEREG_PERIOD_BLOCKS = 12000; // ~ 1 day
184+
185+
function run() external {
186+
require(block.chainid == 560048, "must deploy on Hoodi");
187+
188+
address[] memory restakeableStrategies = new address[](5);
189+
restakeableStrategies[0] = EigenHoodiReleaseConsts.STRATEGY_BASE_STETH;
190+
restakeableStrategies[1] = EigenHoodiReleaseConsts.STRATEGY_BASE_WETH;
191+
restakeableStrategies[3] = EigenHoodiReleaseConsts.STRATEGY_BASE_EIGEN;
192+
restakeableStrategies[4] = EigenHoodiReleaseConsts.BEACON_CHAIN_ETH;
193+
194+
vm.startBroadcast();
195+
deployMevCommitAVS(
196+
OWNER,
197+
DELEGATION_MANAGER,
198+
EIGENPOD_MANAGER,
199+
STRATEGY_MANAGER,
200+
AVS_DIRECTORY,
201+
restakeableStrategies,
202+
FREEZE_ORACLE,
203+
UNFREEZE_FEE,
204+
UNFREEZE_RECEIVER,
205+
UNFREEZE_PERIOD_BLOCKS,
206+
OPERATOR_DEREG_PERIOD_BLOCKS,
207+
VALIDATOR_DEREG_PERIOD_BLOCKS,
208+
LST_RESTARKER_DEREG_PERIOD_BLOCKS
209+
);
210+
vm.stopBroadcast();
211+
}
212+
}

contracts/scripts/validator-registry/avs/ReleaseAddrConsts.sol

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,29 @@ library EigenHoleskyReleaseConsts {
5454
address internal constant STRATEGY_BASE_ANKRETH = 0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac;
5555
address internal constant BEACON_CHAIN_ETH = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0;
5656
}
57+
58+
/// @notice Constants from https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-testnet-deployment
59+
/// @notice Last updated 07-25-2025 — for HOODI testnet
60+
library EigenHoodiReleaseConsts {
61+
// Core
62+
address internal constant DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d;
63+
address internal constant STRATEGY_MANAGER = 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41;
64+
address internal constant EIGENPOD_MANAGER = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c;
65+
address internal constant AVS_DIRECTORY = 0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926;
66+
address internal constant REWARDS_COORDINATOR = 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7;
67+
address internal constant ALLOCATION_MANAGER = 0x95a7431400F362F3647a69535C5666cA0133CAA0;
68+
address internal constant PERMISSION_CONTROLLER = 0xdcCF401fD121d8C542E96BC1d0078884422aFAD2;
69+
70+
// Strategies - Deployed via StrategyFactory
71+
address internal constant STRATEGY_FACTORY = 0xfB7d94501E4d4ACC264833Ef4ede70a11517422B;
72+
address internal constant STRATEGY_BASE = 0x6d28cEC1659BC3a9BC814c3EFc1412878B406579;
73+
address internal constant STRATEGY_BASE_STETH = 0xF8a1a66130D614c7360e868576D5E59203475FE0;
74+
address internal constant STRATEGY_BASE_WETH = 0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d;
75+
// Special strategies
76+
address internal constant STRATEGY_BASE_EIGEN = 0xB27b10291DBFE6576d17afF3e251c954Ae14f1D3;
77+
// Beacon Chain ETH placeholder (not a real contract)
78+
address internal constant BEACON_CHAIN_ETH = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0;
79+
// Tokens
80+
address internal constant EIGEN_TOKEN = 0x8ae2520954db7D80D66835cB71E692835bbA45bf;
81+
address internal constant BACKING_EIGEN = 0x6e60888132Cc7e637488379B4B40c42b3751f63a;
82+
}

contracts/scripts/validator-registry/middleware/DeployMiddleware.s.sol

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
1111
import {MevCommitMiddleware} from "../../../contracts/validator-registry/middleware/MevCommitMiddleware.sol";
1212
import {IRegistry} from "symbiotic-core/interfaces/common/IRegistry.sol";
1313
import {INetworkRegistry} from "symbiotic-core/interfaces/INetworkRegistry.sol";
14-
import {SymbioticHoleskyDevnetConsts, SymbioticMainnetConsts} from "./ReleaseAddrConsts.s.sol";
14+
import {SymbioticHoodiDevnetConsts, SymbioticHoleskyDevnetConsts, SymbioticMainnetConsts} from "./ReleaseAddrConsts.s.sol";
1515
import {IBaseDelegator} from "symbiotic-core/interfaces/delegator/IBaseDelegator.sol";
1616
import {INetworkMiddlewareService} from "symbiotic-core/interfaces/service/INetworkMiddlewareService.sol";
1717
import {MainnetConstants} from "../../MainnetConstants.sol";
@@ -163,3 +163,64 @@ contract DeployHolesky is BaseDeploy {
163163
vm.stopBroadcast();
164164
}
165165
}
166+
167+
168+
contract DeployHoodi is BaseDeploy {
169+
170+
IRegistry constant public NETWORK_REGISTRY = IRegistry(SymbioticHoodiDevnetConsts.NETWORK_REGISTRY);
171+
IRegistry constant public OPERATOR_REGISTRY = IRegistry(SymbioticHoodiDevnetConsts.OPERATOR_REGISTRY);
172+
IRegistry constant public VAULT_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.VAULT_FACTORY);
173+
IRegistry constant public DELEGATOR_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.DELEGATOR_FACTORY);
174+
IRegistry constant public SLASHER_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.SLASHER_FACTORY);
175+
IRegistry constant public BURNER_ROUTER_FACTORY = IRegistry(SymbioticHoodiDevnetConsts.BURNER_ROUTER_FACTORY);
176+
177+
// On Hoodi, use dev keystore account. On mainnet these will be the primev multisig.
178+
address constant public EXPECTED_MSG_SENDER = 0x1623fE21185c92BB43bD83741E226288B516134a;
179+
address constant public OWNER = EXPECTED_MSG_SENDER;
180+
address constant public NETWORK = EXPECTED_MSG_SENDER;
181+
address constant public SLASH_ORACLE = EXPECTED_MSG_SENDER; // Temporary placeholder until oracle implements slashing.
182+
address constant public SLASH_RECEIVER = EXPECTED_MSG_SENDER;
183+
uint256 constant public MIN_BURNER_ROUTER_DELAY = 2 days;
184+
185+
uint96 constant public SUBNETWORK_ID = 1;
186+
uint256 constant public VAULT1_MAX_NETWORK_LIMIT = 100000 ether;
187+
uint256 constant public SLASH_PERIOD_SECONDS = 1 days; // compiles to seconds
188+
189+
function run() external {
190+
require(block.chainid == 560048, "must deploy on Hoodi");
191+
require(msg.sender == EXPECTED_MSG_SENDER, "incorrect msg.sender");
192+
193+
vm.startBroadcast();
194+
195+
INetworkRegistry networkRegistry = INetworkRegistry(address(NETWORK_REGISTRY));
196+
if (!networkRegistry.isEntity(NETWORK)) {
197+
networkRegistry.registerNetwork();
198+
}
199+
200+
address mevCommitMiddlewareProxy = deployMevCommitMiddleware(
201+
NETWORK_REGISTRY,
202+
OPERATOR_REGISTRY,
203+
VAULT_FACTORY,
204+
DELEGATOR_FACTORY,
205+
SLASHER_FACTORY,
206+
BURNER_ROUTER_FACTORY,
207+
NETWORK,
208+
SLASH_PERIOD_SECONDS,
209+
SLASH_ORACLE,
210+
SLASH_RECEIVER,
211+
MIN_BURNER_ROUTER_DELAY,
212+
OWNER
213+
);
214+
215+
INetworkMiddlewareService networkMiddlewareService = INetworkMiddlewareService(address(SymbioticHoodiDevnetConsts.NETWORK_MIDDLEWARE_SERVICE));
216+
if (networkMiddlewareService.middleware(msg.sender) != address(0)) {
217+
console.log("WARNING: overwriting existing middleware registration for network:", msg.sender);
218+
}
219+
networkMiddlewareService.setMiddleware(mevCommitMiddlewareProxy);
220+
221+
// No Hoodi Vaults in Symbiotic docs so hold off on Vault registration
222+
// One created here but not verified or used: https://hoodi.etherscan.io/tx/0x3f9e9651b912bf9ac85bfe8e852183f062049b4410a7a94f7dffececb92140bb
223+
224+
vm.stopBroadcast();
225+
}
226+
}

contracts/scripts/validator-registry/middleware/ReleaseAddrConsts.s.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,23 @@ library SymbioticHoleskyDevnetConsts {
3636

3737
address internal constant BURNER_ROUTER_FACTORY = 0x32e2AfbdAffB1e675898ABA75868d92eE1E68f3b;
3838
}
39+
40+
/// @notice Constants from https://docs.symbiotic.fi/deployments/testnet#hoodi
41+
/// @notice Last updated 07-25-2025
42+
library SymbioticHoodiDevnetConsts {
43+
address internal constant VAULT_FACTORY = 0x407A039D94948484D356eFB765b3c74382A050B4;
44+
address internal constant DELEGATOR_FACTORY = 0x890CA3f95E0f40a79885B7400926544B2214B03f;
45+
address internal constant SLASHER_FACTORY = 0xbf34bf75bb779c383267736c53a4ae86ac7bB299;
46+
address internal constant NETWORK_REGISTRY = 0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9;
47+
48+
address internal constant NETWORK_MIDDLEWARE_SERVICE = 0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3;
49+
address internal constant OPERATOR_REGISTRY = 0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548;
50+
51+
address internal constant VAULT_OPT_IN_SERVICE = 0x95CC0a052ae33941877c9619835A233D21D57351;
52+
address internal constant NETWORK_OPT_IN_SERVICE = 0x58973d16FFA900D11fC22e5e2B6840d9f7e13401;
53+
address internal constant VAULT_CONFIGURATOR = 0x94c344E816A53D07fC4c7F4a18f82b6Da87CFc8f;
54+
address internal constant DEFAULT_STAKER_REWARDS_FACTORY = 0x1eA0b919721C20dae19aBc4391850D94eDbe9b1c;
55+
address internal constant DEFAULT_OPERATOR_REWARDS_FACTORY = 0xE7e597655C3F76117302ea6103f5F2B3F3D75c5d;
56+
57+
address internal constant BURNER_ROUTER_FACTORY = 0xF619c99D166224B4AC008b14Cc67ac72C2E91D8a;
58+
}

0 commit comments

Comments
 (0)