Skip to content

Commit 43ffb52

Browse files
8sunyuanwadealexc
andauthored
feat: holesky deploy scripts (#473)
* script: parser script helpers * feat: holesky deploy scripts * fix: config * fix: ops multisig whitelister * feat: track active validator count in pods (#474) * chore: remove maxPods (#463) * chore: remove maxPods * docs: update docs * refactor: set to private * script: parser script helpers * feat: holesky deploy scripts * fix: config * fix: ops multisig whitelister * refactor: maxpods removal * feat: preprod deployment * refactor: reuse other script --------- Co-authored-by: Alex <[email protected]>
1 parent 3ba2b34 commit 43ffb52

File tree

6 files changed

+923
-18
lines changed

6 files changed

+923
-18
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
RPC_MAINNET="https://eth.llamarpc.com"
22
# RPC_MAINNET="https://mainnet.infura.io/v3/API-KEY"
33
RPC_GOERLI="https://ethereum-goerli.publicnode.com"
4+
RPC_HOLESKY=""
45
ETHERSCAN_API_KEY="API-KEY"
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"chainInfo": {
3+
"chainId": 17000
4+
},
5+
"multisig_addresses": {
6+
"pauserMultisig": "0x53410249ec7d3a3F9F1ba3912D50D6A3Df6d10A7",
7+
"communityMultisig": "0xCb8d2f9e55Bc7B1FA9d089f9aC80C583D2BDD5F7",
8+
"operationsMultisig": "0xfaEF7338b7490b9E272d80A1a39f4657cAf2b97d",
9+
"executorMultisig": "0x28Ade60640fdBDb2609D8d8734D1b5cBeFc0C348",
10+
"timelock": "0xcF19CE0561052a7A7Ff21156730285997B350A7D"
11+
},
12+
"numStrategies": 2,
13+
"strategies": {
14+
"numStrategies": 2,
15+
"MAX_PER_DEPOSIT": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
16+
"MAX_TOTAL_DEPOSITS": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
17+
"strategiesToDeploy": [
18+
{
19+
"token_address": "0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034",
20+
"token_name": "Liquid staked Ether 2.0",
21+
"token_symbol": "stETH"
22+
},
23+
{
24+
"token_address": "0x7322c24752f79c05FFD1E2a6FCB97020C1C264F1",
25+
"token_name": "Rocket Pool ETH",
26+
"token_symbol": "rETH"
27+
}
28+
]
29+
},
30+
"strategyManager": {
31+
"init_strategy_whitelister": "0xfaEF7338b7490b9E272d80A1a39f4657cAf2b97d",
32+
"init_paused_status": 0
33+
},
34+
"delegationManager": {
35+
"init_paused_status": 0,
36+
"init_minWithdrawalDelayBlocks": 50400
37+
},
38+
"avsDirectory": {
39+
"init_paused_status": 0
40+
},
41+
"slasher": {
42+
"init_paused_status": 0
43+
},
44+
"eigenPod": {
45+
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": 32000000000000000000,
46+
"GENESIS_TIME": 1695902400
47+
},
48+
"eigenPodManager": {
49+
"init_paused_status": 0,
50+
"deneb_fork_timestamp": "1707305664"
51+
},
52+
"delayedWithdrawalRouter": {
53+
"init_paused_status": 0,
54+
"init_withdrawalDelayBlocks": 50400
55+
},
56+
"ethPOSDepositAddress": "0x4242424242424242424242424242424242424242",
57+
"beaconOracleAddress": "0x4C116BB629bff7A8373c2378bBd919f8349B8f25"
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"chainInfo": {
3+
"chainId": 17000
4+
},
5+
"multisig_addresses": {
6+
"pauserMultisig": "0x0000000000000000000000000000000000000000",
7+
"communityMultisig": "0x0000000000000000000000000000000000000000",
8+
"operationsMultisig": "0x0000000000000000000000000000000000000000",
9+
"executorMultisig": "0x0000000000000000000000000000000000000000",
10+
"timelock": "0x0000000000000000000000000000000000000000"
11+
},
12+
"numStrategies": 2,
13+
"strategies": {
14+
"numStrategies": 2,
15+
"MAX_PER_DEPOSIT": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
16+
"MAX_TOTAL_DEPOSITS": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
17+
"strategiesToDeploy": [
18+
{
19+
"token_address": "0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034",
20+
"token_name": "Liquid staked Ether 2.0",
21+
"token_symbol": "stETH"
22+
},
23+
{
24+
"token_address": "0x7322c24752f79c05FFD1E2a6FCB97020C1C264F1",
25+
"token_name": "Rocket Pool ETH",
26+
"token_symbol": "rETH"
27+
}
28+
]
29+
},
30+
"strategyManager": {
31+
"init_strategy_whitelister": "0x0000000000000000000000000000000000000000",
32+
"init_paused_status": 0
33+
},
34+
"delegationManager": {
35+
"init_paused_status": 0,
36+
"init_minWithdrawalDelayBlocks": 50400
37+
},
38+
"avsDirectory": {
39+
"init_paused_status": 0
40+
},
41+
"slasher": {
42+
"init_paused_status": 0
43+
},
44+
"eigenPod": {
45+
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": 32000000000000000000,
46+
"GENESIS_TIME": 1695902400
47+
},
48+
"eigenPodManager": {
49+
"init_paused_status": 0,
50+
"deneb_fork_timestamp": "1707305664"
51+
},
52+
"delayedWithdrawalRouter": {
53+
"init_paused_status": 0,
54+
"init_withdrawalDelayBlocks": 50400
55+
},
56+
"ethPOSDepositAddress": "0x4242424242424242424242424242424242424242",
57+
"beaconOracleAddress": "0x4C116BB629bff7A8373c2378bBd919f8349B8f25"
58+
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity =0.8.12;
3+
4+
import "../../utils/ExistingDeploymentParser.sol";
5+
6+
/**
7+
* @notice Script used for the first deployment of EigenLayer core contracts to Holesky
8+
* forge script script/deploy/holesky/M2_Deploy_From_Scratch.s.sol --rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast -vvvv
9+
* forge script script/deploy/holesky/M2_Deploy_From_Scratch.s.sol --rpc-url $RPC_HOLESKY --private-key $PRIVATE_KEY --broadcast -vvvv
10+
*
11+
*/
12+
contract M2_Deploy_Holesky_From_Scratch is ExistingDeploymentParser {
13+
function run() external virtual {
14+
_parseInitialDeploymentParams("script/configs/holesky/M2_deploy_from_scratch.holesky.config.json");
15+
16+
// START RECORDING TRANSACTIONS FOR DEPLOYMENT
17+
vm.startBroadcast();
18+
19+
emit log_named_address("Deployer Address", msg.sender);
20+
21+
_deployFromScratch();
22+
23+
// STOP RECORDING TRANSACTIONS FOR DEPLOYMENT
24+
vm.stopBroadcast();
25+
26+
// Sanity Checks
27+
_verifyContractPointers();
28+
_verifyImplementations();
29+
_verifyContractsInitialized({isInitialDeployment: true});
30+
_verifyInitializationParams();
31+
32+
logAndOutputContractAddresses("script/output/holesky/M2_deploy_from_scratch.holesky.config.json");
33+
}
34+
35+
/**
36+
* @notice Deploy EigenLayer contracts from scratch for Holesky
37+
*/
38+
function _deployFromScratch() internal {
39+
// Deploy ProxyAdmin, later set admins for all proxies to be executorMultisig
40+
eigenLayerProxyAdmin = new ProxyAdmin();
41+
42+
// Set multisigs as pausers, executorMultisig as unpauser
43+
address[] memory pausers = new address[](3);
44+
pausers[0] = executorMultisig;
45+
pausers[1] = operationsMultisig;
46+
pausers[2] = pauserMultisig;
47+
address unpauser = executorMultisig;
48+
eigenLayerPauserReg = new PauserRegistry(pausers, unpauser);
49+
50+
/**
51+
* First, deploy upgradeable proxy contracts that **will point** to the implementations. Since the implementation contracts are
52+
* not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code.
53+
*/
54+
emptyContract = new EmptyContract();
55+
avsDirectory = AVSDirectory(
56+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
57+
);
58+
delegationManager = DelegationManager(
59+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
60+
);
61+
strategyManager = StrategyManager(
62+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
63+
);
64+
slasher = Slasher(
65+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
66+
);
67+
eigenPodManager = EigenPodManager(
68+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
69+
);
70+
delayedWithdrawalRouter = DelayedWithdrawalRouter(
71+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
72+
);
73+
74+
// Deploy EigenPod Contracts
75+
eigenPodImplementation = new EigenPod(
76+
IETHPOSDeposit(ETHPOSDepositAddress),
77+
delayedWithdrawalRouter,
78+
eigenPodManager,
79+
EIGENPOD_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR,
80+
EIGENPOD_GENESIS_TIME
81+
);
82+
83+
eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation));
84+
avsDirectoryImplementation = new AVSDirectory(delegationManager);
85+
delegationManagerImplementation = new DelegationManager(strategyManager, slasher, eigenPodManager);
86+
strategyManagerImplementation = new StrategyManager(delegationManager, eigenPodManager, slasher);
87+
slasherImplementation = new Slasher(strategyManager, delegationManager);
88+
eigenPodManagerImplementation = new EigenPodManager(
89+
IETHPOSDeposit(ETHPOSDepositAddress),
90+
eigenPodBeacon,
91+
strategyManager,
92+
slasher,
93+
delegationManager
94+
);
95+
delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter(eigenPodManager);
96+
97+
// Third, upgrade the proxy contracts to point to the implementations
98+
IStrategy[] memory initializeStrategiesToSetDelayBlocks = new IStrategy[](0);
99+
uint256[] memory initializeWithdrawalDelayBlocks = new uint256[](0);
100+
// AVSDirectory
101+
eigenLayerProxyAdmin.upgradeAndCall(
102+
TransparentUpgradeableProxy(payable(address(avsDirectory))),
103+
address(avsDirectoryImplementation),
104+
abi.encodeWithSelector(
105+
AVSDirectory.initialize.selector,
106+
executorMultisig, // initialOwner
107+
eigenLayerPauserReg,
108+
AVS_DIRECTORY_INIT_PAUSED_STATUS
109+
)
110+
);
111+
// DelegationManager
112+
eigenLayerProxyAdmin.upgradeAndCall(
113+
TransparentUpgradeableProxy(payable(address(delegationManager))),
114+
address(delegationManagerImplementation),
115+
abi.encodeWithSelector(
116+
DelegationManager.initialize.selector,
117+
executorMultisig, // initialOwner
118+
eigenLayerPauserReg,
119+
DELEGATION_MANAGER_INIT_PAUSED_STATUS,
120+
DELEGATION_MANAGER_MIN_WITHDRAWAL_DELAY_BLOCKS,
121+
initializeStrategiesToSetDelayBlocks,
122+
initializeWithdrawalDelayBlocks
123+
)
124+
);
125+
// StrategyManager
126+
eigenLayerProxyAdmin.upgradeAndCall(
127+
TransparentUpgradeableProxy(payable(address(strategyManager))),
128+
address(strategyManagerImplementation),
129+
abi.encodeWithSelector(
130+
StrategyManager.initialize.selector,
131+
executorMultisig, //initialOwner
132+
STRATEGY_MANAGER_WHITELISTER, //initial whitelister
133+
eigenLayerPauserReg,
134+
STRATEGY_MANAGER_INIT_PAUSED_STATUS
135+
)
136+
);
137+
// Slasher
138+
eigenLayerProxyAdmin.upgradeAndCall(
139+
TransparentUpgradeableProxy(payable(address(slasher))),
140+
address(slasherImplementation),
141+
abi.encodeWithSelector(
142+
Slasher.initialize.selector,
143+
executorMultisig,
144+
eigenLayerPauserReg,
145+
SLASHER_INIT_PAUSED_STATUS
146+
)
147+
);
148+
// EigenPodManager
149+
eigenLayerProxyAdmin.upgradeAndCall(
150+
TransparentUpgradeableProxy(payable(address(eigenPodManager))),
151+
address(eigenPodManagerImplementation),
152+
abi.encodeWithSelector(
153+
EigenPodManager.initialize.selector,
154+
beaconOracle,
155+
msg.sender, // initialOwner is msg.sender for now to set forktimestamp later
156+
eigenLayerPauserReg,
157+
EIGENPOD_MANAGER_INIT_PAUSED_STATUS
158+
)
159+
);
160+
// Delayed Withdrawal Router
161+
eigenLayerProxyAdmin.upgradeAndCall(
162+
TransparentUpgradeableProxy(payable(address(delayedWithdrawalRouter))),
163+
address(delayedWithdrawalRouterImplementation),
164+
abi.encodeWithSelector(
165+
DelayedWithdrawalRouter.initialize.selector,
166+
executorMultisig, // initialOwner
167+
eigenLayerPauserReg,
168+
DELAYED_WITHDRAWAL_ROUTER_INIT_PAUSED_STATUS,
169+
DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS
170+
)
171+
);
172+
173+
// Deploy Strategies
174+
baseStrategyImplementation = new StrategyBaseTVLLimits(strategyManager);
175+
uint256 numStrategiesToDeploy = strategiesToDeploy.length;
176+
for (uint256 i = 0; i < numStrategiesToDeploy; i++) {
177+
StrategyUnderlyingTokenConfig memory strategyConfig = strategiesToDeploy[i];
178+
179+
// Deploy and upgrade strategy
180+
StrategyBaseTVLLimits strategy = StrategyBaseTVLLimits(
181+
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
182+
);
183+
eigenLayerProxyAdmin.upgradeAndCall(
184+
TransparentUpgradeableProxy(payable(address(strategy))),
185+
address(baseStrategyImplementation),
186+
abi.encodeWithSelector(
187+
StrategyBaseTVLLimits.initialize.selector,
188+
STRATEGY_MAX_PER_DEPOSIT,
189+
STRATEGY_MAX_TOTAL_DEPOSITS,
190+
IERC20(strategyConfig.tokenAddress),
191+
eigenLayerPauserReg
192+
)
193+
);
194+
195+
deployedStrategyArray.push(strategy);
196+
}
197+
198+
// Fork timestamp config
199+
eigenPodManager.setDenebForkTimestamp(EIGENPOD_MANAGER_DENEB_FORK_TIMESTAMP);
200+
201+
// Transfer ownership
202+
eigenLayerProxyAdmin.transferOwnership(executorMultisig);
203+
eigenPodManager.transferOwnership(executorMultisig);
204+
eigenPodBeacon.transferOwnership(executorMultisig);
205+
}
206+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity =0.8.12;
3+
4+
import "./M2_Deploy_From_Scratch.s.sol";
5+
6+
/**
7+
* @notice Script used for the first deployment of EigenLayer core contracts to Holesky
8+
* forge script script/deploy/holesky/M2_Deploy_Preprod.s.sol --rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast -vvvv
9+
* forge script script/deploy/holesky/M2_Deploy_Preprod.s.sol --rpc-url $RPC_HOLESKY --private-key $PRIVATE_KEY --broadcast -vvvv
10+
*
11+
* Script for dev environment, exact same as M2_Deploy_From_Scratch.s.sol but with an EOAowner
12+
* instead of multisig addresses for permissions.
13+
* Unused config fields:
14+
* - init_strategy_whitelister
15+
* - multisig_addresses(operations, pauser, executor, community)
16+
*/
17+
contract M2_Deploy_Holesky_Preprod is M2_Deploy_Holesky_From_Scratch {
18+
/// @dev EOAowner is the deployer and owner of the contracts
19+
address EOAowner;
20+
21+
function run() external virtual override {
22+
_parseInitialDeploymentParams("script/configs/holesky/M2_deploy_preprod.holesky.config.json");
23+
24+
// Overwrite multisig to be EOAowner
25+
EOAowner = msg.sender;
26+
executorMultisig = EOAowner;
27+
operationsMultisig = EOAowner;
28+
pauserMultisig = EOAowner;
29+
communityMultisig = EOAowner;
30+
STRATEGY_MANAGER_WHITELISTER = EOAowner;
31+
32+
// START RECORDING TRANSACTIONS FOR DEPLOYMENT
33+
vm.startBroadcast();
34+
35+
emit log_named_address("Deployer and EOAowner Address", EOAowner);
36+
37+
_deployFromScratch();
38+
39+
// STOP RECORDING TRANSACTIONS FOR DEPLOYMENT
40+
vm.stopBroadcast();
41+
42+
// Sanity Checks
43+
_verifyContractPointers();
44+
_verifyImplementations();
45+
_verifyContractsInitialized({isInitialDeployment: true});
46+
_verifyInitializationParams(); // override to check contract.owner() is EOAowner instead
47+
48+
logAndOutputContractAddresses("script/output/holesky/M2_deploy_preprod.holesky.config.json");
49+
}
50+
}

0 commit comments

Comments
 (0)