diff --git a/script/Release.s.sol b/script/Release.s.sol index 7882f85e6..11d29e440 100644 --- a/script/Release.s.sol +++ b/script/Release.s.sol @@ -1,260 +1,260 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.12; - -import "./utils/Releasoor.s.sol"; -import "./utils/Encoders.sol"; - -contract Release is Releasoor { - - using TxBuilder for *; - using AddressUtils for *; - - struct ReleaseStep { - function () external step; - } - - // Public, standard release: - // - EOA deploy - // - queue/execute via ops multisig/timelock - function manifest() public returns (ReleaseStep[] memory steps) { - return _newRelease(ReleaseType.OPS_TIMELOCK) - .append(this.deploy) - .append(this.queueUpgrade) - .wait(10 days) - .append(this.executeUpgrade); - } - - // Private, emergency release: - // - EOA deploy - // - execute instantly via community msig - function manifest() public returns (ReleaseStep[] memory steps) { - return _newRelease(ReleaseType.COMMUNITY_MSIG) - .append(this.deploy) - .append(this.executeUpgrade); - } - - struct Deployment { - string name; - address deployedTo; - } - - function deploy( - Addresses memory addrs, - Environment memory env, - Params memory params - ) internal override returns (Deployment[] memory deployments) { - - - vm.startBroadcast(); - - deployments[0] = Deployment({ - name: type(EigenPod).name, - address: address(new EigenPod( - IETHPOSDeposit(params.ethPOS), - IEigenPodManager(addrs.eigenPodManager.proxy), - params.EIGENPOD_GENESIS_TIME - )) - }); - - EigenPodManager newEPMImpl = new EigenPodManager( - IETHPOSDeposit(params.ethPOS), - IUpgradeableBeacon(addrs.eigenPod.beacon), - IStrategyManager(addrs.strategyManager.proxy), - ISlasher(addrs.slasher.proxy), - IDelegationManager(addrs.delegationManager.proxy) - ); - - vm.stopBroadcast(); - - type(EigenPod).contractName; - - - - _logDeploy(EIGENPOD, address(newEigenPodImpl)); - - // addrs.eigenPod.setPending(address(newEigenPodImpl)); - // addrs.eigenPodManager.setPending(address(newEPMImpl)); - } - - function queueUpgrade(Addresses memory addrs) internal override { - Txs storage txns = _newTxs(); - eta = env.isMainnet() ? 12351235 : 0; - - txns.append({ - to: addrs.eigenPod.beacon, - data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) - }); - - txns.append({ - to: addrs.proxyAdmin, - data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) - }); - - ( - bytes memory calldata_to_timelock_queueing_action, - bytes memory calldata_to_timelock_executing_action, - bytes memory final_calldata_to_executor_multisig - ) = EncTimelock.queueTransaction({ - timelock: addrs.timelock, - multisend: params.multiSendCallOnly, - executor: addrs.executorMultisig, - executorTxns: txns, - eta: eta - }); - - _log("calldata_to_timelock_queueing_action", calldata_to_timelock_queueing_action); - _log("calldata_to_timelock_executing_action", calldata_to_timelock_executing_action); - _log("final_calldata_to_executor_multisig", final_calldata_to_executor_multisig); - - vm.startBroadcast(addrs.operationsMultisig); - - (success, ) = addrs.timelock.call(calldata_to_timelock_queueing_action); - require(success, "queueing transaction in timelock failed"); - - vm.stopBroadcast(); - } - - function executeUpgrade(Addresses memory addrs) internal override { - Txs storage txs = _newTxs(); - - txs.append({ - to: addrs.eigenPod.beacon, - data: EncUpgradeableBeacon.upgradeTo(addrs.eigenPod.getPending()) - }); - - txs.append({ - to: addrs.eigenPodManager.proxy, - data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) - }); - - bytes memory calldata_to_multisend_contract = EncMultiSendCallOnly.multiSend(txs); - - bytes memory final_calldata_to_executor_multisig = EncGnosisSafe.execTransaction({ - from: addrs.timelock, - to: params.multiSendCallOnly, - data: calldata_to_multisend_contract, - op: EncGnosisSafe.Operation.DelegateCall - }); - - bytes memory calldata_to_timelock_executing_action = EncTimelock.executeTransaction({ - target: addrs.executorMultisig, - data: final_calldata_to_executor_multisig, - eta: 0 - }); - - emit log_named_bytes("calldata_to_timelock_executing_action", calldata_to_timelock_executing_action); - - Txs storage txns = _newTxs(); - - txns.append({ - to: addrs.timelock, - data: calldata_to_timelock_executing_action - }); - - txns.append({ - to: addrs.strategyFactory.proxy, - data: EncStrategyFactory.whitelistStrategies(strats) - }); - - txns.broadcastFrom(addrs.opsMultisig); - - // Update config - addrs.eigenPod.updateFromPending(); - addrs.eigenPodManager.updateFromPending(); - } - - function queueUpgrade(Addresses memory addrs) internal override returns (Txns storage) { - Txns storage txns = addrs.opsMultisig.queueTimelock({ - timelock: addrs.timelock, - eta: 0, - _txns: addrs.executorMultisig - .append({ - to: addrs.strategyManager.proxy, - data: EncStrategyManager.setStrategyWhitelister(addrs.opsMultisig) - }) - .append({ - to: addrs.eigenPod.beacon, - data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) - }) - .append({ - to: addrs.proxyAdmin, - data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) - }) - .asSafeExecTxn(); - }); - - txns.printSummary(); - - return txns; - } - - function executeUpgrade(Addresses memory addrs) internal override returns (Txns storage) { - Txns storage txns = addrs.opsMultisig.executeTimelock({ - timelock: addrs.timelock, - eta: 0, - to: addrs.executorMultisig, - data: addrs.executorMultisig - .append({ - to: addrs.strategyManager.proxy, - data: EncStrategyManager.setStrategyWhitelister(addrs.opsMultisig) - }) - .append({ - to: addrs.eigenPod.beacon, - data: EncBeacon.upgradeTo(addrs.eigenPod.pendingImpl) - }) - .append({ - to: addrs.proxyAdmin, - data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.pendingImpl) - }) - }) - .append({ - to: addrs.strategyManager.proxy, - data: EncStrategyManager.addStrategiesToDepositWhitelist(strats, bools) - }); - - txns.printSummary(); - - // Update config - addrs.eigenPod.updateFromPending(); - addrs.eigenPodManager.updateFromPending(); - - return txns; - } - - // function _deployPEPE(Addresses memory addrs) internal returns (EigenPod, EigenPodManager) { - // // Deploy EigenPod - // eigenPodImplementation = new EigenPod( - // IETHPOSDeposit(cfg.ETHPOSDepositAddress), - // IEigenPodManager(addrs.eigenPodManager.proxy), - // cfg.EIGENPOD_GENESIS_TIME - // ); - - // // Deploy EigenPodManager - // eigenPodManagerImplementation = new EigenPodManager( - // IETHPOSDeposit(cfg.ETHPOSDepositAddress), - // IBeacon(addrs.eigenPodBeacon.beacon), - // IStrategyManager(addrs.strategyManager.proxy), - // ISlasher(addrs.slasher.proxy), - // IDelegationManager(addrs.delegationManager.proxy) - // ); - - // return (eigenPodImplementation, eigenPodManagerImplementation); - // } - - // function test_Release() public { - // _readEnvironment(ENV_MAINNET); - - // _printAddrs(); - // emit log("====="); - - // _readEnvironment(ENV_HOLESKY); - - // _printAddrs(); - // emit log("====="); - - // _readEnvironment(ENV_PREPROD); - - // _printAddrs(); - // emit log("====="); - // } -} +// // SPDX-License-Identifier: BUSL-1.1 +// pragma solidity ^0.8.12; + +// import "./utils/Releasoor.s.sol"; +// import "./utils/Encoders.sol"; + +// contract Release is Releasoor { + +// using TxBuilder for *; +// using AddressUtils for *; + +// struct ReleaseStep { +// function () external step; +// } + +// // Public, standard release: +// // - EOA deploy +// // - queue/execute via ops multisig/timelock +// function manifest() public returns (ReleaseStep[] memory steps) { +// return _newRelease(ReleaseType.OPS_TIMELOCK) +// .append(this.deploy) +// .append(this.queueUpgrade) +// .wait(10 days) +// .append(this.executeUpgrade); +// } + +// // Private, emergency release: +// // - EOA deploy +// // - execute instantly via community msig +// function manifest() public returns (ReleaseStep[] memory steps) { +// return _newRelease(ReleaseType.COMMUNITY_MSIG) +// .append(this.deploy) +// .append(this.executeUpgrade); +// } + +// struct Deployment { +// string name; +// address deployedTo; +// } + +// function deploy( +// Addresses memory addrs, +// Environment memory env, +// Params memory params +// ) internal override returns (Deployment[] memory deployments) { + + +// vm.startBroadcast(); + +// deployments[0] = Deployment({ +// name: type(EigenPod).name, +// deployedTo: address(new EigenPod( +// IETHPOSDeposit(params.ethPOS), +// IEigenPodManager(addrs.eigenPodManager.proxy), +// params.EIGENPOD_GENESIS_TIME +// )) +// }); + +// EigenPodManager newEPMImpl = new EigenPodManager( +// IETHPOSDeposit(params.ethPOS), +// IUpgradeableBeacon(addrs.eigenPod.beacon), +// IStrategyManager(addrs.strategyManager.proxy), +// ISlasher(addrs.slasher.proxy), +// IDelegationManager(addrs.delegationManager.proxy) +// ); + +// vm.stopBroadcast(); + +// type(EigenPod).contractName; + + + +// _logDeploy(EIGENPOD, address(newEigenPodImpl)); + +// // addrs.eigenPod.setPending(address(newEigenPodImpl)); +// // addrs.eigenPodManager.setPending(address(newEPMImpl)); +// } + +// function queueUpgrade(Addresses memory addrs) internal override { +// Txs storage txns = _newTxs(); +// eta = env.isMainnet() ? 12351235 : 0; + +// txns.append({ +// to: addrs.eigenPod.beacon, +// data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) +// }); + +// txns.append({ +// to: addrs.proxyAdmin, +// data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) +// }); + +// ( +// bytes memory calldata_to_timelock_queueing_action, +// bytes memory calldata_to_timelock_executing_action, +// bytes memory final_calldata_to_executor_multisig +// ) = EncTimelock.queueTransaction({ +// timelock: addrs.timelock, +// multisend: params.multiSendCallOnly, +// executor: addrs.executorMultisig, +// executorTxns: txns, +// eta: eta +// }); + +// _log("calldata_to_timelock_queueing_action", calldata_to_timelock_queueing_action); +// _log("calldata_to_timelock_executing_action", calldata_to_timelock_executing_action); +// _log("final_calldata_to_executor_multisig", final_calldata_to_executor_multisig); + +// vm.startBroadcast(addrs.operationsMultisig); + +// (success, ) = addrs.timelock.call(calldata_to_timelock_queueing_action); +// require(success, "queueing transaction in timelock failed"); + +// vm.stopBroadcast(); +// } + +// function executeUpgrade(Addresses memory addrs) internal override { +// Txs storage txs = _newTxs(); + +// txs.append({ +// to: addrs.eigenPod.beacon, +// data: EncUpgradeableBeacon.upgradeTo(addrs.eigenPod.getPending()) +// }); + +// txs.append({ +// to: addrs.eigenPodManager.proxy, +// data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) +// }); + +// bytes memory calldata_to_multisend_contract = EncMultiSendCallOnly.multiSend(txs); + +// bytes memory final_calldata_to_executor_multisig = EncGnosisSafe.execTransaction({ +// from: addrs.timelock, +// to: params.multiSendCallOnly, +// data: calldata_to_multisend_contract, +// op: EncGnosisSafe.Operation.DelegateCall +// }); + +// bytes memory calldata_to_timelock_executing_action = EncTimelock.executeTransaction({ +// target: addrs.executorMultisig, +// data: final_calldata_to_executor_multisig, +// eta: 0 +// }); + +// emit log_named_bytes("calldata_to_timelock_executing_action", calldata_to_timelock_executing_action); + +// Txs storage txns = _newTxs(); + +// txns.append({ +// to: addrs.timelock, +// data: calldata_to_timelock_executing_action +// }); + +// txns.append({ +// to: addrs.strategyFactory.proxy, +// data: EncStrategyFactory.whitelistStrategies(strats) +// }); + +// txns.broadcastFrom(addrs.opsMultisig); + +// // Update config +// addrs.eigenPod.updateFromPending(); +// addrs.eigenPodManager.updateFromPending(); +// } + +// function queueUpgrade(Addresses memory addrs) internal override returns (Txns storage) { +// Txns storage txns = addrs.opsMultisig.queueTimelock({ +// timelock: addrs.timelock, +// eta: 0, +// _txns: addrs.executorMultisig +// .append({ +// to: addrs.strategyManager.proxy, +// data: EncStrategyManager.setStrategyWhitelister(addrs.opsMultisig) +// }) +// .append({ +// to: addrs.eigenPod.beacon, +// data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) +// }) +// .append({ +// to: addrs.proxyAdmin, +// data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) +// }) +// .asSafeExecTxn() +// }); + +// txns.printSummary(); + +// return txns; +// } + +// function executeUpgrade(Addresses memory addrs) internal override returns (Txns storage) { +// Txns storage txns = addrs.opsMultisig.executeTimelock({ +// timelock: addrs.timelock, +// eta: 0, +// to: addrs.executorMultisig, +// data: addrs.executorMultisig +// .append({ +// to: addrs.strategyManager.proxy, +// data: EncStrategyManager.setStrategyWhitelister(addrs.opsMultisig) +// }) +// .append({ +// to: addrs.eigenPod.beacon, +// data: EncBeacon.upgradeTo(addrs.eigenPod.pendingImpl) +// }) +// .append({ +// to: addrs.proxyAdmin, +// data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.pendingImpl) +// }) +// }) +// .append({ +// to: addrs.strategyManager.proxy, +// data: EncStrategyManager.addStrategiesToDepositWhitelist(strats, bools) +// }); + +// txns.printSummary(); + +// // Update config +// addrs.eigenPod.updateFromPending(); +// addrs.eigenPodManager.updateFromPending(); + +// return txns; +// } + +// // function _deployPEPE(Addresses memory addrs) internal returns (EigenPod, EigenPodManager) { +// // // Deploy EigenPod +// // eigenPodImplementation = new EigenPod( +// // IETHPOSDeposit(cfg.ETHPOSDepositAddress), +// // IEigenPodManager(addrs.eigenPodManager.proxy), +// // cfg.EIGENPOD_GENESIS_TIME +// // ); + +// // // Deploy EigenPodManager +// // eigenPodManagerImplementation = new EigenPodManager( +// // IETHPOSDeposit(cfg.ETHPOSDepositAddress), +// // IBeacon(addrs.eigenPodBeacon.beacon), +// // IStrategyManager(addrs.strategyManager.proxy), +// // ISlasher(addrs.slasher.proxy), +// // IDelegationManager(addrs.delegationManager.proxy) +// // ); + +// // return (eigenPodImplementation, eigenPodManagerImplementation); +// // } + +// // function test_Release() public { +// // _readEnvironment(ENV_MAINNET); + +// // _printAddrs(); +// // emit log("====="); + +// // _readEnvironment(ENV_HOLESKY); + +// // _printAddrs(); +// // emit log("====="); + +// // _readEnvironment(ENV_PREPROD); + +// // _printAddrs(); +// // emit log("====="); +// // } +// } diff --git a/script/Release_Template.s.sol b/script/Release_Template.s.sol index 893f9a583..7f21420b0 100644 --- a/script/Release_Template.s.sol +++ b/script/Release_Template.s.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.12; import "script/utils/ConfigParser.sol"; +import "script/utils/EncodeSafeMultisendMainnet.sol"; import {EncGnosisSafe} from "script/utils/Encoders.sol"; /// @notice Deployment data struct @@ -19,9 +20,10 @@ struct Transaction { EncGnosisSafe.Operation op; } +/// TODO: break all abstract contracts out into their own file in a `template` directory + /// @notice template for an EOA script abstract contract EOABuilder is ConfigParser { - Deployment[] internal deployments; function deploy(string memory envPath) public returns (Deployment[] memory) { ( @@ -37,8 +39,30 @@ abstract contract EOABuilder is ConfigParser { } /// @notice template for a Multisig script -abstract contract MultisigBuilder is ConfigParser { +abstract contract MultisigBuilder is ConfigParser, EncodeSafeTransactionMainnet { + /// @return a Transaction object for a Gnosis Safe to ingest + function execute(string memory envPath) public returns (bytes memory) { + ( + Addresses memory addrs, + Environment memory env, + Params memory params + ) = _readConfigFile(envPath); + + Tx[] memory txs = _execute(addrs, env, params); + + return encodeMultisendTxs(txs); + } + + /// @notice to be implemented by inheriting contract + function _execute(Addresses memory addrs, Environment memory env, Params memory params) internal virtual returns (Tx[] memory); +} + +abstract contract NestedMultisigBuilder is ConfigParser { + + /// @return a Transaction object for a Gnosis Safe to ingest + /// @dev this object is intended to hold calldata to be sent to *yet another* Safe + /// which will contain the actual relevant calldata function execute(string memory envPath) public returns (Transaction memory) { ( Addresses memory addrs, @@ -53,11 +77,16 @@ abstract contract MultisigBuilder is ConfigParser { function _execute(Addresses memory addrs, Environment memory env, Params memory params) internal virtual returns (Transaction memory); } - /// @notice template for an OpsMultisig script that goes through the timelock -abstract contract OpsTimelockBuilder is MultisigBuilder { +abstract contract OpsTimelockBuilder is NestedMultisigBuilder { + + /// @return a Transaction object for a Gnosis Safe to ingest function queue(string memory envPath) public returns (Transaction memory) { // TODO + + // get response from _queue() + // encode for Timelock + // return encoded call for Ops Multisig } function _queue(Addresses memory addrs, Environment memory env, Params memory params) internal virtual returns (Transaction memory); diff --git a/script/ScriptTest.t.sol b/script/ScriptTest.t.sol index b9b5beec7..e3a915a7f 100644 --- a/script/ScriptTest.t.sol +++ b/script/ScriptTest.t.sol @@ -1,75 +1,75 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.12; - -import "./Release_Template.s.sol"; - -// zeus new "pepe" opsmultisig - -contract PEPE_Upgrade is OpsTimelockBuilder { - - struct TimelockData { - address target; - uint value; - string signature; - bytes data; - uint eta; - } - - function _makeTimelockData( - Addresses memory addrs, - Environment memory env, - Params memory params - ) internal override returns (TimelockData memory) { - TimelockData data = _newTimelockData(); - data.eta = env.isMainnet() ? 12351235 : 0; - - data.appendCall({ - to: addrs.eigenPod.beacon, - data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) - }); - - data.appendCall({ - to: addrs.proxyAdmin, - data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) - }); - - return data.encode(); - } - - function _queue( - Addresses memory addrs, - Environment memory env, - Params memory params - ) internal override returns (Calls[] memory) { - TimelockData memory data = _makeTimelockData(addrs, env, params); - - return opsMultisig.queue(txns); - } - - function _execute( - Addresses memory addrs, - Environment memory env, - Params memory params - ) internal override returns (Calls[]) { - TimelockTxn[] memory txns = _makeTimelockTxns(addrs, env, params); - - Calls[] memory final = opsMultsig.execute(txns) - .append({ - to: awfe - data: awef - }); - - return final; - } -} - -contract PEPE_Deploy is EOABuilder { - - function _deploy( - Addresses memory addrs, - Environment memory env, - Params memory params - ) internal override returns (Deployment[]) { - - } -} \ No newline at end of file +// // SPDX-License-Identifier: BUSL-1.1 +// pragma solidity ^0.8.12; + +// import "./Release_Template.s.sol"; + +// // zeus new "pepe" opsmultisig + +// contract PEPE_Upgrade is OpsTimelockBuilder { + +// struct TimelockData { +// address target; +// uint value; +// string signature; +// bytes data; +// uint eta; +// } + +// function _makeTimelockData( +// Addresses memory addrs, +// Environment memory env, +// Params memory params +// ) internal override returns (TimelockData memory) { +// TimelockData data = _newTimelockData(); +// data.eta = env.isMainnet() ? 12351235 : 0; + +// data.appendCall({ +// to: addrs.eigenPod.beacon, +// data: EncBeacon.upgradeTo(addrs.eigenPod.getPending()) +// }); + +// data.appendCall({ +// to: addrs.proxyAdmin, +// data: EncProxyAdmin.upgrade(addrs.eigenPodManager.proxy, addrs.eigenPodManager.getPending()) +// }); + +// return data.encode(); +// } + +// function _queue( +// Addresses memory addrs, +// Environment memory env, +// Params memory params +// ) internal override returns (Transaction memory) { +// TimelockData memory data = _makeTimelockData(addrs, env, params); + +// return opsMultisig.queue(txns); +// } + +// function _execute( +// Addresses memory addrs, +// Environment memory env, +// Params memory params +// ) internal override returns (Transaction memory) { +// TimelockTxn[] memory txns = _makeTimelockTxns(addrs, env, params); + +// Calls[] memory result = opsMultsig.execute(txns) +// .append({ +// to: awfe, +// data: awef +// }); + +// return result; +// } +// } + +// contract PEPE_Deploy is EOABuilder { + +// function _deploy( +// Addresses memory addrs, +// Environment memory env, +// Params memory params +// ) internal override returns (Deployment[]) { + +// } +// } \ No newline at end of file diff --git a/script/releases/v0.1-eigenpod/DeployEigenPod.s.sol b/script/releases/v0.1-eigenpod/DeployEigenPod.s.sol index e0e3040de..f9401c4c7 100644 --- a/script/releases/v0.1-eigenpod/DeployEigenPod.s.sol +++ b/script/releases/v0.1-eigenpod/DeployEigenPod.s.sol @@ -2,10 +2,13 @@ pragma solidity ^0.8.12; import "script/Release_Template.s.sol"; +import "src/contracts/pods/EigenPod.sol"; contract DeployEigenPod is EOABuilder { + Deployment[] internal deployments; - function _deploy(Addresses memory addrs, Environment memory env, Params memory params) internal override returns (Deployment[] memory) { + /// @notice deploys an EigenPod and returns the deployed address + function _deploy(Addresses memory addrs, Environment memory, Params memory params) internal override returns (Deployment[] memory) { deployments.push(Deployment({ name: type(EigenPod).name, diff --git a/script/releases/v0.1-eigenpod/UpgradeEigenPod.s.sol b/script/releases/v0.1-eigenpod/UpgradeEigenPod.s.sol index 7ee52f974..9b100aa72 100644 --- a/script/releases/v0.1-eigenpod/UpgradeEigenPod.s.sol +++ b/script/releases/v0.1-eigenpod/UpgradeEigenPod.s.sol @@ -5,14 +5,32 @@ import "script/Release_Template.s.sol"; contract UpgradeCounter is MultisigBuilder { - function _execute(Addresses memory addrs, Environment memory env, Params memory params) internal override returns (Transaction memory) { + function _execute(Addresses memory addrs, Environment memory env, Params memory params) internal override returns (Tx[] memory) { + Tx[] memory txs = new Tx[](2); - bytes memory calldata_to_executor; - return Transaction({ - to: addrs.timelock, + // txs[0] = Tx({ + // to: eigenPodBeacon, + // value: 0, + // data: abi.encodeWithSelector( + // IUpgradeableBeacon.upgradeTo.selector, newEigenPodImpl + // ) + // }); + + // txs[1] = Tx({ + // to: eigenLayerProxyAdmin, + // value: 0, + // data: abi.encodeWithSelector(ProxyAdmin.upgrade.selector, eigenPodManager, newEigenPodManagerImpl) + // }); + + bytes memory calldata_to_executor; // upgrade data + + Transaction({ + to: addrs.proxyAdmin, value: 0, data: calldata_to_executor, op: EncGnosisSafe.Operation.DelegateCall }); + + return txs; } } \ No newline at end of file diff --git a/script/releases/v0.4.2-pepe/Script.s.sol b/script/releases/v0.4.2-pepe/Script.s.sol index 326c99a34..127aebae0 100644 --- a/script/releases/v0.4.2-pepe/Script.s.sol +++ b/script/releases/v0.4.2-pepe/Script.s.sol @@ -1,24 +1,24 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.12; +// // SPDX-License-Identifier: BUSL-1.1 +// pragma solidity ^0.8.12; -import "./utils/Releasoor.s.sol"; +// import "./../../utils/Releasoor.s.sol"; -contract v0_4_2_ is Releasoor { +// contract v0_4_2_ is Releasoor { - using TxBuilder for *; - using AddressUtils for *; +// using TxBuilder for *; +// using AddressUtils for *; - function deploy(Addresses memory addrs) internal override { - // If you're deploying contracts, do that here - } +// function deploy(Addresses memory addrs) internal override { +// // If you're deploying contracts, do that here +// } - function queueUpgrade(Addresses memory addrs) internal override returns (Tx[] memory executorTxns, uint eta) { - // If you're queueing an upgrade via the timelock, you can - // define and encode those transactions here - } +// function queueUpgrade(Addresses memory addrs) internal override returns (Tx[] memory executorTxns, uint eta) { +// // If you're queueing an upgrade via the timelock, you can +// // define and encode those transactions here +// } - function executeUpgrade(Addresses memory addrs) internal override { - // Whether you are using the timelock or just making transactions - // from the ops multisig, you can define/encode those transactions here - } -} \ No newline at end of file +// function executeUpgrade(Addresses memory addrs) internal override { +// // Whether you are using the timelock or just making transactions +// // from the ops multisig, you can define/encode those transactions here +// } +// } \ No newline at end of file diff --git a/script/utils/EncodeSafeMultisendMainnet.sol b/script/utils/EncodeSafeMultisendMainnet.sol new file mode 100644 index 000000000..e1a27fc2e --- /dev/null +++ b/script/utils/EncodeSafeMultisendMainnet.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.12; + +import "forge-std/Script.sol"; +import "forge-std/Test.sol"; + +// script that calculates calldata input to provide to timelock to call the executor multisig and execute an action. +// in this particular case, it encodes an action where the executor multisig will call the community multisig with no data and a value of 1e9 (i.e. one gwei) + +interface ISafe { + /// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction. + /// Note: The fees are always transferred, even if the user transaction fails. + /// @param to Destination address of Safe transaction. + /// @param value Ether value of Safe transaction. + /// @param data Data payload of Safe transaction. + /// @param operation Operation type of Safe transaction. + /// @param safeTxGas Gas that should be used for the Safe transaction. + /// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund) + /// @param gasPrice Gas price that should be used for the payment calculation. + /// @param gasToken Token address (or 0 if ETH) that is used for the payment. + /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin). + /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v}) + function execTransaction( + address to, + uint256 value, + bytes calldata data, + uint8 operation, + uint256 safeTxGas, + uint256 baseGas, + uint256 gasPrice, + address gasToken, + address payable refundReceiver, + bytes memory signatures + ) external; +} + +interface ITimelock { + function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external returns (bytes32); + /* + { + require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin."); + require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay."); + + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + queuedTransactions[txHash] = true; + + emit QueueTransaction(txHash, target, value, signature, data, eta); + return txHash; + } + */ + + function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external payable returns (bytes memory); +} + +contract Enum { + enum Operation {Call, DelegateCall} +} + +contract EncodeSafeTransactionMainnet is Test { + // CALLDATA FOR CALL FROM TIMELOCK TO EXECUTOR MULTISIG + // regular call + uint256 safeTxGas = 0; + uint256 baseGas = 0; + uint256 gasPrice = 0; + address gasToken = address(uint160(0)); + address payable refundReceiver = payable(address(uint160(0))); + + // CALDATA FOR CALL TO TIMELOCK + address timelockTarget = address(0x1); // NOTE: dummy value + uint256 timelockValue = 0; + // empty string, just encode all the data in 'timelockData' + string timelockSignature; + + function encodeForTimelock( + address to, + uint256 value, + bytes memory data, + Enum.Operation operation, + uint256 timelockEta + ) public { + + address timelock = address(0x0); // NOTE: dummy value + + bytes memory final_calldata_timelock_to_executor_multisig = encodeForExecutor(timelock, to, value, data, operation); + + emit log_named_bytes("final_calldata_timelock_to_executor_multisig", final_calldata_timelock_to_executor_multisig); + + bytes memory calldata_to_timelock = abi.encodeWithSelector(ITimelock.queueTransaction.selector, + timelockTarget, + timelockValue, + timelockSignature, + final_calldata_timelock_to_executor_multisig, + timelockEta + ); + + emit log_named_bytes("calldata_to_timelock", calldata_to_timelock); + } + + function encodeForExecutor( + address from, + address to, + uint256 value, + bytes memory data, + Enum.Operation operation + ) public returns (bytes memory) { + bytes1 v = bytes1(uint8(1)); + bytes32 r = bytes32(uint256(uint160(from))); + bytes32 s; + bytes memory sig = abi.encodePacked(r,s,v); + emit log_named_bytes("sig", sig); + + bytes memory final_calldata_to_executor_multisig = abi.encodeWithSelector(ISafe.execTransaction.selector, + to, + value, + data, + operation, + safeTxGas, + baseGas, + gasPrice, + gasToken, + refundReceiver, + sig + ); + + emit log_named_bytes("final_calldata_to_executor_multisig", final_calldata_to_executor_multisig); + + return final_calldata_to_executor_multisig; + } + + struct Tx { + address to; + uint256 value; + bytes data; + } + + function encodeMultisendTxs(Tx[] memory txs) public pure returns (bytes memory) { + bytes memory ret = new bytes(0); + for (uint256 i = 0; i < txs.length; i++) { + ret = abi.encodePacked( + ret, + abi.encodePacked( + uint8(0), + txs[i].to, + txs[i].value, + uint256(txs[i].data.length), + txs[i].data + ) + ); + } + return ret; + } +} \ No newline at end of file diff --git a/script/utils/Releasoor.s.sol b/script/utils/Releasoor.s.sol index d0e98199c..59a6edc49 100644 --- a/script/utils/Releasoor.s.sol +++ b/script/utils/Releasoor.s.sol @@ -1,159 +1,160 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.12; - -import "forge-std/Script.sol"; -import "forge-std/Test.sol"; - -import "./ConfigParser.sol"; -import "./StringUtils.sol"; -import "./AddressUtils.sol"; -import "./TxBuilder.sol"; - -contract OpsMultisigBuilder is Releasoor { - -} - -contract Releasoor is ConfigParser { - - using StringUtils for *; - - Environment env; - Params params; - - uint txsCount; - mapping(uint => Txs) transactions; - - string constant DEPLOY = "deploy"; - string constant QUEUE = "queue"; - string constant EXECUTE = "execute"; - - string constant ENV_MAINNET = "mainnet"; - string constant ENV_HOLESKY = "testnet-holesky"; - string constant ENV_PREPROD = "preprod-holesky"; - - string constant CONFIG_MAINNET = "script/configs/mainnet.json"; - string constant CONFIG_HOLESKY = "script/configs/holesky.json"; - string constant CONFIG_PREPROD = "script/configs/preprod.json"; - - string constant CONFIG_ZIPZOOP = "script/configs/zipzoop.json"; - - function deploy(string memory jsonFile) public returns (Deployment[] memory deployments) { - - (Addresses, Env, Params) = _readConfig(); - - return _deploy(addrs, env, params); - } - - /// $ run execute mainnet - /// -- requires that you have previously run deploy and queue - /// ... except that sometimes we don't need to run deploy OR queue. For example: - /// I want to write/run a script that just has the ops multisig call `addStratsToWhitelist`. - /// This doesn't involve a timelock, as the ops multisig holds the whitelister role - /// We may have deployed something in the deploy script, but we probably didn't queue anything - /// for this. - /// - /// So, it's mainly important that execute fails if: - /// - We reference a queued transaction that doesn't exist in the timelock - /// - This would mean we haven't called `queue` yet - /// - We reference a pendingImpl that doesn't exist in the config - /// - This would mean we haven't called `deploy` yet - function run(string memory action, string memory _env) public returns (bytes memory) { - _log(action); - _log(_env); - - _log("Running script: ".concat(action).concat(" for env: ").concat(_env)); - - uint currentChainId = block.chainid; - emit log_named_uint("You are currently on chain id", currentChainId); - - // string memory filePath; - // if (_env.eq(ENV_MAINNET)) { - // filePath = CONFIG_MAINNET; - // } else if (_env.eq(ENV_HOLESKY)) { - // filePath = CONFIG_HOLESKY; - // } else if (_env.eq(ENV_PREPROD)) { - // filePath = CONFIG_PREPROD; - // } else { - // revert("invalid env"); - // } - - ( - Addresses memory addrs, - Environment memory _env, - Params memory _params - ) = _readConfigFile(CONFIG_ZIPZOOP); - _printEnv(_env); - - env = _env; - params = _params; - require(_env.chainid == currentChainId, "You are on the wrong chain for this config"); - - bytes32 initialAddrs = keccak256(abi.encode(addrs)); - - if (action.eq(DEPLOY)) { - (string[] memory names, ..) = deploy(addrs); - } else if (action.eq(QUEUE)) { - (Txs storage executorTxns, uint eta) = queueUpgrade(addrs); - - _printQueueUpgradeSummary(executorTxns, eta); - } else if (action.eq(EXECUTE)) { - executeUpgrade(addrs); - } else { - revert("invalid action"); - } - - _log("Script complete"); - - // Check if we made changes to config - if (initialAddrs != keccak256(abi.encode(addrs))) { - _writeConfigFile(addrs, _env, _params); - } - } - - function deploy(Addresses memory addrs) internal virtual { - revert("deploy not implemented"); - } - - function queueUpgrade(Addresses memory addrs) internal virtual returns (Txs storage executorTxns, uint eta) { - revert("queueUpgrade not implemented"); - } - - function executeUpgrade(Addresses memory addrs) internal virtual { - revert("executeUpgrade not implemented"); - } - - function _newTxs() internal returns (Txs storage) { - Txs storage txs = transactions[txsCount]; - txsCount++; - - return txs; - } - - function _printQueueUpgradeSummary(Txs storage executorTxns, uint eta) internal { - bytes memory calldata_to_multisend_contract = EncMultiSendCallOnly.multiSend(executorTxns); - emit log_named_bytes("calldata_to_multisend_contract", calldata_to_multisend_contract); - - bytes memory final_calldata_to_executor_multisig = EncGnosisSafe.execTransaction({ - from: addrs.timelock, - to: params.multiSendCallOnly, - data: calldata_to_multisend_contract, - op: EncGnosisSafe.Operation.DelegateCall - }); - emit log_named_bytes("final_calldata_to_executor_multisig", final_calldata_to_executor_multisig); - - bytes memory calldata_to_timelock_queueing_action = EncTimelock.queueTransaction({ - target: addrs.executorMultisig, - data: final_calldata_to_executor_multisig, - eta: 0 - }); - emit log_named_bytes("calldata_to_timelock_queueing_action", calldata_to_timelock_queueing_action); - } - - function _log(string memory s) internal { - emit log(s); - } - - function _log(string memory s, address a) internal { - emit log_named_address(s, a); - } -} \ No newline at end of file +// // SPDX-License-Identifier: UNLICENSED +// pragma solidity ^0.8.12; + +// import "forge-std/Script.sol"; +// import "forge-std/Test.sol"; + +// import "./ConfigParser.sol"; +// import "./StringUtils.sol"; +// import "./AddressUtils.sol"; +// import "./TxBuilder.sol"; + +// contract Releasoor is ConfigParser { + +// using StringUtils for *; + +// Environment env; +// Params params; + +// uint txsCount; +// mapping(uint => Txs) transactions; + +// string constant DEPLOY = "deploy"; +// string constant QUEUE = "queue"; +// string constant EXECUTE = "execute"; + +// string constant ENV_MAINNET = "mainnet"; +// string constant ENV_HOLESKY = "testnet-holesky"; +// string constant ENV_PREPROD = "preprod-holesky"; + +// string constant CONFIG_MAINNET = "script/configs/mainnet.json"; +// string constant CONFIG_HOLESKY = "script/configs/holesky.json"; +// string constant CONFIG_PREPROD = "script/configs/preprod.json"; + +// string constant CONFIG_ZIPZOOP = "script/configs/zipzoop.json"; + +// struct Deployment { +// string name; +// address deployedTo; +// } + +// function deploy(string memory jsonFile) public returns (Deployment[] memory deployments) { + +// (Addresses memory addrs, Environment memory env, Params memory params) = _readConfig(); + +// return _deploy(addrs, env, params); +// } + +// /// $ run execute mainnet +// /// -- requires that you have previously run deploy and queue +// /// ... except that sometimes we don't need to run deploy OR queue. For example: +// /// I want to write/run a script that just has the ops multisig call `addStratsToWhitelist`. +// /// This doesn't involve a timelock, as the ops multisig holds the whitelister role +// /// We may have deployed something in the deploy script, but we probably didn't queue anything +// /// for this. +// /// +// /// So, it's mainly important that execute fails if: +// /// - We reference a queued transaction that doesn't exist in the timelock +// /// - This would mean we haven't called `queue` yet +// /// - We reference a pendingImpl that doesn't exist in the config +// /// - This would mean we haven't called `deploy` yet +// function run(string memory action, string memory _envPath) public returns (bytes memory) { +// _log(action); +// _log(_envPath); + +// _log("Running script: ".concat(action).concat(" for env: ").concat(_envPath)); + +// uint currentChainId = block.chainid; +// emit log_named_uint("You are currently on chain id", currentChainId); + +// // string memory filePath; +// // if (_env.eq(ENV_MAINNET)) { +// // filePath = CONFIG_MAINNET; +// // } else if (_env.eq(ENV_HOLESKY)) { +// // filePath = CONFIG_HOLESKY; +// // } else if (_env.eq(ENV_PREPROD)) { +// // filePath = CONFIG_PREPROD; +// // } else { +// // revert("invalid env"); +// // } + +// ( +// Addresses memory addrs, +// Environment memory _env, +// Params memory _params +// ) = _readConfigFile(_envPath); +// _printEnv(_env); + +// env = _env; +// params = _params; +// require(_env.chainid == currentChainId, "You are on the wrong chain for this config"); + +// bytes32 initialAddrs = keccak256(abi.encode(addrs)); + +// if (action.eq(DEPLOY)) { +// (string[] memory names,) = deploy(addrs); +// } else if (action.eq(QUEUE)) { +// (Txs storage executorTxns, uint eta) = queueUpgrade(addrs); + +// _printQueueUpgradeSummary(executorTxns, eta); +// } else if (action.eq(EXECUTE)) { +// executeUpgrade(addrs); +// } else { +// revert("invalid action"); +// } + +// _log("Script complete"); + +// // Check if we made changes to config +// if (initialAddrs != keccak256(abi.encode(addrs))) { +// _writeConfigFile(addrs, _env, _params); +// } +// } + +// function deploy(Addresses memory addrs) internal virtual { +// revert("deploy not implemented"); +// } + +// function queueUpgrade(Addresses memory addrs) internal virtual returns (Txs storage executorTxns, uint eta) { +// revert("queueUpgrade not implemented"); +// } + +// function executeUpgrade(Addresses memory addrs) internal virtual { +// revert("executeUpgrade not implemented"); +// } + +// function _newTxs() internal returns (Txs storage) { +// Txs storage txs = transactions[txsCount]; +// txsCount++; + +// return txs; +// } + +// function _printQueueUpgradeSummary(Txs storage executorTxns, uint eta) internal { +// bytes memory calldata_to_multisend_contract = EncMultiSendCallOnly.multiSend(executorTxns); +// emit log_named_bytes("calldata_to_multisend_contract", calldata_to_multisend_contract); + +// bytes memory final_calldata_to_executor_multisig = EncGnosisSafe.execTransaction({ +// from: addrs.timelock, +// to: params.multiSendCallOnly, +// data: calldata_to_multisend_contract, +// op: EncGnosisSafe.Operation.DelegateCall +// }); +// emit log_named_bytes("final_calldata_to_executor_multisig", final_calldata_to_executor_multisig); + +// bytes memory calldata_to_timelock_queueing_action = EncTimelock.queueTransaction({ +// target: addrs.executorMultisig, +// data: final_calldata_to_executor_multisig, +// eta: 0 +// }); +// emit log_named_bytes("calldata_to_timelock_queueing_action", calldata_to_timelock_queueing_action); +// } + +// function _log(string memory s) internal { +// emit log(s); +// } + +// function _log(string memory s, address a) internal { +// emit log_named_address(s, a); +// } +// } \ No newline at end of file