diff --git a/test/integration/StakingNode.t.sol b/test/integration/StakingNode.t.sol index 07dff0d97..048fa9523 100644 --- a/test/integration/StakingNode.t.sol +++ b/test/integration/StakingNode.t.sol @@ -325,6 +325,7 @@ contract StakingNodeVerifyWithdrawalCredentials is StakingNodeTestBase { uint256 queuedShares; uint256 withdrawnETH; uint256 unverifiedStakedETH; + int256 podOwnerShares; } function takeSnapshot(uint256 nodeId) internal view returns (StateSnapshot memory) { @@ -334,7 +335,8 @@ contract StakingNodeVerifyWithdrawalCredentials is StakingNodeTestBase { stakingNodeBalance: stakingNodesManager.nodes(nodeId).getETHBalance(), queuedShares: stakingNodesManager.nodes(nodeId).getQueuedSharesAmount(), withdrawnETH: stakingNodesManager.nodes(nodeId).getWithdrawnETH(), - unverifiedStakedETH: stakingNodesManager.nodes(nodeId).unverifiedStakedETH() + unverifiedStakedETH: stakingNodesManager.nodes(nodeId).unverifiedStakedETH(), + podOwnerShares: eigenPodManager.podOwnerShares(address(stakingNodesManager.nodes(nodeId))) }); } @@ -400,84 +402,77 @@ contract StakingNodeVerifyWithdrawalCredentials is StakingNodeTestBase { vm.stopPrank(); } - // function testVerifyCheckpointsForOneValidator() public { - - // uint256 nodeId = createStakingNodes(1)[0]; - // // Call createValidators with the nodeIds array and validatorCount - // validatorIndices = createValidators(repeat(nodeId, 1), 1); - // beaconChain.advanceEpoch_NoRewards(); - // registerValidators(repeat(nodeId, 1)); + function testVerifyCheckpointsForOneValidator() public { + uint256 nodeId = createStakingNodes(1)[0]; + // Call createValidators with the nodeIds array and validatorCount + validatorIndices = createValidators(repeat(nodeId, 1), 1); + beaconChain.advanceEpoch_NoRewards(); + registerValidators(repeat(nodeId, 1)); - // uint40 validatorIndex = validatorIndices[0]; - - // { - // _verifyWithdrawalCredentials(nodeId, validatorIndex); - - // // check that unverifiedStakedETH is 0 and podOwnerShares is 32 ETH (AMOUNT) - // assertEq(stakingNodesManager.nodes(nodeId).unverifiedStakedETH(), 0, "_testVerifyWithdrawalCredentials: E0"); - // assertEq(uint256(eigenPodManager.podOwnerShares(address(stakingNodesManager.nodes(nodeId)))), AMOUNT, "_testVerifyWithdrawalCredentials: E1"); - // } - - // beaconChain.advanceEpoch(); - // // Capture initial state - // uint256 initialTotalAssets = yneth.totalAssets(); - // uint256 initialTotalSupply = yneth.totalSupply(); - // uint256 initialNodeBalance = stakingNodesManager.nodes(nodeId).getETHBalance(); - // uint256 initialQueuedShares = stakingNodesManager.nodes(nodeId).getQueuedSharesAmount(); - // uint256 initialWithdrawnETH = stakingNodesManager.nodes(nodeId).getWithdrawnETH(); - // uint256 initialUnverifiedStakedETH = stakingNodesManager.nodes(nodeId).unverifiedStakedETH(); - // uint256 initialPodOwnerShares = uint256(eigenPodManager.podOwnerShares(address(stakingNodesManager.nodes(nodeId)))); - - // // start checkpoint - // { - // vm.startPrank(actors.ops.STAKING_NODES_OPERATOR); - // stakingNodesManager.nodes(nodeId).startCheckpoint(true); - // vm.stopPrank(); - - // // make sure startCheckpoint cant be called again, which means that the checkpoint has started - // IStakingNode _node = stakingNodesManager.nodes(nodeId); - // vm.expectRevert("EigenPod._startCheckpoint: must finish previous checkpoint before starting another"); - // vm.prank(actors.ops.STAKING_NODES_OPERATOR); - // _node.startCheckpoint(true); - // } - - // // Assert that state remains unchanged after starting checkpoint - // assertEq(yneth.totalAssets(), initialTotalAssets, "Total assets changed after starting checkpoint"); - // assertEq(yneth.totalSupply(), initialTotalSupply, "Total supply changed after starting checkpoint"); - // assertEq(stakingNodesManager.nodes(nodeId).getETHBalance(), initialNodeBalance, "Node balance changed after starting checkpoint"); - // assertEq(stakingNodesManager.nodes(nodeId).getQueuedSharesAmount(), initialQueuedShares, "Queued shares changed after starting checkpoint"); - // assertEq(stakingNodesManager.nodes(nodeId).getWithdrawnETH(), initialWithdrawnETH, "Withdrawn ETH changed after starting checkpoint"); - // assertEq(stakingNodesManager.nodes(nodeId).unverifiedStakedETH(), initialUnverifiedStakedETH, "Unverified staked ETH changed after starting checkpoint"); - - // // verify checkpoints - // { - // uint40[] memory _validators = new uint40[](1); - // _validators[0] = validatorIndex; - // IStakingNode _node = stakingNodesManager.nodes(nodeId); - // CheckpointProofs memory _cpProofs = beaconChain.getCheckpointProofs(_validators, _node.eigenPod().currentCheckpointTimestamp()); - // IEigenPodSimplified(address(_node.eigenPod())).verifyCheckpointProofs({ - // balanceContainerProof: _cpProofs.balanceContainerProof, - // proofs: _cpProofs.balanceProofs - // }); - - // // check that proofsRemaining is 0 - // IEigenPod.Checkpoint memory _checkpoint = stakingNodesManager.nodes(nodeId).eigenPod().currentCheckpoint(); - // assertEq(_checkpoint.proofsRemaining, 0, "_testVerifyCheckpointsBeforeWithdrawalRequest: E0"); - - // // Assert that node balance and shares increased by the amount of rewards - // uint256 newPodOwnerShares = uint256(eigenPodManager.podOwnerShares(address(stakingNodesManager.nodes(nodeId)))); - // uint256 rewardsAmount = newPodOwnerShares - initialPodOwnerShares; - // assertGt(rewardsAmount, 0, "No rewards were added"); - // assertEq(stakingNodesManager.nodes(nodeId).getETHBalance(), initialNodeBalance + rewardsAmount, "Node balance did not increase by rewards amount"); - - // // Assert that other state variables remain unchanged - // assertEq(yneth.totalAssets(), initialTotalAssets, "Total assets changed after verification"); - // assertEq(yneth.totalSupply(), initialTotalSupply, "Total supply changed after verification"); - // assertEq(stakingNodesManager.nodes(nodeId).getQueuedSharesAmount(), initialQueuedShares, "Queued shares changed after verification"); - // assertEq(stakingNodesManager.nodes(nodeId).getWithdrawnETH(), initialWithdrawnETH, "Withdrawn ETH changed after verification"); - // assertEq(stakingNodesManager.nodes(nodeId).unverifiedStakedETH(), initialUnverifiedStakedETH, "Unverified staked ETH changed after verification"); - // } - // } + uint40 validatorIndex = validatorIndices[0]; + + { + _verifyWithdrawalCredentials(nodeId, validatorIndex); + + // check that unverifiedStakedETH is 0 and podOwnerShares is 32 ETH (AMOUNT) + assertEq(stakingNodesManager.nodes(nodeId).unverifiedStakedETH(), 0, "_testVerifyWithdrawalCredentials: E0"); + assertEq(uint256(eigenPodManager.podOwnerShares(address(stakingNodesManager.nodes(nodeId)))), AMOUNT, "_testVerifyWithdrawalCredentials: E1"); + } + + beaconChain.advanceEpoch(); + // Capture initial state + StateSnapshot memory initialState = takeSnapshot(nodeId); + + // start checkpoint + { + vm.startPrank(actors.ops.STAKING_NODES_OPERATOR); + stakingNodesManager.nodes(nodeId).startCheckpoint(true); + vm.stopPrank(); + + // make sure startCheckpoint cant be called again, which means that the checkpoint has started + IStakingNode _node = stakingNodesManager.nodes(nodeId); + vm.expectRevert("EigenPod._startCheckpoint: must finish previous checkpoint before starting another"); + vm.prank(actors.ops.STAKING_NODES_OPERATOR); + _node.startCheckpoint(true); + } + + // Assert that state remains unchanged after starting checkpoint + StateSnapshot memory afterStartCheckpoint = takeSnapshot(nodeId); + assertEq(afterStartCheckpoint.totalAssets, initialState.totalAssets, "Total assets changed after starting checkpoint"); + assertEq(afterStartCheckpoint.totalSupply, initialState.totalSupply, "Total supply changed after starting checkpoint"); + assertEq(afterStartCheckpoint.stakingNodeBalance, initialState.stakingNodeBalance, "Node balance changed after starting checkpoint"); + assertEq(afterStartCheckpoint.queuedShares, initialState.queuedShares, "Queued shares changed after starting checkpoint"); + assertEq(afterStartCheckpoint.withdrawnETH, initialState.withdrawnETH, "Withdrawn ETH changed after starting checkpoint"); + assertEq(afterStartCheckpoint.unverifiedStakedETH, initialState.unverifiedStakedETH, "Unverified staked ETH changed after starting checkpoint"); + + // verify checkpoints + { + uint40[] memory _validators = new uint40[](1); + _validators[0] = validatorIndex; + IStakingNode _node = stakingNodesManager.nodes(nodeId); + CheckpointProofs memory _cpProofs = beaconChain.getCheckpointProofs(_validators, _node.eigenPod().currentCheckpointTimestamp()); + IEigenPodSimplified(address(_node.eigenPod())).verifyCheckpointProofs({ + balanceContainerProof: _cpProofs.balanceContainerProof, + proofs: _cpProofs.balanceProofs + }); + + // check that proofsRemaining is 0 + IEigenPod.Checkpoint memory _checkpoint = stakingNodesManager.nodes(nodeId).eigenPod().currentCheckpoint(); + assertEq(_checkpoint.proofsRemaining, 0, "_testVerifyCheckpointsBeforeWithdrawalRequest: E0"); + + // Assert that node balance and shares increased by the amount of rewards + StateSnapshot memory afterVerification = takeSnapshot(nodeId); + uint256 rewardsAmount = uint256(afterVerification.podOwnerShares - initialState.podOwnerShares); + assertEq(afterVerification.stakingNodeBalance, initialState.stakingNodeBalance + rewardsAmount, "Node balance did not increase by rewards amount"); + + // Assert that other state variables remain unchanged + assertEq(afterVerification.totalAssets, initialState.totalAssets, "Total assets changed after verification"); + assertEq(afterVerification.totalSupply, initialState.totalSupply, "Total supply changed after verification"); + assertEq(afterVerification.queuedShares, initialState.queuedShares, "Queued shares changed after verification"); + assertEq(afterVerification.withdrawnETH, initialState.withdrawnETH, "Withdrawn ETH changed after verification"); + assertEq(afterVerification.unverifiedStakedETH, initialState.unverifiedStakedETH, "Unverified staked ETH changed after verification"); + } + } function testVerifyCheckpointsForManyValidators() public {