Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"init_paused_status": 0
},
"eigenPod": {
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": 32000000000000000000,
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": 32000000000,
"GENESIS_TIME": 1695902400
},
"eigenPodManager": {
Expand Down
46 changes: 46 additions & 0 deletions script/configs/mainnet/M2_mainnet_upgrade.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"chainInfo": {
"chainId": 1
},
"multisig_addresses": {
"communityMultisig": "0xFEA47018D632A77bA579846c840d5706705Dc598",
"executorMultisig": "0x369e6F597e22EaB55fFb173C6d9cD234BD699111",
"operationsMultisig": "0xBE1685C81aA44FF9FB319dD389addd9374383e90",
"pauserMultisig": "0x5050389572f2d220ad927CcbeA0D406831012390",
"timelock": "0xA6Db1A8C5a981d1536266D2a393c5F8dDb210EAF"
},
"strategies": {
"numStrategies": 0,
"MAX_PER_DEPOSIT": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
"MAX_TOTAL_DEPOSITS": 115792089237316195423570985008687907853269984665640564039457584007913129639935,
"strategiesToDeploy": []
},
"strategyManager": {
"init_strategy_whitelister": "0xBE1685C81aA44FF9FB319dD389addd9374383e90",
"init_paused_status": 1
},
"delegationManager": {
"init_paused_status": 0,
"init_minWithdrawalDelayBlocks": 50400
},
"avsDirectory": {
"init_paused_status": 0
},
"slasher": {
"init_paused_status": 115792089237316195423570985008687907853269984665640564039457584007913129639935
},
"eigenPod": {
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": 32000000000,
"GENESIS_TIME": 1606824023
},
"eigenPodManager": {
"init_paused_status": 0,
"deneb_fork_timestamp": "1710338135"
},
"delayedWithdrawalRouter": {
"init_paused_status": 0,
"init_withdrawalDelayBlocks": 50400
},
"ethPOSDepositAddress": "0x00000000219ab540356cBB839Cbe05303d7705Fa",
"beaconOracleAddress": "0x343907185b71aDF0eBa9567538314396aa985442"
}
306 changes: 306 additions & 0 deletions script/deploy/mainnet/M2_Mainnet_Upgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

import "../../utils/ExistingDeploymentParser.sol";
import "../../utils/TimelockEncoding.sol";
import "../../utils/Multisend.sol";

/**
* @notice Script used for the first deployment of EigenLayer core contracts to Holesky
* anvil --fork-url $RPC_MAINNET
* forge script script/deploy/mainnet/M2_Mainnet_Upgrade.s.sol:M2_Mainnet_Upgrade --rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast -vvvv
*
* forge script script/deploy/mainnet/M2_Mainnet_Upgrade.s.sol:M2_Mainnet_Upgrade --rpc-url $RPC_MAINNET --private-key $PRIVATE_KEY --broadcast -vvvv
*
*/
contract M2_Mainnet_Upgrade is ExistingDeploymentParser {
function run() external virtual {
_parseDeployedContracts("script/output/mainnet/M1_deployment_mainnet_2023_6_9.json");
_parseInitialDeploymentParams("script/configs/mainnet/M2_mainnet_upgrade.config.json");

// START RECORDING TRANSACTIONS FOR DEPLOYMENT
vm.startBroadcast();

emit log_named_address("Deployer Address", msg.sender);

_deployImplementationContracts();

// STOP RECORDING TRANSACTIONS FOR DEPLOYMENT
vm.stopBroadcast();

// Simulate upgrade of contracts to new implementations
_simulateUpgrade();

// Sanity Checks
_verifyContractPointers();
_verifyImplementations();
_verifyContractsInitialized({isInitialDeployment: true});
_verifyInitializationParams();

logAndOutputContractAddresses("script/output/mainnet/M2_mainnet_upgrade.output.json");
}

/**
* @notice Deploy EigenLayer contracts from scratch for Holesky
*/
function _deployImplementationContracts() internal {
// 1. Deploy New TUPS
avsDirectoryImplementation = new AVSDirectory(delegationManager);
avsDirectory = AVSDirectory(
address(
new TransparentUpgradeableProxy(
address(avsDirectoryImplementation),
address(eigenLayerProxyAdmin),
abi.encodeWithSelector(
AVSDirectory.initialize.selector,
executorMultisig, // initialOwner
eigenLayerPauserReg,
AVS_DIRECTORY_INIT_PAUSED_STATUS
)
)
)
);

// 2. Deploy Implementations
eigenPodImplementation = new EigenPod(
IETHPOSDeposit(ETHPOSDepositAddress),
delayedWithdrawalRouter,
eigenPodManager,
EIGENPOD_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR,
EIGENPOD_GENESIS_TIME
);
delegationManagerImplementation = new DelegationManager(strategyManager, slasher, eigenPodManager);
strategyManagerImplementation = new StrategyManager(delegationManager, eigenPodManager, slasher);
slasherImplementation = new Slasher(strategyManager, delegationManager);
eigenPodManagerImplementation = new EigenPodManager(
IETHPOSDeposit(ETHPOSDepositAddress),
eigenPodBeacon,
strategyManager,
slasher,
delegationManager
);
delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter(eigenPodManager);
}

function _simulateUpgrade() internal {

vm.startPrank(executorMultisig);

// First, upgrade the proxy contracts to point to the implementations
// AVSDirectory
// eigenLayerProxyAdmin.upgrade(
// TransparentUpgradeableProxy(payable(address(avsDirectory))),
// address(avsDirectoryImplementation)
// );
// DelegationManager
eigenLayerProxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(delegationManager))),
address(delegationManagerImplementation)
);
// StrategyManager
eigenLayerProxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(strategyManager))),
address(strategyManagerImplementation)
);
// Slasher
eigenLayerProxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(slasher))),
address(slasherImplementation)
);
// EigenPodManager
eigenLayerProxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(eigenPodManager))),
address(eigenPodManagerImplementation)
);
// Delayed Withdrawal Router
eigenLayerProxyAdmin.upgrade(
TransparentUpgradeableProxy(payable(address(delayedWithdrawalRouter))),
address(delayedWithdrawalRouterImplementation)
);

// Second, configure additional settings and paused statuses
delegationManager.setMinWithdrawalDelayBlocks(DELEGATION_MANAGER_MIN_WITHDRAWAL_DELAY_BLOCKS);
delegationManager.unpause(0);
eigenPodManager.unpause(0);

eigenPodManager.setDenebForkTimestamp(EIGENPOD_MANAGER_DENEB_FORK_TIMESTAMP);
eigenPodManager.updateBeaconChainOracle(beaconOracle);
eigenPodBeacon.upgradeTo(address(eigenPodImplementation));

vm.stopPrank();
}
}

// forge t --mt test_queueUpgrade --fork-url $RPC_MAINNET -vvvv
contract Queue_M2_Upgrade is M2_Mainnet_Upgrade, TimelockEncoding {
Vm cheats = Vm(HEVM_ADDRESS);

// Thurs Apr 04 2024 12:00:00 GMT-0700 (Pacific Daylight Time)
uint256 timelockEta = 1712214000;

function test_queueUpgrade() external {
_parseDeployedContracts("script/output/mainnet/M1_deployment_mainnet_2023_6_9.json");
_parseInitialDeploymentParams("script/configs/mainnet/M2_mainnet_upgrade.config.json");

// TODO: fill in correct addresses
// simulate deploying contracts
_deployImplementationContracts();

Tx[] memory txs = new Tx[](11);
// upgrade the DelegationManager, Slasher, StrategyManager, DelayedWithdrawalRouter, EigenPodManager, & EigenPod contracts
txs[0] = Tx(
address(eigenLayerProxyAdmin),
0,
abi.encodeWithSelector(
ProxyAdmin.upgrade.selector,
TransparentUpgradeableProxy(payable(address(delegationManager))),
delegationManagerImplementation
)
);

txs[1] = Tx(
address(eigenLayerProxyAdmin),
0,
abi.encodeWithSelector(
ProxyAdmin.upgrade.selector,
TransparentUpgradeableProxy(payable(address(slasher))),
slasherImplementation
)
);

txs[2] = Tx(
address(eigenLayerProxyAdmin),
0,
abi.encodeWithSelector(
ProxyAdmin.upgrade.selector,
TransparentUpgradeableProxy(payable(address(strategyManager))),
strategyManagerImplementation
)
);

txs[3] = Tx(
address(eigenLayerProxyAdmin),
0,
abi.encodeWithSelector(
ProxyAdmin.upgrade.selector,
TransparentUpgradeableProxy(payable(address(delayedWithdrawalRouter))),
delayedWithdrawalRouterImplementation
)
);

txs[4] = Tx(
address(eigenLayerProxyAdmin),
0,
abi.encodeWithSelector(
ProxyAdmin.upgrade.selector,
TransparentUpgradeableProxy(payable(address(eigenPodManager))),
eigenPodManagerImplementation
)
);

txs[5] = Tx(
address(eigenPodBeacon),
0,
abi.encodeWithSelector(
UpgradeableBeacon.upgradeTo.selector,
eigenPodImplementation
)
);

// set the min withdrawal delay blocks on the DelegationManager
txs[6] = Tx(
address(delegationManager),
0, // value
abi.encodeWithSelector(DelegationManager.setMinWithdrawalDelayBlocks.selector, DELEGATION_MANAGER_MIN_WITHDRAWAL_DELAY_BLOCKS)
);

// set beacon chain oracle on EigenPodManager
txs[7] = Tx(
address(eigenPodManager),
0, // value
abi.encodeWithSelector(EigenPodManager.updateBeaconChainOracle.selector, beaconOracle)
);

// set Deneb fork timestamp on EigenPodManager
txs[8] = Tx(
address(eigenPodManager),
0, // value
abi.encodeWithSelector(EigenPodManager.setDenebForkTimestamp.selector, EIGENPOD_MANAGER_DENEB_FORK_TIMESTAMP)
);

// unpause everything on DelegationManager
txs[9] = Tx(
address(delegationManager),
0, // value
abi.encodeWithSelector(Pausable.unpause.selector, 0)
);

// unpause everything on EigenPodManager
txs[10] = Tx(
address(eigenPodManager),
0, // value
abi.encodeWithSelector(Pausable.unpause.selector, 0)
);

bytes memory calldata_to_multisend_contract = abi.encodeWithSelector(MultiSendCallOnly.multiSend.selector, encodeMultisendTxs(txs));
emit log_named_bytes("calldata_to_multisend_contract", calldata_to_multisend_contract);

bytes memory final_calldata_to_executor_multisig = encodeForExecutor({
// call to executor will be from the timelock
from: timelock,
// performing many operations at the same time
to: multiSendCallOnly,
// value to send in tx
value: 0,
// calldata for the operation
data: calldata_to_multisend_contract,
// operation type (for performing many operations at the same time)
operation: ISafe.Operation.DelegateCall
});

(bytes memory calldata_to_timelock_queuing_action, bytes memory calldata_to_timelock_executing_action) = encodeForTimelock({
// address to be called from the timelock
to: executorMultisig,
// value to send in tx
value: 0,
// calldata for the operation
data: final_calldata_to_executor_multisig,
// time at which the tx will become executable
timelockEta: timelockEta

});

bytes32 expectedTxHash = getTxHash({
target: executorMultisig,
_value: 0,
_data: final_calldata_to_executor_multisig,
eta: timelockEta
});
emit log_named_bytes32("expectedTxHash", expectedTxHash);

cheats.prank(operationsMultisig);
(bool success, ) = timelock.call(calldata_to_timelock_queuing_action);
require(success, "call to timelock queuing action failed");

require(ITimelock(timelock).queuedTransactions(expectedTxHash), "expectedTxHash not queued");

// test performing the upgrade
cheats.warp(timelockEta);
cheats.prank(operationsMultisig);
(success, ) = timelock.call(calldata_to_timelock_executing_action);
require(success, "call to timelock executing action failed");

// Check correctness after upgrade
_verifyContractPointers();
_verifyImplementations();
_verifyContractsInitialized({isInitialDeployment: true});
_verifyInitializationParams();
}

function getTxHash(address target, uint256 _value, bytes memory _data, uint256 eta) public pure returns (bytes32) {
// empty bytes
bytes memory signature;
bytes32 txHash = keccak256(abi.encode(target, _value, signature, _data, eta));
return txHash;
}
}
3 changes: 3 additions & 0 deletions script/output/mainnet/M1_deployment_mainnet_2023_6_9.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"addresses": {
"avsDirectory": "0x0000000000000000000000000000000000000000",
"avsDirectoryImplementation": "0x0000000000000000000000000000000000000000",
"baseStrategyImplementation": "0xdfdA04f980bE6A64E3607c95Ca26012Ab9aA46d3",
"beaconOracleAddress": "0x0000000000000000000000000000000000000000",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be non-zero? I get that the avsDirectory is set to the zero address because it is not deployed yet.
I would guess that this doesn't matter, just searching for anything, honestly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes I added this because the _parseDeployedContracts helper will throw an error when trying to parse it out. It was used for the holesky deployment so I added these 0 addresses here based on the current mainnet state.
The beaconOracle address gets overwritten when _parseInitialDeploymentParams is called right after.

"delayedWithdrawalRouter": "0x7Fe7E9CC0F274d2435AD5d56D5fa73E47F6A23D8",
"delayedWithdrawalRouterImplementation": "0x44Bcb0E01CD0C5060D4Bb1A07b42580EF983E2AF",
"delegation": "0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A",
Expand Down
Loading