Skip to content

Commit 62a7c40

Browse files
authored
EigenPod Unit Test Refactor (#317)
1 parent 4f2018c commit 62a7c40

15 files changed

+1197
-541
lines changed

src/contracts/pods/EigenPod.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ contract EigenPod is IEigenPod, Initializable, ReentrancyGuardUpgradeable, Eigen
549549
// Done with proofs! Now update the validator's balance and send to the EigenPodManager if needed
550550

551551
uint64 currentRestakedBalanceGwei = validatorInfo.restakedBalanceGwei;
552-
uint64 newRestakedBalanceGwei;
552+
uint64 newRestakedBalanceGwei;
553553
if (validatorBalance > MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) {
554554
newRestakedBalanceGwei = MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR;
555555
} else {

src/test/EigenPod.t.sol

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,8 @@ contract EigenPodTests is ProofParsing, EigenPodPausingConstants {
770770
"eigenPodManager shares not updated correctly"
771771
);
772772
}
773-
773+
774+
/// @notice Similar test done in EP unit test
774775
//test deploying an eigen pod with mismatched withdrawal credentials between the proof and the actual pod's address
775776
function testDeployNewEigenPodWithWrongWithdrawalCreds(address wrongWithdrawalAddress) public {
776777
// ./solidityProofGen -newBalance=32000115173 "ValidatorFieldsProof" 302913 true "data/withdrawal_proof_goerli/goerli_block_header_6399998.json" "data/withdrawal_proof_goerli/goerli_slot_6399998.json" "withdrawal_credential_proof_302913.json"
@@ -903,40 +904,6 @@ contract EigenPodTests is ProofParsing, EigenPodPausingConstants {
903904
newPod.verifyBalanceUpdates(uint64(block.timestamp - 1), validatorIndices, stateRootProofStruct, proofs, validatorFieldsArray);
904905
}
905906

906-
//test that when withdrawal credentials are verified more than once, it reverts
907-
function testDeployNewEigenPodWithActiveValidator() public {
908-
// ./solidityProofGen -newBalance=32000115173 "ValidatorFieldsProof" 302913 true "data/withdrawal_proof_goerli/goerli_block_header_6399998.json" "data/withdrawal_proof_goerli/goerli_slot_6399998.json" "withdrawal_credential_proof_302913.json"
909-
setJSON("./src/test/test-data/withdrawal_credential_proof_302913.json");
910-
IEigenPod pod = _testDeployAndVerifyNewEigenPod(podOwner, signature, depositDataRoot);
911-
912-
uint64 timestamp = 1;
913-
914-
bytes32[][] memory validatorFieldsArray = new bytes32[][](1);
915-
validatorFieldsArray[0] = getValidatorFields();
916-
bytes[] memory proofsArray = new bytes[](1);
917-
proofsArray[0] = abi.encodePacked(getWithdrawalCredentialProof());
918-
919-
uint40[] memory validatorIndices = new uint40[](1);
920-
validatorIndices[0] = uint40(getValidatorIndex());
921-
922-
BeaconChainProofs.StateRootProof memory stateRootProofStruct = _getStateRootProof();
923-
924-
cheats.startPrank(podOwner);
925-
cheats.expectRevert(
926-
bytes(
927-
"EigenPod.verifyCorrectWithdrawalCredentials: Validator must be inactive to prove withdrawal credentials"
928-
)
929-
);
930-
pod.verifyWithdrawalCredentials(
931-
timestamp,
932-
stateRootProofStruct,
933-
validatorIndices,
934-
proofsArray,
935-
validatorFieldsArray
936-
);
937-
cheats.stopPrank();
938-
}
939-
940907
// // 3. Single withdrawal credential
941908
// // Test: Owner proves an withdrawal credential.
942909
// // validator status should be marked as ACTIVE
@@ -1920,3 +1887,41 @@ contract Relayer is Test {
19201887
// return (queuedWithdrawal, withdrawalRoot);
19211888
// }
19221889

1890+
//Integration Test
1891+
// function testFullWithdrawalProofWithWrongWithdrawalFields(bytes32[] memory wrongWithdrawalFields) public {
1892+
// Relayer relay = new Relayer();
1893+
// uint256 WITHDRAWAL_FIELD_TREE_HEIGHT = 2;
1894+
1895+
// setJSON("./src/test/test-data/fullWithdrawalProof_Latest.json");
1896+
// BeaconChainProofs.WithdrawalProof memory proofs = _getWithdrawalProof();
1897+
// bytes32 beaconStateRoot = getBeaconStateRoot();
1898+
// cheats.assume(wrongWithdrawalFields.length != 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT);
1899+
// validatorFields = getValidatorFields();
1900+
1901+
// cheats.expectRevert(bytes("BeaconChainProofs.verifyWithdrawal: withdrawalFields has incorrect length"));
1902+
// relay.verifyWithdrawal(beaconStateRoot, wrongWithdrawalFields, proofs);
1903+
// }
1904+
1905+
// // Integration Test
1906+
// function testMismatchedWithdrawalProofInputs(uint64 numValidators, uint64 numValidatorProofs) external {
1907+
// cheats.assume(numValidators < numValidatorProofs && numValidatorProofs < 5);
1908+
// setJSON("./src/test/test-data/fullWithdrawalProof_Latest.json");
1909+
// bytes[] memory validatorFieldsProofArray = new bytes[](numValidatorProofs);
1910+
// for (uint256 index = 0; index < numValidators; index++) {
1911+
// validatorFieldsProofArray[index] = abi.encodePacked(getValidatorProof());
1912+
// }
1913+
// bytes32[][] memory validatorFieldsArray = new bytes32[][](numValidators);
1914+
// for (uint256 index = 0; index < validatorFieldsArray.length; index++) {
1915+
// validatorFieldsArray[index] = getValidatorFields();
1916+
// }
1917+
// BeaconChainProofs.StateRootProof memory stateRootProofStruct = _getStateRootProof();
1918+
// BeaconChainProofs.WithdrawalProof[] memory withdrawalProofsArray = new BeaconChainProofs.WithdrawalProof[](1);
1919+
1920+
// withdrawalProofsArray[0] = _getWithdrawalProof();
1921+
1922+
// bytes32[][] memory withdrawalFieldsArray = new bytes32[][](1);
1923+
// withdrawalFieldsArray[0] = withdrawalFields;
1924+
1925+
// cheats.expectRevert(bytes("EigenPod.verifyAndProcessWithdrawals: inputs must be same length"));
1926+
// pod.verifyAndProcessWithdrawals(0, stateRootProofStruct, withdrawalProofsArray, validatorFieldsProofArray, validatorFieldsArray, withdrawalFieldsArray);
1927+
// }
Lines changed: 42 additions & 0 deletions
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+
interface IEigenPodEvents {
5+
/// @notice Emitted when an ETH validator stakes via this eigenPod
6+
event EigenPodStaked(bytes pubkey);
7+
8+
/// @notice Emitted when an ETH validator's withdrawal credentials are successfully verified to be pointed to this eigenPod
9+
event ValidatorRestaked(uint40 validatorIndex);
10+
11+
/// @notice Emitted when an ETH validator's balance is proven to be updated. Here newValidatorBalanceGwei
12+
// is the validator's balance that is credited on EigenLayer.
13+
event ValidatorBalanceUpdated(uint40 validatorIndex, uint64 balanceTimestamp, uint64 newValidatorBalanceGwei);
14+
15+
/// @notice Emitted when an ETH validator is prove to have withdrawn from the beacon chain
16+
event FullWithdrawalRedeemed(
17+
uint40 validatorIndex,
18+
uint64 withdrawalTimestamp,
19+
address indexed recipient,
20+
uint64 withdrawalAmountGwei
21+
);
22+
23+
/// @notice Emitted when a partial withdrawal claim is successfully redeemed
24+
event PartialWithdrawalRedeemed(
25+
uint40 validatorIndex,
26+
uint64 withdrawalTimestamp,
27+
address indexed recipient,
28+
uint64 partialWithdrawalAmountGwei
29+
);
30+
31+
/// @notice Emitted when restaked beacon chain ETH is withdrawn from the eigenPod.
32+
event RestakedBeaconChainETHWithdrawn(address indexed recipient, uint256 amount);
33+
34+
/// @notice Emitted when podOwner enables restaking
35+
event RestakingActivated(address indexed podOwner);
36+
37+
/// @notice Emitted when ETH is received via the `receive` fallback
38+
event NonBeaconChainETHReceived(uint256 amountReceived);
39+
40+
/// @notice Emitted when ETH that was previously received via the `receive` fallback is withdrawn
41+
event NonBeaconChainETHWithdrawn(address indexed recipient, uint256 amountWithdrawn);
42+
}

src/test/harnesses/EigenPodHarness.sol

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,38 @@ contract EPInternalFunctions is EigenPod {
1919
_GENESIS_TIME
2020
) {}
2121

22+
function verifyWithdrawalCredentials(
23+
uint64 oracleTimestamp,
24+
bytes32 beaconStateRoot,
25+
uint40 validatorIndex,
26+
bytes calldata validatorFieldsProof,
27+
bytes32[] calldata validatorFields
28+
) public returns (uint256) {
29+
return _verifyWithdrawalCredentials(
30+
oracleTimestamp,
31+
beaconStateRoot,
32+
validatorIndex,
33+
validatorFieldsProof,
34+
validatorFields
35+
);
36+
}
37+
38+
function verifyAndProcessWithdrawal(
39+
bytes32 beaconStateRoot,
40+
BeaconChainProofs.WithdrawalProof calldata withdrawalProof,
41+
bytes calldata validatorFieldsProof,
42+
bytes32[] calldata validatorFields,
43+
bytes32[] calldata withdrawalFields
44+
) public returns (IEigenPod.VerifiedWithdrawal memory) {
45+
return _verifyAndProcessWithdrawal(
46+
beaconStateRoot,
47+
withdrawalProof,
48+
validatorFieldsProof,
49+
validatorFields,
50+
withdrawalFields
51+
);
52+
}
53+
2254
function processFullWithdrawal(
2355
uint40 validatorIndex,
2456
bytes32 validatorPubkeyHash,
@@ -59,11 +91,11 @@ contract EPInternalFunctions is EigenPod {
5991
bytes32[] calldata validatorFields,
6092
uint64 mostRecentBalanceUpdateTimestamp
6193
)
62-
public
94+
public returns (int256)
6395
{
6496
bytes32 pkhash = validatorFields[0];
6597
_validatorPubkeyHashToInfo[pkhash].mostRecentBalanceUpdateTimestamp = mostRecentBalanceUpdateTimestamp;
66-
_verifyBalanceUpdate(
98+
return _verifyBalanceUpdate(
6799
oracleTimestamp,
68100
validatorIndex,
69101
beaconStateRoot,
@@ -75,4 +107,8 @@ contract EPInternalFunctions is EigenPod {
75107
function setValidatorStatus(bytes32 pkhash, VALIDATOR_STATUS status) public {
76108
_validatorPubkeyHashToInfo[pkhash].status = status;
77109
}
110+
111+
function setValidatorRestakedBalance(bytes32 pkhash, uint64 restakedBalanceGwei) public {
112+
_validatorPubkeyHashToInfo[pkhash].restakedBalanceGwei = restakedBalanceGwei;
113+
}
78114
}

src/test/mocks/DelayedWithdrawalRouterMock.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pragma solidity >=0.5.0;
33

44
import "../../contracts/interfaces/IDelayedWithdrawalRouter.sol";
55

6-
76
contract DelayedWithdrawalRouterMock is IDelayedWithdrawalRouter {
87
/**
98
* @notice Creates an delayed withdrawal for `msg.value` to the `recipient`.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"validatorIndex":302913,"beaconStateRoot":"0x8276d4d448d27e7d41da771ca7729f7a25c01b5fcd1f18f9bd9632dc7fde1388","slotRoot":"0xfea7610000000000000000000000000000000000000000000000000000000000","balanceRoot":"0x6cba5d7307000000e5d9ef840600000008bd5d7307000000239e5d7307000000","latestBlockHeaderRoot":"0x56461a3931812e3341030121e7db0f298112576ac9e898c00f4f1338c2ad647e","ValidatorBalanceProof":["0x26805d73070000002aa55d7307000000218e5d730700000056d35d7307000000","0x24846a54724508d8394a9e30f819bc19fe6727745be4f19e1e3924b985b4b8e9","0x48fb4849c31d88b413f650c17bd55bb11fe38bcef5d234dba8532737ae78f776","0x0d7d38f90a04ef49d15ca10af0e818e227134e4b46c7b22dd10e149f2a2bc612","0xdd345235f28f92719c39c9a5042b91f814d535ae5df574c0f6cd38f77791fc2b","0x0855928643f4210d9d8d0986847674139be32ebf3db984b6d81f3ed136475b6d","0x28460d51c1ce75299f8c0dff8bca9f498fef0edc57c343bbd76592b3d6b984a3","0x068a141709053afb48698290176068f448867cba9c6ff10f986b1d02691f6e70","0x9f0958275fe6ea80b1825bcd11907d1076600719ce574ae2a609e51a975dde54","0xd43fbb18b30449f5c81148848fd6579b4f6cebfe66187bd1c36a293b22085fc2","0x7bf0aac502053da7dfd5356960db63ab48d3cc6ee5f36f41639eadacd34ac272","0x866e3b213d02f1cb86149c2472789ab9d7fb3fb52371a893dc8b6f8936ebd0c1","0xcec7cc4b82fb8dd889257128af3e4433700fcc0fb0505b431aa5f592111e785b","0xdd08667067baa43e2b41b793464a591a29643b5582c8fc9c2c045f984c5848d7","0x842ec80062a4f2f7e9d80ab408374ae42817acf5036aff40b3ade345ab196090","0xfe1ae22b8ba21fce84b25f5da3e37a91db49158b7025d6371d5a54c03adba125","0x8c039a81d68952077db2cc11713ae6f5a9ecc5ebe859c0612ff7215c0ccd7aba","0x5415d3199f1da31287d646d03c2691728396d87f7ef52c142596301e27a343ca","0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4","0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f","0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa","0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c","0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167","0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7","0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0","0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544","0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765","0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4","0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1","0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636","0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c","0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7","0xc6f67e02e6e4e1bdefb994c6098953f34636ba2b6ca20a4721d2b26a886722ff","0x1c9a7e5ff1cf48b4ad1582d3f4e4a1004f3b20d8c5a2b71387a4254ad933ebc5","0x2f075ae229646b6f6aed19a5e372cf295081401eb893ff599b3f9acc0c0d3e7d","0x328921deb59612076801e8cd61592107b5c67c79b846595cc6320c395b46362c","0xbfb909fdb236ad2411b4e4883810a074b840464689986c3f8a8091827e17c327","0x55d8fb3687ba3ba49f342c77f5a1f89bec83d811446e1a467139213d640b6a74","0x846b080000000000000000000000000000000000000000000000000000000000","0x7d46d32db9a97974916a2114aeffc11fc031a954b2110742267054a438055c1a","0x81e1234eb27473f180f890c98019ecb7655a3e58105c7182d8daf726d75aaf8d","0x275abf1ff862082807cafed8d0a318c27439ec7159d81c831ee2832b5d6b57f6","0x4715bf9a259680cd06827b30bddb27ad445506e9edeb72a3eab904d94dea816b","0x5ba049ff558dd0ff1eadf2cef346aac41b7059433f21925b345f1024af18057d"],"ValidatorFields":["0xe36689b7b39ee895a754ba878afac2aa5d83349143a8b23d371823dd9ed3435d","0x01000000000000000000000049c486e3f4303bc11c02f952fe5b08d0ab22d443","0xe5d9ef8406000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0xea65010000000000000000000000000000000000000000000000000000000000","0xf265010000000000000000000000000000000000000000000000000000000000","0xffffffffffffffff000000000000000000000000000000000000000000000000","0xffffffffffffffff000000000000000000000000000000000000000000000000"],"StateRootAgainstLatestBlockHeaderProof":["0x0000000000000000000000000000000000000000000000000000000000000000","0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71"],"WithdrawalCredentialProof":["0x9e06c3582190fe488eac3f9f6c95622742f9afe3e038b39d2ca97ba6d5d0de4e","0x3eb11a14af12d8558cc14493938ffa0a1c6155349699c2b9245e76344d9922ee","0x81c959aeae7524f4f1d2d3d930ba504cbe86330619a221c9e2d9fb315e32a4d1","0x9b9adf5d31a74f30ae86ce7f7a8bfe89d2bdf2bd799d0c6896174b4f15878bf1","0x17d22cd18156b4bcbefbcfa3ed820c14cc5af90cb7c02c373cc476bc947ba4ac","0x22c1a00da80f2c5c8a11fdd629af774b9dde698305735d63b19aed6a70310537","0x949da2d82acf86e064a7022c5d5e69528ad6d3dd5b9cdf7fb9b736f0d925fc38","0x1920215f3c8c349a04f6d29263f495416e58d85c885b7d356dd4d335427d2748","0x7f12746ac9a3cc418594ab2c25838fdaf9ef43050a12f38f0c25ad7f976d889a","0x451a649946a59a90f56035d1eccdfcaa99ac8bb74b87c403653bdc5bc0055e2c","0x00ab86a6644a7694fa7bc0da3a8730404ea7e26da981b169316f7acdbbe8c79b","0x0d500027bb8983acbec0993a3d063f5a1f4b9a5b5893016bc9eec28e5633867e","0x2ba5cbed64a0202199a181c8612a8c5dad2512ad0ec6aa7f0c079392e16008ee","0xab8576644897391ddc0773ac95d072de29d05982f39201a5e0630b81563e91e9","0xc6e90f3f46f28faea3476837d2ec58ad5fa171c1f04446f2aa40aa433523ec74","0xb86e491b234c25dc5fa17b43c11ef04a7b3e89f99b2bb7d8daf87ee6dc6f3ae3","0xdb41e006a5111a4f2620a004e207d2a63fc5324d7f528409e779a34066a9b67f","0xe2356c743f98d89213868108ad08074ca35f685077e487077cef8a55917736c6","0xf7552771443e29ebcc7a4aad87e308783559a0b4ff696a0e49f81fb2736fe528","0x3d3aabf6c36de4242fef4b6e49441c24451ccf0e8e184a33bece69d3e3d40ac3","0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa","0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c","0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167","0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7","0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0","0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544","0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765","0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4","0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1","0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636","0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c","0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7","0xc6f67e02e6e4e1bdefb994c6098953f34636ba2b6ca20a4721d2b26a886722ff","0x1c9a7e5ff1cf48b4ad1582d3f4e4a1004f3b20d8c5a2b71387a4254ad933ebc5","0x2f075ae229646b6f6aed19a5e372cf295081401eb893ff599b3f9acc0c0d3e7d","0x328921deb59612076801e8cd61592107b5c67c79b846595cc6320c395b46362c","0xbfb909fdb236ad2411b4e4883810a074b840464689986c3f8a8091827e17c327","0x55d8fb3687ba3ba49f342c77f5a1f89bec83d811446e1a467139213d640b6a74","0xf7210d4f8e7e1039790e7bf4efa207555a10a6db1dd4b95da313aaa88b88fe76","0xad21b516cbc645ffe34ab5de1c8aef8cd4e7f8d2b51e8e1456adc7563cda206f","0x846b080000000000000000000000000000000000000000000000000000000000","0x5a6c050000000000000000000000000000000000000000000000000000000000","0x47314ebc95c63f3fd909af6442ed250d823b2ee8a6e48d8167d4dfdab96c8b5e","0x9fade50f5a88a8f7a027b4e7fa019f2289075e38668e926f9909dfcd5bcb3574","0x4715bf9a259680cd06827b30bddb27ad445506e9edeb72a3eab904d94dea816b","0x5ba049ff558dd0ff1eadf2cef346aac41b7059433f21925b345f1024af18057d"]}

src/test/test-data/fullWithdrawalProof_Latest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"slot": 6397852,
3-
"validatorIndex": 0,
3+
"validatorIndex": 302913,
44
"historicalSummaryIndex": 146,
55
"withdrawalIndex": 0,
66
"blockHeaderRootIndex": 8092,

0 commit comments

Comments
 (0)