Skip to content

Commit 06b611b

Browse files
Merge pull request #304 from etherfi-protocol/pankaj/test/pectra-mainnet-tests
Pectra Features on mainnet tests
2 parents 5d870e9 + e169451 commit 06b611b

4 files changed

Lines changed: 686 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.27;
3+
4+
import "../../../src/EtherFiTimelock.sol";
5+
import "../../../src/interfaces/IEtherFiNode.sol";
6+
import "../../../src/EtherFiNodesManager.sol";
7+
import {IEigenPod, IEigenPodTypes} from "../../../src/eigenlayer-interfaces/IEigenPod.sol";
8+
import "forge-std/Script.sol";
9+
import "forge-std/console2.sol";
10+
11+
/**
12+
forge script script/el-exits/pectra-executions/Consolidate-validators.s.sol:ConsolidateValidators --fork-url <mainnet-rpc> -vvvv
13+
*/
14+
15+
contract ConsolidateValidators is Script {
16+
EtherFiTimelock etherFiTimelock =
17+
EtherFiTimelock(payable(0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761));
18+
EtherFiTimelock etherFiOperatingTimelock = EtherFiTimelock(payable(0xcD425f44758a08BaAB3C4908f3e3dE5776e45d7a));
19+
20+
//--------------------------------------------------------------------------------------
21+
//------------------------- Existing Users/Proxies -------------------------------------
22+
//--------------------------------------------------------------------------------------
23+
address constant ETHERFI_NODES_MANAGER_ADDRESS =
24+
0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F;
25+
26+
EtherFiNodesManager etherFiNodesManager = EtherFiNodesManager(payable(ETHERFI_NODES_MANAGER_ADDRESS));
27+
28+
address constant ETHERFI_NODES_MANAGER_ADMIN_ROLE = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC;
29+
30+
address constant EIGEN_POD_ADDRESS = 0x9563794BEf554667f4650eaAe192FfeC1C656C23; // 20 validators
31+
32+
address constant ETHERFI_OPERATING_ADMIN =
33+
0x2aCA71020De61bb532008049e1Bd41E451aE8AdC;
34+
address constant TIMELOCK_CONTROLLER = 0xcdd57D11476c22d265722F68390b036f3DA48c21;
35+
36+
address constant EL_TRIGGER_EXITER = 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F;
37+
38+
uint256 MIN_DELAY_OPERATING_TIMELOCK = 28800; // 8 hours
39+
40+
//consolidate the following validators:
41+
bytes constant PK_54043 = hex"8014c4704f081bd4b8470cb93722601095a314c3db7ccf79c129189d01c432db968a64131f23a94c8ff1e280500ae3d3"; // linked in EtherfiNodesManager
42+
bytes constant PK_54045 = hex"820cf0499d0d908d10c19d85027ed4077322096cd4fb322a763c3bf5e4eb70db30b44ef1284e6fb713421a195735d942";
43+
// bytes constant PK_54041 = hex"87d657860a8b0450d7e700d60aa88a42ee5e6fdedeeb25dd3aee7e1112697f837b4b2e94d37167a900921e6b90c7f3ac";
44+
45+
function run() public {
46+
console2.log("================================================");
47+
console2.log("======================== Running Consolidate Validators ========================");
48+
console2.log("================================================");
49+
console2.log("");
50+
51+
// uint256[] memory legacyIdsForOneValidator = new uint256[](1);
52+
// legacyIdsForOneValidator[0] = 54043;
53+
// bytes[] memory pubkeysForOneValidator = new bytes[](1);
54+
// pubkeysForOneValidator[0] = PK_54043;
55+
56+
// vm.prank(address(etherFiOperatingTimelock));
57+
// etherFiNodesManager.linkLegacyValidatorIds(legacyIdsForOneValidator, pubkeysForOneValidator);
58+
// vm.stopPrank();
59+
// console2.log("Linking legacy validator ids for one validator complete");
60+
61+
vm.deal(address(etherFiOperatingTimelock), 1 ether);
62+
scheduleConsolidation();
63+
}
64+
65+
function scheduleConsolidation() public {
66+
( , IEigenPod pod) = _resolvePod(PK_54043);
67+
console2.log("Pod address:", address(pod));
68+
bytes[] memory validatorPubkeys = new bytes[](2);
69+
validatorPubkeys[0] = PK_54043;
70+
validatorPubkeys[1] = PK_54045;
71+
IEigenPodTypes.ConsolidationRequest[] memory reqs = _consolidationRequestsFromPubkeys(validatorPubkeys);
72+
73+
uint256 feePer = pod.getConsolidationRequestFee();
74+
uint256 n = reqs.length;
75+
uint256 valueToSend = feePer * n;
76+
console2.log("Value to send:", valueToSend);
77+
console2.log("Fee per:", feePer);
78+
console2.log("Number of requests:", n);
79+
80+
address[] memory targets = new address[](1);
81+
targets[0] = address(etherFiNodesManager);
82+
uint256[] memory values = new uint256[](1);
83+
values[0] = valueToSend;
84+
bytes[] memory data = new bytes[](1);
85+
data[0] = abi.encodeWithSelector(
86+
etherFiNodesManager.requestConsolidation.selector,
87+
reqs
88+
);
89+
90+
bytes32 timelockSalt = keccak256(abi.encode(targets, data, block.number));
91+
bytes memory scheduleCalldata = abi.encodeWithSelector(
92+
etherFiOperatingTimelock.scheduleBatch.selector,
93+
targets,
94+
values,
95+
data,
96+
bytes32(0), // predecessor
97+
timelockSalt,
98+
MIN_DELAY_OPERATING_TIMELOCK // minDelay
99+
);
100+
console2.log("Scheduled consolidation request Tx");
101+
console2.log("================================================");
102+
console2.logBytes(scheduleCalldata);
103+
console2.log("================================================");
104+
console2.log("");
105+
106+
bytes memory executeCalldata = abi.encodeWithSelector(
107+
etherFiOperatingTimelock.executeBatch.selector,
108+
targets,
109+
values,
110+
data,
111+
bytes32(0), // predecessor
112+
timelockSalt,
113+
MIN_DELAY_OPERATING_TIMELOCK // minDelay
114+
);
115+
console2.log("Executed consolidation request Tx");
116+
console2.log("================================================");
117+
console2.logBytes(executeCalldata);
118+
console2.log("================================================");
119+
console2.log("");
120+
121+
vm.prank(address(ETHERFI_NODES_MANAGER_ADMIN_ROLE));
122+
etherFiOperatingTimelock.scheduleBatch(targets, values, data, bytes32(0), timelockSalt, MIN_DELAY_OPERATING_TIMELOCK);
123+
vm.stopPrank();
124+
vm.warp(block.timestamp + MIN_DELAY_OPERATING_TIMELOCK + 1); // +1 to ensure it's past the delay
125+
vm.prank(address(ETHERFI_NODES_MANAGER_ADMIN_ROLE));
126+
etherFiOperatingTimelock.executeBatch(targets, values, data, bytes32(0), timelockSalt);
127+
vm.stopPrank();
128+
}
129+
130+
function _consolidationRequestsFromPubkeys(bytes[] memory pubkeys)
131+
internal
132+
pure
133+
returns (IEigenPodTypes.ConsolidationRequest[] memory reqs) {
134+
reqs = new IEigenPodTypes.ConsolidationRequest[](pubkeys.length);
135+
for (uint256 i = 0; i < pubkeys.length; ++i) {
136+
reqs[i] = IEigenPodTypes.ConsolidationRequest({
137+
srcPubkey: pubkeys[i],
138+
targetPubkey: PK_54043 // same pod consolidation
139+
});
140+
}
141+
}
142+
143+
function _resolvePod(bytes memory pubkey) internal view returns (IEtherFiNode etherFiNode, IEigenPod pod) {
144+
bytes32 pkHash = etherFiNodesManager.calculateValidatorPubkeyHash(pubkey);
145+
etherFiNode = etherFiNodesManager.etherFiNodeFromPubkeyHash(pkHash);
146+
pod = etherFiNode.getEigenPod();
147+
require(address(pod) != address(0), "test: node has no pod");
148+
}
149+
}
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.27;
3+
4+
import "../../../src/EtherFiTimelock.sol";
5+
import "../../../src/interfaces/IEtherFiNode.sol";
6+
// import {IEtherFiNodesManager} from "../../../src/interfaces/IEtherFiNodesManager.sol";
7+
import "../../../src/EtherFiNodesManager.sol";
8+
import {IEigenPod, IEigenPodTypes} from "../../../src/eigenlayer-interfaces/IEigenPod.sol";
9+
import "forge-std/Script.sol";
10+
import "forge-std/console2.sol";
11+
12+
/**
13+
forge script script/el-exits/pectra-executions/EL-withdrawal-for-node.s.sol:ELWithdrawalForNode --fork-url <mainnet-rpc> -vvvv
14+
*/
15+
16+
contract ELWithdrawalForNode is Script {
17+
EtherFiTimelock etherFiTimelock =
18+
EtherFiTimelock(payable(0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761));
19+
EtherFiTimelock etherFiOperatingTimelock = EtherFiTimelock(payable(0xcD425f44758a08BaAB3C4908f3e3dE5776e45d7a));
20+
21+
//--------------------------------------------------------------------------------------
22+
//------------------------- Existing Users/Proxies -------------------------------------
23+
//--------------------------------------------------------------------------------------
24+
address constant ETHERFI_NODES_MANAGER_ADDRESS =
25+
0x8B71140AD2e5d1E7018d2a7f8a288BD3CD38916F;
26+
27+
EtherFiNodesManager etherFiNodesManager = EtherFiNodesManager(payable(ETHERFI_NODES_MANAGER_ADDRESS));
28+
29+
address constant ETHERFI_NODES_MANAGER_ADMIN_ROLE = 0x2aCA71020De61bb532008049e1Bd41E451aE8AdC;
30+
31+
address constant EIGEN_POD_ADDRESS = 0x9563794BEf554667f4650eaAe192FfeC1C656C23; // 20 validators
32+
33+
address constant ETHERFI_OPERATING_ADMIN =
34+
0x2aCA71020De61bb532008049e1Bd41E451aE8AdC;
35+
address constant TIMELOCK_CONTROLLER = 0xcdd57D11476c22d265722F68390b036f3DA48c21;
36+
37+
address constant EL_TRIGGER_EXITER = 0x12582A27E5e19492b4FcD194a60F8f5e1aa31B0F;
38+
39+
uint256 MIN_DELAY_OPERATING_TIMELOCK = 28800; // 8 hours
40+
uint256 MIN_DELAY_TIMELOCK = 259200; // 72 hours
41+
42+
bytes constant PK_54043 = hex"8014c4704f081bd4b8470cb93722601095a314c3db7ccf79c129189d01c432db968a64131f23a94c8ff1e280500ae3d3";
43+
bytes constant PK_54045 = hex"820cf0499d0d908d10c19d85027ed4077322096cd4fb322a763c3bf5e4eb70db30b44ef1284e6fb713421a195735d942";
44+
bytes constant PK_54041 = hex"87d657860a8b0450d7e700d60aa88a42ee5e6fdedeeb25dd3aee7e1112697f837b4b2e94d37167a900921e6b90c7f3ac";
45+
bytes constant PK_54050 = hex"8838691e23c67fc8a3021d1dfe49abdbd803469dd3471960f973fa6ed08eb180104d1ddd66938b4dc6264f04e489c6e7";
46+
bytes constant PK_54040 = hex"895186127b42e8202949b9fff00c112df8070c25d96fbe4238fab3a133c49f4a6401dc55828ad5b89093af7602487a2c";
47+
bytes constant PK_54049 = hex"8c64ee1865c48b01ef1af561c41b0e3b363f2a83d99b835d6312638b380d2f698c78f2d405133d8b2aec8c439820f50e";
48+
bytes constant PK_54044 = hex"917f7c7916ee8ba15289810ea118d458c8b4fefb88caa5bef970aa972f7605ed47b54451d9b7c5128c484cf3ce989c1c";
49+
bytes constant PK_54048 = hex"9310d317f4df0b52f8fa2191b6826e93ccd613b2fb4f4e1463c5b112be9102b689ad628c717f201ededf18555d775b43";
50+
bytes constant PK_54035 = hex"936dfac756c52488607b7f07d8905cbff4ae647aaeea75645f28f73a46ae3f6cc9dd55be57ea8ebbf1052197be97bb28";
51+
bytes constant PK_54053 = hex"a160a281269a464e89ca8cdd0521200232c2d37140f218daaa9393aa008c6b3b5ed48040a3e4f46b059532c6b07af360";
52+
bytes constant PK_54039 = hex"a3b265189b2cb571a2d48043a7da96c918df480983c89f86480a1ae5af8a6aa14c381ef091387c201fe5c886b8c27755";
53+
bytes constant PK_54051 = hex"a3e60bce7da064113757a74572909242403654e11ad48c9ee646ea926c026ebf9e60bde5054117b0c74600762693f90c";
54+
bytes constant PK_54047 = hex"a3fb69cd6685e6df16d9dc6e5a0fd174d4460e393bf151b62d4ed62fc4524125f665c3ef91e8673154ce30a934562127";
55+
bytes constant PK_54042 = hex"a481a9553e9cd70a28685c3c86da72cb7cc47fc4132aa79609bc121f3d1c1fe693fb82b70ab1792267837f03fd8b480a";
56+
bytes constant PK_54036 = hex"a702539fb750fa7524a382f0a80572161786be488e77cd680d41d3ba47acd2bd9218036e218e61f7a397b25f6fd473b9";
57+
bytes constant PK_54052 = hex"a9e0d47715165646896c9dd1eaad3822824340f9432978fe2220d1d849509711fa822080d69a5604a7df372dcd7290ff";
58+
bytes constant PK_54037 = hex"ab82fc4c1eee2b1c26d3adcf6a1240beb18aafe86ac0ca897cd94611eefae7a88e3b3c80dd768b6f2da9326ecebfcc54";
59+
bytes constant PK_54054 = hex"b72d2761774961ee47a8b9a917110a70425b4500909ccd972f72c7219e3f0c76f086de76cb80a4598ecb44245effeaa9";
60+
bytes constant PK_54046 = hex"b7ca7c4dccc74cc17a1b2325a95e690aca40fd4d2980bd65180d98bf0da447cf84254da073c28c1b1efc959611e5cfe1";
61+
bytes constant PK_54038 = hex"b974967fa38e82a9983019ccdb754df1c176edf5e542ec7377c23bcce730c094007fb84d9816f5fb22f09b725e46d99a";
62+
63+
function run() public {
64+
console2.log("================================================");
65+
console2.log("======================== Running EL Withdrawal For Node Transactions ========================");
66+
console2.log("================================================");
67+
console2.log("");
68+
69+
// vm.startBroadcast(ETHERFI_OPERATING_ADMIN);
70+
// vm.prank(ETHERFI_OPERATING_ADMIN);
71+
linkLegacyValidatorIds();
72+
// vm.stopPrank();
73+
// vm.stopBroadcast();
74+
75+
// vm.startBroadcast(EL_TRIGGER_EXITER);
76+
executeELWithdrawalForNodeTransactions();
77+
// vm.stopBroadcast();
78+
}
79+
80+
function linkLegacyValidatorIds() public {
81+
uint256[] memory legacyIdsForOneValidator = new uint256[](1);
82+
legacyIdsForOneValidator[0] = 54043;
83+
bytes[] memory pubkeysForOneValidator = new bytes[](1);
84+
pubkeysForOneValidator[0] = PK_54043;
85+
86+
address[] memory targets = new address[](1);
87+
targets[0] = address(etherFiNodesManager);
88+
uint256[] memory values = new uint256[](1);
89+
values[0] = 0;
90+
bytes[] memory data = new bytes[](1);
91+
data[0] = abi.encodeWithSelector(
92+
etherFiNodesManager.linkLegacyValidatorIds.selector,
93+
legacyIdsForOneValidator,
94+
pubkeysForOneValidator
95+
);
96+
97+
bytes32 timelockSalt = keccak256(
98+
abi.encode(targets, data, block.number)
99+
);
100+
101+
bytes memory scheduleCalldata = abi.encodeWithSelector(
102+
etherFiOperatingTimelock.scheduleBatch.selector,
103+
targets,
104+
values,
105+
data,
106+
bytes32(0), //predecessor
107+
timelockSalt,
108+
MIN_DELAY_OPERATING_TIMELOCK
109+
);
110+
console2.log("Scheduled linkLegacyValidatorIds Tx");
111+
console2.log("================================================");
112+
console2.logBytes(scheduleCalldata);
113+
console2.log("================================================");
114+
console2.log("");
115+
116+
bytes memory executeCalldata = abi.encodeWithSelector(
117+
etherFiOperatingTimelock.executeBatch.selector,
118+
targets,
119+
values,
120+
data,
121+
bytes32(0), //predecessor
122+
timelockSalt,
123+
MIN_DELAY_OPERATING_TIMELOCK
124+
);
125+
console2.log("Executed linkLegacyValidatorIds Tx");
126+
console2.log("================================================");
127+
console2.logBytes(executeCalldata);
128+
console2.log("================================================");
129+
console2.log("");
130+
131+
vm.prank(address(ETHERFI_OPERATING_ADMIN));
132+
etherFiNodesManager.linkLegacyValidatorIds(legacyIdsForOneValidator, pubkeysForOneValidator);
133+
vm.stopPrank();
134+
135+
// uncomment to run against fork
136+
// console2.log("=== SCHEDULING BATCH ===");
137+
// // console2.log("Current timestamp:", block.timestamp);
138+
// etherFiOperatingTimelock.scheduleBatch(targets, values, data, bytes32(0), timelockSalt, MIN_DELAY_OPERATING_TIMELOCK);
139+
140+
// console2.log("=== FAST FORWARDING TIME ===");
141+
// vm.warp(block.timestamp + MIN_DELAY_OPERATING_TIMELOCK + 1); // +1 to ensure it's past the delay
142+
// // console2.log("New timestamp:", block.timestamp);
143+
// etherFiOperatingTimelock.executeBatch(targets, values, data, bytes32(0), timelockSalt);
144+
}
145+
146+
function executeELWithdrawalForNodeTransactions() public {
147+
console2.log("Executing EL Withdrawal For Node Transactions");
148+
149+
// STEP 1: GET EIGEN POD
150+
IEigenPod pod = IEigenPod(EIGEN_POD_ADDRESS);
151+
152+
// STEP 2: GET WITHDRAWAL REQUESTS
153+
IEigenPodTypes.WithdrawalRequest[] memory withdrawalRequests = _getWithdrawalsRequests();
154+
155+
// STEP 3: GET WITHDRAWAL REQUEST FEE
156+
uint256 feePer = pod.getWithdrawalRequestFee();
157+
uint256 n = withdrawalRequests.length;
158+
uint256 valueToSend = feePer * n;
159+
160+
// STEP 4: EXECUTE EL WITHDRAWAL FOR NODE TRANSACTIONS
161+
vm.prank(address(EL_TRIGGER_EXITER));
162+
etherFiNodesManager.requestExecutionLayerTriggeredWithdrawal{value: valueToSend}(withdrawalRequests);
163+
vm.stopPrank();
164+
}
165+
166+
function _getWithdrawalsRequests() public pure returns (IEigenPodTypes.WithdrawalRequest[] memory withdrawalRequests) {
167+
bytes[] memory pubkeys = new bytes[](20);
168+
uint64[] memory amountsGwei = new uint64[](20);
169+
170+
pubkeys[0] = PK_54043;
171+
amountsGwei[0] = 0;
172+
pubkeys[1] = PK_54045;
173+
amountsGwei[1] = 0;
174+
pubkeys[2] = PK_54041;
175+
amountsGwei[2] = 0;
176+
pubkeys[3] = PK_54050;
177+
amountsGwei[3] = 0;
178+
pubkeys[4] = PK_54040;
179+
amountsGwei[4] = 0;
180+
pubkeys[5] = PK_54049;
181+
amountsGwei[5] = 0;
182+
pubkeys[6] = PK_54044;
183+
amountsGwei[6] = 0;
184+
pubkeys[7] = PK_54048;
185+
amountsGwei[7] = 0;
186+
pubkeys[8] = PK_54035;
187+
amountsGwei[8] = 0;
188+
pubkeys[9] = PK_54053;
189+
amountsGwei[9] = 0;
190+
pubkeys[10] = PK_54039;
191+
amountsGwei[10] = 0;
192+
pubkeys[11] = PK_54051;
193+
amountsGwei[11] = 0;
194+
pubkeys[12] = PK_54047;
195+
amountsGwei[12] = 0;
196+
pubkeys[13] = PK_54042;
197+
amountsGwei[13] = 0;
198+
pubkeys[14] = PK_54036;
199+
amountsGwei[14] = 0;
200+
pubkeys[15] = PK_54052;
201+
amountsGwei[15] = 0;
202+
pubkeys[16] = PK_54037;
203+
amountsGwei[16] = 0;
204+
pubkeys[17] = PK_54054;
205+
amountsGwei[17] = 0;
206+
pubkeys[18] = PK_54046;
207+
amountsGwei[18] = 0;
208+
pubkeys[19] = PK_54038;
209+
amountsGwei[19] = 0;
210+
211+
withdrawalRequests = new IEigenPodTypes.WithdrawalRequest[](pubkeys.length);
212+
for (uint256 i = 0; i < pubkeys.length; i++) {
213+
withdrawalRequests[i] = IEigenPodTypes.WithdrawalRequest({
214+
pubkey: pubkeys[i],
215+
amountGwei: amountsGwei[i]
216+
});
217+
}
218+
return withdrawalRequests;
219+
}
220+
}

0 commit comments

Comments
 (0)