Skip to content

Commit 7a6f055

Browse files
authored
feat: v1.9.0 upgrade scripts + reusable upgrade helpers (#1665)
**Motivation:** Need upgrade scripts for `v1.9.0`. In addition, we want to simplify the amount of copy-pasting we do when writing upgrade. This PR addresses both. **Modifications:** ***v1.9.0:*** Creates two upgrade scripts: 1. `script/releases/v1.9.0-slashing-ux`: Upgrades for non destination chains 2. `script/releases/v1.9.0-slashing-ux-destination`: Upgrades for destination chains (base/base-sepolia) ***CrosschainDeployLib:*** The `CrosschainDeployLib` allows for deterministic deployments, based on a standard `empty` and `proxy` contract byte code. However, this byte code can change based off the metadata hash. In order to have reproducible deploys when metadata hash changes, we hard code the creation code for the empty and proxy contracts. *Note: There are different creation codes for mainnet and testnet environments due to the metadata hash changing between those on-chain deployments.* ***Library Helpers:*** 1. `CoreContractsDeployer`: Helper functions to deploy each implementation core contract 2. `CoreUpgradeQueueBuilder`: Helper functions to add append upgrading each proxy contract to the latest implementation 3. `TestUtils`: Reusable test helpers for deployment 4. `Env`: Updates env to have helper functions that recreate our [deployment matrix](https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#deployments) **Result:** Upgrade scripts + reusable libraries
1 parent 15bd250 commit 7a6f055

33 files changed

+3319
-71
lines changed

.github/workflows/validate-deployment-scripts.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
strategy:
1919
fail-fast: true
2020
matrix:
21-
env: [mainnet, testnet-sepolia, testnet-hoodi, testnet-base-sepolia, base]
21+
env: [mainnet, testnet-sepolia, testnet-hoodi, testnet-base-sepolia, base, preprod-hoodi]
2222

2323
steps:
2424
- uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911
@@ -66,7 +66,7 @@ jobs:
6666
- name: Validate Solidity Scripts
6767
run: |
6868
# Find all .sol files under /script/releases
69-
RELEASE_FILES=$(find script/releases -type f -name "*.sol" ! -name "Env.sol" ! -name "CrosschainDeployLib.sol" 2>/dev/null || echo "")
69+
RELEASE_FILES=$(find script/releases -type f -name "*.sol" ! -name "Env.sol" ! -name "CrosschainDeployLib.sol" ! -name "TestUtils.sol" ! -name "CoreContractsDeployer.sol" ! -name "CoreUpgradeQueueBuilder.sol" 2>/dev/null || echo "")
7070
7171
# Combine file lists
7272
FILES="$RELEASE_FILES"
@@ -91,6 +91,8 @@ jobs:
9191
RPC_URL="${{ secrets.RPC_MAINNET }}"
9292
elif [ "${{ matrix.env }}" = "base" ]; then
9393
RPC_URL="${{ secrets.RPC_BASE }}"
94+
elif [ "${{ matrix.env }}" = "preprod-hoodi" ]; then
95+
RPC_URL="${{ secrets.RPC_HOODI }}"
9496
fi
9597
9698
# Run zeus test on each file with the specified environment and RPC URL

script/deploy/multichain/create_generator_config.s.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ contract CreateGeneratorConfig is Script, Test {
1919
function run(string memory network, uint256 xCoord, uint256 yCoord) public {
2020
// Network must be preprod, testnet-sepolia, or mainnet
2121
require(
22-
_strEq(network, "preprod") || _strEq(network, "testnet-sepolia") || _strEq(network, "mainnet"),
22+
_strEq(network, "preprod-hoodi") || _strEq(network, "testnet-sepolia") || _strEq(network, "mainnet"),
2323
"Invalid network"
2424
);
2525

script/deploy/multichain/deploy_generator.s.sol.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ contract DeployGenerator is Script, Test {
2626
*
2727
*/
2828
require(
29-
_strEq(network, "preprod") || _strEq(network, "testnet-sepolia") || _strEq(network, "mainnet"),
29+
_strEq(network, "preprod-hoodi") || _strEq(network, "testnet-sepolia") || _strEq(network, "mainnet"),
3030
"Invalid network"
3131
);
3232

script/operations/update-generator/1-updateGenerator.s.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity ^0.8.12;
33

44
import "../../releases/Env.sol";
5+
import "../../releases/TestUtils.sol";
56
import {MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol";
67

78
// Types
@@ -17,6 +18,7 @@ import {stdToml} from "forge-std/StdToml.sol";
1718
* Purpose: Update the generator on a PREPROD/TESTNET environment
1819
*/
1920
contract QueueTransferProxyAdmin is MultisigBuilder {
21+
using TestUtils for *;
2022
using Env for *;
2123
using OperatorSetLib for OperatorSet;
2224
using stdToml for string;
@@ -32,8 +34,8 @@ contract QueueTransferProxyAdmin is MultisigBuilder {
3234
function testScript() public virtual {
3335
// Require that the environment is a testnet environment supported by multichain
3436
require(
35-
Env._strEq(Env.env(), "preprod") || Env._strEq(Env.env(), "testnet-sepolia")
36-
|| Env._strEq(Env.env(), "testnet-base-sepolia"),
37+
TestUtils._strEq(Env.env(), "preprod-hoodi") || TestUtils._strEq(Env.env(), "testnet-sepolia")
38+
|| TestUtils._strEq(Env.env(), "testnet-base-sepolia"),
3739
"Environment must be a preprod/testnet environment"
3840
);
3941

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import {EOADeployer} from "zeus-templates/templates/EOADeployer.sol";
5+
import "./Env.sol";
6+
7+
/**
8+
* @title CoreContractsDeployer
9+
* @notice Provides reusable helpers for deploying individual core contract implementations.
10+
* Usage:
11+
* ```solidity
12+
* vm.startBroadcast();
13+
* deployPermissionController();
14+
* deployKeyRegistrar();
15+
* vm.stopBroadcast();
16+
* ```
17+
*/
18+
abstract contract CoreContractsDeployer is EOADeployer {
19+
using Env for *;
20+
21+
/**
22+
* permissions/
23+
*/
24+
function deployPermissionController() internal onlyEOA returns (PermissionController deployed) {
25+
deployed = new PermissionController();
26+
deployImpl({name: type(PermissionController).name, deployedTo: address(deployed)});
27+
}
28+
29+
function deployKeyRegistrar() internal onlyEOA returns (KeyRegistrar deployed) {
30+
deployed = new KeyRegistrar({
31+
_permissionController: Env.proxy.permissionController(),
32+
_allocationManager: Env.proxy.allocationManager(),
33+
_version: Env.deployVersion()
34+
});
35+
deployImpl({name: type(KeyRegistrar).name, deployedTo: address(deployed)});
36+
}
37+
38+
/**
39+
* core/
40+
*/
41+
function deployAllocationManagerView() internal onlyEOA returns (AllocationManagerView deployed) {
42+
deployed = new AllocationManagerView({
43+
_delegation: Env.proxy.delegationManager(),
44+
_eigenStrategy: Env.proxy.eigenStrategy(),
45+
_DEALLOCATION_DELAY: Env.MIN_WITHDRAWAL_DELAY(),
46+
_ALLOCATION_CONFIGURATION_DELAY: Env.ALLOCATION_CONFIGURATION_DELAY()
47+
});
48+
deployImpl({name: type(AllocationManagerView).name, deployedTo: address(deployed)});
49+
}
50+
51+
function deployAllocationManager() internal onlyEOA returns (AllocationManager deployed) {
52+
deployed = new AllocationManager({
53+
_allocationManagerView: Env.impl.allocationManagerView(),
54+
_delegation: Env.proxy.delegationManager(),
55+
_eigenStrategy: Env.proxy.eigenStrategy(),
56+
_pauserRegistry: Env.impl.pauserRegistry(),
57+
_permissionController: Env.proxy.permissionController(),
58+
_DEALLOCATION_DELAY: Env.MIN_WITHDRAWAL_DELAY(),
59+
_ALLOCATION_CONFIGURATION_DELAY: Env.ALLOCATION_CONFIGURATION_DELAY()
60+
});
61+
deployImpl({name: type(AllocationManager).name, deployedTo: address(deployed)});
62+
}
63+
64+
function deployAVSDirectory() internal onlyEOA returns (AVSDirectory deployed) {
65+
deployed = new AVSDirectory({
66+
_delegation: Env.proxy.delegationManager(),
67+
_pauserRegistry: Env.impl.pauserRegistry(),
68+
_version: Env.deployVersion()
69+
});
70+
deployImpl({name: type(AVSDirectory).name, deployedTo: address(deployed)});
71+
}
72+
73+
function deployDelegationManager() internal onlyEOA returns (DelegationManager deployed) {
74+
deployed = new DelegationManager({
75+
_strategyManager: Env.proxy.strategyManager(),
76+
_eigenPodManager: Env.proxy.eigenPodManager(),
77+
_allocationManager: Env.proxy.allocationManager(),
78+
_pauserRegistry: Env.impl.pauserRegistry(),
79+
_permissionController: Env.proxy.permissionController(),
80+
_MIN_WITHDRAWAL_DELAY: Env.MIN_WITHDRAWAL_DELAY(),
81+
_version: Env.deployVersion()
82+
});
83+
deployImpl({name: type(DelegationManager).name, deployedTo: address(deployed)});
84+
}
85+
86+
function deployProtocolRegistry() internal onlyEOA returns (ProtocolRegistry deployed) {
87+
deployed = new ProtocolRegistry();
88+
deployImpl({name: type(ProtocolRegistry).name, deployedTo: address(deployed)});
89+
}
90+
91+
function deployReleaseManager() internal onlyEOA returns (ReleaseManager deployed) {
92+
deployed = new ReleaseManager({_permissionController: Env.proxy.permissionController()});
93+
deployImpl({name: type(ReleaseManager).name, deployedTo: address(deployed)});
94+
}
95+
96+
function deployRewardsCoordinator() internal onlyEOA returns (RewardsCoordinator deployed) {
97+
deployed = new RewardsCoordinator({
98+
params: IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams({
99+
delegationManager: Env.proxy.delegationManager(),
100+
strategyManager: Env.proxy.strategyManager(),
101+
allocationManager: Env.proxy.allocationManager(),
102+
pauserRegistry: Env.impl.pauserRegistry(),
103+
permissionController: Env.proxy.permissionController(),
104+
CALCULATION_INTERVAL_SECONDS: Env.CALCULATION_INTERVAL_SECONDS(),
105+
MAX_REWARDS_DURATION: Env.MAX_REWARDS_DURATION(),
106+
MAX_RETROACTIVE_LENGTH: Env.MAX_RETROACTIVE_LENGTH(),
107+
MAX_FUTURE_LENGTH: Env.MAX_FUTURE_LENGTH(),
108+
GENESIS_REWARDS_TIMESTAMP: Env.GENESIS_REWARDS_TIMESTAMP()
109+
})
110+
});
111+
deployImpl({name: type(RewardsCoordinator).name, deployedTo: address(deployed)});
112+
}
113+
114+
function deployStrategyManager() internal onlyEOA returns (StrategyManager deployed) {
115+
deployed = new StrategyManager({
116+
_allocationManager: Env.proxy.allocationManager(),
117+
_delegation: Env.proxy.delegationManager(),
118+
_pauserRegistry: Env.impl.pauserRegistry(),
119+
_version: Env.deployVersion()
120+
});
121+
deployImpl({name: type(StrategyManager).name, deployedTo: address(deployed)});
122+
}
123+
124+
/**
125+
* pods/
126+
*/
127+
function deployEigenPodManager() internal onlyEOA returns (EigenPodManager deployed) {
128+
deployed = new EigenPodManager({
129+
_ethPOS: Env.ethPOS(),
130+
_eigenPodBeacon: Env.beacon.eigenPod(),
131+
_delegationManager: Env.proxy.delegationManager(),
132+
_pauserRegistry: Env.impl.pauserRegistry()
133+
});
134+
deployImpl({name: type(EigenPodManager).name, deployedTo: address(deployed)});
135+
}
136+
137+
function deployEigenPod() internal onlyEOA returns (EigenPod deployed) {
138+
deployed = new EigenPod({_ethPOS: Env.ethPOS(), _eigenPodManager: Env.proxy.eigenPodManager()});
139+
deployImpl({name: type(EigenPod).name, deployedTo: address(deployed)});
140+
}
141+
142+
/**
143+
* strategies/
144+
*/
145+
function deployEigenStrategy() internal onlyEOA returns (EigenStrategy deployed) {
146+
deployed = new EigenStrategy({
147+
_strategyManager: Env.proxy.strategyManager(),
148+
_pauserRegistry: Env.impl.pauserRegistry()
149+
});
150+
deployImpl({name: type(EigenStrategy).name, deployedTo: address(deployed)});
151+
}
152+
153+
function deployStrategyBase() internal onlyEOA returns (StrategyBase deployed) {
154+
deployed = new StrategyBase({
155+
_strategyManager: Env.proxy.strategyManager(),
156+
_pauserRegistry: Env.impl.pauserRegistry()
157+
});
158+
deployImpl({name: type(StrategyBase).name, deployedTo: address(deployed)});
159+
}
160+
161+
function deployStrategyBaseTVLLimits() internal onlyEOA returns (StrategyBaseTVLLimits deployed) {
162+
deployed = new StrategyBaseTVLLimits({
163+
_strategyManager: Env.proxy.strategyManager(),
164+
_pauserRegistry: Env.impl.pauserRegistry()
165+
});
166+
deployImpl({name: type(StrategyBaseTVLLimits).name, deployedTo: address(deployed)});
167+
}
168+
169+
function deployStrategyFactory() internal onlyEOA returns (StrategyFactory deployed) {
170+
deployed = new StrategyFactory({
171+
_strategyManager: Env.proxy.strategyManager(),
172+
_pauserRegistry: Env.impl.pauserRegistry()
173+
});
174+
deployImpl({name: type(StrategyFactory).name, deployedTo: address(deployed)});
175+
}
176+
177+
/**
178+
* multichain/
179+
*/
180+
function deployBN254CertificateVerifier() internal onlyEOA returns (BN254CertificateVerifier deployed) {
181+
deployed = new BN254CertificateVerifier({_operatorTableUpdater: Env.proxy.operatorTableUpdater()});
182+
deployImpl({name: type(BN254CertificateVerifier).name, deployedTo: address(deployed)});
183+
}
184+
185+
function deployCrossChainRegistry() internal onlyEOA returns (CrossChainRegistry deployed) {
186+
deployed = new CrossChainRegistry({
187+
_allocationManager: Env.proxy.allocationManager(),
188+
_keyRegistrar: Env.proxy.keyRegistrar(),
189+
_permissionController: Env.proxy.permissionController(),
190+
_pauserRegistry: Env.impl.pauserRegistry()
191+
});
192+
deployImpl({name: type(CrossChainRegistry).name, deployedTo: address(deployed)});
193+
}
194+
195+
function deployECDSACertificateVerifier() internal onlyEOA returns (ECDSACertificateVerifier deployed) {
196+
deployed = new ECDSACertificateVerifier({
197+
_operatorTableUpdater: Env.proxy.operatorTableUpdater(),
198+
_version: Env.deployVersion()
199+
});
200+
deployImpl({name: type(ECDSACertificateVerifier).name, deployedTo: address(deployed)});
201+
}
202+
203+
function deployOperatorTableUpdater() internal onlyEOA returns (OperatorTableUpdater deployed) {
204+
deployed = new OperatorTableUpdater({
205+
_bn254CertificateVerifier: Env.proxy.bn254CertificateVerifier(),
206+
_ecdsaCertificateVerifier: Env.proxy.ecdsaCertificateVerifier(),
207+
_pauserRegistry: Env.impl.pauserRegistry()
208+
});
209+
deployImpl({name: type(OperatorTableUpdater).name, deployedTo: address(deployed)});
210+
}
211+
212+
/**
213+
* avs/
214+
*/
215+
function deployTaskMailbox() internal onlyEOA returns (TaskMailbox deployed) {
216+
deployed = new TaskMailbox({
217+
_bn254CertificateVerifier: address(Env.proxy.bn254CertificateVerifier()),
218+
_ecdsaCertificateVerifier: address(Env.proxy.ecdsaCertificateVerifier()),
219+
_maxTaskSLA: Env.MAX_TASK_SLA()
220+
});
221+
deployImpl({name: type(TaskMailbox).name, deployedTo: address(deployed)});
222+
}
223+
}

0 commit comments

Comments
 (0)