Skip to content

Commit f47780d

Browse files
committed
feat: transfer da ownership zeus scripts
1 parent f0ff053 commit f47780d

File tree

6 files changed

+211
-1
lines changed

6 files changed

+211
-1
lines changed

script/configs/mainnet/mainnet-addresses.config.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"lastUpdated": "v0.4.3-mainnet-foundation-incentives",
2+
"lastUpdated": "transfer-da-ownership",
33
"addresses": {
44
"avsDirectory": "0x135dda560e946695d6f155dacafc6f1f25c1f5af",
55
"avsDirectoryImplementation": "0xdabdb3cd346b7d5f5779b0b614ede1cc9dcba5b7",
@@ -9,6 +9,10 @@
99
"delayedWithdrawalRouterImplementation": "0x4bb6731b02314d40abbffbc4540f508874014226",
1010
"delegationManager": "0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A",
1111
"delegationManagerImplementation": "0x1784be6401339fc0fedf7e9379409f5c1bfe9dda",
12+
"eigenDAProxyAdmin": "0x8247EF5705d3345516286B72bFE6D690197C2E99",
13+
"eigenDAEjectionManager": "0x130d8EA0052B45554e4C99079B84df292149Bd5E",
14+
"eigenDARegistryCoordinator:": "0x0BAAc79acD45A023E19345c352d8a7a83C4e5656",
15+
"eigenDAServiceManager": "0x870679E138bCdf293b7Ff14dD44b70FC97e12fc0",
1216
"eigenLayerPauserReg": "0x0c431C66F4dE941d089625E5B423D00707977060",
1317
"eigenLayerProxyAdmin": "0x8b9566AdA63B64d1E1dcF1418b43fd1433b72444",
1418
"eigenPodBeacon": "0x5a2a4F2F3C18f09179B6703e63D9eDD165909073",
@@ -72,6 +76,7 @@
7276
},
7377
"parameters": {
7478
"communityMultisig": "0xFEA47018D632A77bA579846c840d5706705Dc598",
79+
"eigenDAOpsMultisig": "0x002721B4790d97dC140a049936aA710152Ba92D5",
7580
"executorMultisig": "0x369e6F597e22EaB55fFb173C6d9cD234BD699111",
7681
"operationsMultisig": "0xBE1685C81aA44FF9FB319dD389addd9374383e90",
7782
"pauserMultisig": "0x5050389572f2d220ad927CcbeA0D406831012390",

script/releases/Env.sol

+20
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ library Env {
6464
return _string("ZEUS_DEPLOY_TO_VERSION");
6565
}
6666

67+
function eigenDAOpsMultisig() internal view returns (address) {
68+
return _envAddress("eigenDAOpsMultisig");
69+
}
70+
71+
function eigenDAProxyAdmin() internal view returns (address) {
72+
return _envAddress("eigenDAProxyAdmin");
73+
}
74+
75+
function eigenDAEjectionManager() internal view returns (address) {
76+
return _envAddress("eigenDAEjectionManager");
77+
}
78+
79+
function eigenDARegistryCoordinator() internal view returns (address) {
80+
return _envAddress("eigenDARegistryCoordinator");
81+
}
82+
83+
function eigenDAServiceManager() internal view returns (address) {
84+
return _envAddress("eigenDAServiceManager");
85+
}
86+
6787
function executorMultisig() internal view returns (address) {
6888
return _envAddress("executorMultisig");
6989
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import "../Env.sol";
5+
6+
import {MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol";
7+
import "zeus-templates/utils/Encode.sol";
8+
9+
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
10+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
11+
12+
/**
13+
* Purpose:
14+
* * enqueue a multisig transaction which;
15+
* - transfers DA Proxy Admin ownership to the EigenDA ops multisig
16+
* This should be run via the protocol council multisig.
17+
*/
18+
contract QueueTransferProxyAdmin is MultisigBuilder {
19+
using Env for *;
20+
using Encode for *;
21+
22+
function _runAsMultisig() internal virtual override prank(Env.opsMultisig()) {
23+
bytes memory calldata_to_executor = _getCalldataToExecutor();
24+
25+
TimelockController timelock = Env.timelockController();
26+
timelock.schedule({
27+
target: Env.executorMultisig(),
28+
value: 0,
29+
data: calldata_to_executor,
30+
predecessor: 0,
31+
salt: 0,
32+
delay: timelock.getMinDelay()
33+
});
34+
}
35+
36+
/// @dev Get the calldata to be sent from the timelock to the executor
37+
function _getCalldataToExecutor() internal returns (bytes memory) {
38+
MultisigCall[] storage executorCalls = Encode.newMultisigCalls().append({
39+
to: Env.eigenDAProxyAdmin(),
40+
data: abi.encodeCall(Ownable.transferOwnership, (Env.eigenDAOpsMultisig()))
41+
});
42+
43+
return Encode.gnosisSafe.execTransaction({
44+
from: address(Env.timelockController()),
45+
to: Env.multiSendCallOnly(),
46+
op: Encode.Operation.DelegateCall,
47+
data: Encode.multiSend(executorCalls)
48+
});
49+
}
50+
51+
function testScript() public virtual {
52+
TimelockController timelock = Env.timelockController();
53+
bytes memory calldata_to_executor = _getCalldataToExecutor();
54+
bytes32 txHash = timelock.hashOperation({
55+
target: Env.executorMultisig(),
56+
value: 0,
57+
data: calldata_to_executor,
58+
predecessor: 0,
59+
salt: 0
60+
});
61+
62+
// Check that the upgrade does not exist in the timelock
63+
assertFalse(timelock.isOperationPending(txHash), "Transaction should NOT be queued.");
64+
65+
execute();
66+
67+
// Check that the upgrade has been added to the timelock
68+
assertTrue(timelock.isOperationPending(txHash), "Transaction should be queued.");
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import "../Env.sol";
5+
6+
import {MultisigBuilder} from "zeus-templates/templates/MultisigBuilder.sol";
7+
import "zeus-templates/utils/Encode.sol";
8+
9+
import "@openzeppelin/contracts/access/Ownable.sol";
10+
11+
/**
12+
* Purpose:
13+
* * enqueue a multisig transaction which;
14+
* - transfers DA contract ownership to the EigenDA ops multisig
15+
* This should be run via the core ops multisig.
16+
*/
17+
contract TransferOwnershipDAContracts is MultisigBuilder {
18+
using Env for *;
19+
20+
function _runAsMultisig() internal override prank(Env.opsMultisig()) {
21+
Ownable(Env.eigenDAEjectionManager()).transferOwnership(Env.eigenDAOpsMultisig());
22+
Ownable(Env.eigenDARegistryCoordinator()).transferOwnership(Env.eigenDAOpsMultisig());
23+
Ownable(Env.eigenDAServiceManager()).transferOwnership(Env.eigenDAOpsMultisig());
24+
}
25+
26+
function testScript() public virtual {
27+
_runAsMultisig();
28+
29+
assertTrue(
30+
Ownable(Env.eigenDAEjectionManager()).owner() == Env.eigenDAOpsMultisig(),
31+
"eigenDAEjectionManager owner invalid"
32+
);
33+
assertTrue(
34+
Ownable(Env.eigenDARegistryCoordinator()).owner() == Env.eigenDAOpsMultisig(),
35+
"eigenDARegistryCoordinator owner invalid"
36+
);
37+
assertTrue(
38+
Ownable(Env.eigenDAServiceManager()).owner() == Env.eigenDAOpsMultisig(),
39+
"eigenDAServiceManager owner invalid"
40+
);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import "../Env.sol";
5+
import {QueueTransferProxyAdmin} from "./1-queueTransferProxyAdmin.s.sol";
6+
7+
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
8+
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
9+
10+
contract ExecuteTransferProxyAdmin is QueueTransferProxyAdmin {
11+
using Env for *;
12+
13+
function _runAsMultisig() internal override prank(Env.protocolCouncilMultisig()) {
14+
bytes memory calldata_to_executor = _getCalldataToExecutor();
15+
16+
TimelockController timelock = Env.timelockController();
17+
timelock.execute({
18+
target: Env.executorMultisig(),
19+
value: 0,
20+
payload: calldata_to_executor,
21+
predecessor: 0,
22+
salt: 0
23+
});
24+
}
25+
26+
function testScript() public virtual override {
27+
TimelockController timelock = Env.timelockController();
28+
bytes memory calldata_to_executor = _getCalldataToExecutor();
29+
bytes32 txHash = timelock.hashOperation({
30+
target: Env.executorMultisig(),
31+
value: 0,
32+
data: calldata_to_executor,
33+
predecessor: 0,
34+
salt: 0
35+
});
36+
37+
assertFalse(timelock.isOperationPending(txHash), "Transaction should NOT be queued.");
38+
39+
// 1- run queueing logic
40+
QueueTransferProxyAdmin._runAsMultisig();
41+
_unsafeResetHasPranked(); // reset hasPranked so we can use it again
42+
43+
assertTrue(timelock.isOperationPending(txHash), "Transaction should be queued.");
44+
assertFalse(timelock.isOperationReady(txHash), "Transaction should NOT be ready for execution.");
45+
assertFalse(timelock.isOperationDone(txHash), "Transaction should NOT be complete.");
46+
47+
// 2- warp past delay
48+
vm.warp(block.timestamp + timelock.getMinDelay()); // 1 tick after ETA
49+
assertEq(timelock.isOperationReady(txHash), true, "Transaction should be executable.");
50+
51+
// 3- execute
52+
execute();
53+
54+
assertTrue(timelock.isOperationDone(txHash), "Transaction should be complete.");
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "transfer-da-ownership",
3+
"phases": [
4+
{
5+
"type": "multisig",
6+
"filename": "1-queueTransferProxyAdmin.s.sol"
7+
},
8+
{
9+
"type": "multisig",
10+
"filename": "2-transferOwnership.s.sol"
11+
},
12+
{
13+
"type": "multisig",
14+
"filename": "3-executeTransferProxyAdmin.s.sol"
15+
}
16+
]
17+
}

0 commit comments

Comments
 (0)