Skip to content
2 changes: 1 addition & 1 deletion src/contracts/pods/EigenPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ contract EigenPod is IEigenPod, Initializable, ReentrancyGuardUpgradeable, Eigen
// Done with proofs! Now update the validator's balance and send to the EigenPodManager if needed

uint64 currentRestakedBalanceGwei = validatorInfo.restakedBalanceGwei;
uint64 newRestakedBalanceGwei;
uint64 newRestakedBalanceGwei;
if (validatorBalance > MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR) {
newRestakedBalanceGwei = MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR;
} else {
Expand Down
75 changes: 40 additions & 35 deletions src/test/EigenPod.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@ contract EigenPodTests is ProofParsing, EigenPodPausingConstants {
"eigenPodManager shares not updated correctly"
);
}


/// @notice Similar test done in EP unit test
//test deploying an eigen pod with mismatched withdrawal credentials between the proof and the actual pod's address
function testDeployNewEigenPodWithWrongWithdrawalCreds(address wrongWithdrawalAddress) public {
// ./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"
Expand Down Expand Up @@ -853,40 +854,6 @@ contract EigenPodTests is ProofParsing, EigenPodPausingConstants {
newPod.verifyBalanceUpdates(uint64(block.timestamp - 1), validatorIndices, stateRootProofStruct, proofs, validatorFieldsArray);
}

//test that when withdrawal credentials are verified more than once, it reverts
function testDeployNewEigenPodWithActiveValidator() public {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking through the diffs, can't see where this is added back - will you move it to integration tests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added here since it was more of a unit test:

function test_revert_validatorActive() public {
// Set JSON & params
setJSON("./src/test/test-data/withdrawal_credential_proof_302913.json");
_setWithdrawalCredentialParams();
// Set validator status to active
eigenPodHarness.setValidatorStatus(validatorFields[0], IEigenPod.VALIDATOR_STATUS.ACTIVE);
// Expect revert
cheats.expectRevert(
"EigenPod.verifyCorrectWithdrawalCredentials: Validator must be inactive to prove withdrawal credentials"
);
eigenPodHarness.verifyWithdrawalCredentials(
oracleTimestamp,
beaconStateRoot,
validatorIndex,
validatorFieldsProof,
validatorFields
);
}

// ./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"
setJSON("./src/test/test-data/withdrawal_credential_proof_302913.json");
IEigenPod pod = _testDeployAndVerifyNewEigenPod(podOwner, signature, depositDataRoot);

uint64 timestamp = 1;

bytes32[][] memory validatorFieldsArray = new bytes32[][](1);
validatorFieldsArray[0] = getValidatorFields();
bytes[] memory proofsArray = new bytes[](1);
proofsArray[0] = abi.encodePacked(getWithdrawalCredentialProof());

uint40[] memory validatorIndices = new uint40[](1);
validatorIndices[0] = uint40(getValidatorIndex());

BeaconChainProofs.StateRootProof memory stateRootProofStruct = _getStateRootProof();

cheats.startPrank(podOwner);
cheats.expectRevert(
bytes(
"EigenPod.verifyCorrectWithdrawalCredentials: Validator must be inactive to prove withdrawal credentials"
)
);
pod.verifyWithdrawalCredentials(
timestamp,
stateRootProofStruct,
validatorIndices,
proofsArray,
validatorFieldsArray
);
cheats.stopPrank();
}

// // 3. Single withdrawal credential
// // Test: Owner proves an withdrawal credential.
// // validator status should be marked as ACTIVE
Expand Down Expand Up @@ -1870,3 +1837,41 @@ contract Relayer is Test {
// return (queuedWithdrawal, withdrawalRoot);
// }

//Integration Test
// function testFullWithdrawalProofWithWrongWithdrawalFields(bytes32[] memory wrongWithdrawalFields) public {
// Relayer relay = new Relayer();
// uint256 WITHDRAWAL_FIELD_TREE_HEIGHT = 2;

// setJSON("./src/test/test-data/fullWithdrawalProof_Latest.json");
// BeaconChainProofs.WithdrawalProof memory proofs = _getWithdrawalProof();
// bytes32 beaconStateRoot = getBeaconStateRoot();
// cheats.assume(wrongWithdrawalFields.length != 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT);
// validatorFields = getValidatorFields();

// cheats.expectRevert(bytes("BeaconChainProofs.verifyWithdrawal: withdrawalFields has incorrect length"));
// relay.verifyWithdrawal(beaconStateRoot, wrongWithdrawalFields, proofs);
// }

// // Integration Test
// function testMismatchedWithdrawalProofInputs(uint64 numValidators, uint64 numValidatorProofs) external {
// cheats.assume(numValidators < numValidatorProofs && numValidatorProofs < 5);
// setJSON("./src/test/test-data/fullWithdrawalProof_Latest.json");
// bytes[] memory validatorFieldsProofArray = new bytes[](numValidatorProofs);
// for (uint256 index = 0; index < numValidators; index++) {
// validatorFieldsProofArray[index] = abi.encodePacked(getValidatorProof());
// }
// bytes32[][] memory validatorFieldsArray = new bytes32[][](numValidators);
// for (uint256 index = 0; index < validatorFieldsArray.length; index++) {
// validatorFieldsArray[index] = getValidatorFields();
// }
// BeaconChainProofs.StateRootProof memory stateRootProofStruct = _getStateRootProof();
// BeaconChainProofs.WithdrawalProof[] memory withdrawalProofsArray = new BeaconChainProofs.WithdrawalProof[](1);

// withdrawalProofsArray[0] = _getWithdrawalProof();

// bytes32[][] memory withdrawalFieldsArray = new bytes32[][](1);
// withdrawalFieldsArray[0] = withdrawalFields;

// cheats.expectRevert(bytes("EigenPod.verifyAndProcessWithdrawals: inputs must be same length"));
// pod.verifyAndProcessWithdrawals(0, stateRootProofStruct, withdrawalProofsArray, validatorFieldsProofArray, validatorFieldsArray, withdrawalFieldsArray);
// }
42 changes: 42 additions & 0 deletions src/test/events/IEigenPodEvents.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

interface IEigenPodEvents {
/// @notice Emitted when an ETH validator stakes via this eigenPod
event EigenPodStaked(bytes pubkey);

/// @notice Emitted when an ETH validator's withdrawal credentials are successfully verified to be pointed to this eigenPod
event ValidatorRestaked(uint40 validatorIndex);

/// @notice Emitted when an ETH validator's balance is proven to be updated. Here newValidatorBalanceGwei
// is the validator's balance that is credited on EigenLayer.
event ValidatorBalanceUpdated(uint40 validatorIndex, uint64 balanceTimestamp, uint64 newValidatorBalanceGwei);

/// @notice Emitted when an ETH validator is prove to have withdrawn from the beacon chain
event FullWithdrawalRedeemed(
uint40 validatorIndex,
uint64 withdrawalTimestamp,
address indexed recipient,
uint64 withdrawalAmountGwei
);

/// @notice Emitted when a partial withdrawal claim is successfully redeemed
event PartialWithdrawalRedeemed(
uint40 validatorIndex,
uint64 withdrawalTimestamp,
address indexed recipient,
uint64 partialWithdrawalAmountGwei
);

/// @notice Emitted when restaked beacon chain ETH is withdrawn from the eigenPod.
event RestakedBeaconChainETHWithdrawn(address indexed recipient, uint256 amount);

/// @notice Emitted when podOwner enables restaking
event RestakingActivated(address indexed podOwner);

/// @notice Emitted when ETH is received via the `receive` fallback
event NonBeaconChainETHReceived(uint256 amountReceived);

/// @notice Emitted when ETH that was previously received via the `receive` fallback is withdrawn
event NonBeaconChainETHWithdrawn(address indexed recipient, uint256 amountWithdrawn);
}
40 changes: 38 additions & 2 deletions src/test/harnesses/EigenPodHarness.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,38 @@ contract EPInternalFunctions is EigenPod {
_GENESIS_TIME
) {}

function verifyWithdrawalCredentials(
uint64 oracleTimestamp,
bytes32 beaconStateRoot,
uint40 validatorIndex,
bytes calldata validatorFieldsProof,
bytes32[] calldata validatorFields
) public returns (uint256) {
return _verifyWithdrawalCredentials(
oracleTimestamp,
beaconStateRoot,
validatorIndex,
validatorFieldsProof,
validatorFields
);
}

function verifyAndProcessWithdrawal(
bytes32 beaconStateRoot,
BeaconChainProofs.WithdrawalProof calldata withdrawalProof,
bytes calldata validatorFieldsProof,
bytes32[] calldata validatorFields,
bytes32[] calldata withdrawalFields
) public returns (IEigenPod.VerifiedWithdrawal memory) {
return _verifyAndProcessWithdrawal(
beaconStateRoot,
withdrawalProof,
validatorFieldsProof,
validatorFields,
withdrawalFields
);
}

function processFullWithdrawal(
uint40 validatorIndex,
bytes32 validatorPubkeyHash,
Expand Down Expand Up @@ -59,11 +91,11 @@ contract EPInternalFunctions is EigenPod {
bytes32[] calldata validatorFields,
uint64 mostRecentBalanceUpdateTimestamp
)
public
public returns (int256)
{
bytes32 pkhash = validatorFields[0];
_validatorPubkeyHashToInfo[pkhash].mostRecentBalanceUpdateTimestamp = mostRecentBalanceUpdateTimestamp;
_verifyBalanceUpdate(
return _verifyBalanceUpdate(
oracleTimestamp,
validatorIndex,
beaconStateRoot,
Expand All @@ -75,4 +107,8 @@ contract EPInternalFunctions is EigenPod {
function setValidatorStatus(bytes32 pkhash, VALIDATOR_STATUS status) public {
_validatorPubkeyHashToInfo[pkhash].status = status;
}

function setValidatorRestakedBalance(bytes32 pkhash, uint64 restakedBalanceGwei) public {
_validatorPubkeyHashToInfo[pkhash].restakedBalanceGwei = restakedBalanceGwei;
}
}
1 change: 0 additions & 1 deletion src/test/mocks/DelayedWithdrawalRouterMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity >=0.5.0;

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


contract DelayedWithdrawalRouterMock is IDelayedWithdrawalRouter {
/**
* @notice Creates an delayed withdrawal for `msg.value` to the `recipient`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +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"]}
2 changes: 1 addition & 1 deletion src/test/test-data/fullWithdrawalProof_Latest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"slot": 6397852,
"validatorIndex": 0,
"validatorIndex": 302913,
"historicalSummaryIndex": 146,
"withdrawalIndex": 0,
"blockHeaderRootIndex": 8092,
Expand Down
Loading