From de39e63c7929928e88d1d799fe70a3f06877aecd Mon Sep 17 00:00:00 2001 From: ChaoticWalrus <93558947+ChaoticWalrus@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:40:42 -0700 Subject: [PATCH 1/2] add test which verifies that delegated shares are added to the correct operator when completing a withdrawal as shares also fix the EigenPodManagerMock to return an appropriate value for the 'increase in delegateable shares' --- src/test/mocks/EigenPodManagerMock.sol | 5 +- src/test/unit/DelegationUnit.t.sol | 93 ++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/test/mocks/EigenPodManagerMock.sol b/src/test/mocks/EigenPodManagerMock.sol index 5107589af..3a0651952 100644 --- a/src/test/mocks/EigenPodManagerMock.sol +++ b/src/test/mocks/EigenPodManagerMock.sol @@ -65,7 +65,10 @@ contract EigenPodManagerMock is IEigenPodManager, Test { function podOwnerShares(address podOwner) external view returns (int256) {} - function addShares(address podOwner, uint256 shares) external returns (uint256) {} + function addShares(address /*podOwner*/, uint256 shares) external returns (uint256) { + // this is the "increase in delegateable tokens" + return (shares); + } function withdrawSharesAsTokens(address podOwner, address destination, uint256 shares) external {} diff --git a/src/test/unit/DelegationUnit.t.sol b/src/test/unit/DelegationUnit.t.sol index 0e3e2eebf..8af7b219e 100644 --- a/src/test/unit/DelegationUnit.t.sol +++ b/src/test/unit/DelegationUnit.t.sol @@ -2279,6 +2279,99 @@ contract DelegationUnitTests is EigenLayerTestHelper { } } + // ensures that when the staker and withdrawer are different and a withdrawal is completed as shares (i.e. not as tokens) + // that the shares get added back to the right operator + function test_completingWithdrawalAsSharesAddsSharesToCorrectOperator() external { + address staker = address(this); + address withdrawer = address(1000); + address operator_for_staker = address(1001); + address operator_for_withdrawer = address(1002); + + // register operators + bytes32 salt; + IDelegationManager.OperatorDetails memory operatorDetails = IDelegationManager.OperatorDetails({ + earningsReceiver: operator_for_staker, + delegationApprover: address(0), + stakerOptOutWindowBlocks: 0 + }); + testRegisterAsOperator(operator_for_staker, operatorDetails, emptyStringForMetadataURI); + testRegisterAsOperator(operator_for_withdrawer, operatorDetails, emptyStringForMetadataURI); + + // delegate from the `staker` and withdrawer to the operators + ISignatureUtils.SignatureWithExpiry memory approverSignatureAndExpiry; + cheats.startPrank(staker); + delegationManager.delegateTo(operator_for_staker, approverSignatureAndExpiry, salt); + cheats.stopPrank(); + cheats.startPrank(withdrawer); + delegationManager.delegateTo(operator_for_withdrawer, approverSignatureAndExpiry, salt); + cheats.stopPrank(); + + // Setup input params + IStrategy[] memory strategies = new IStrategy[](3); + strategies[0] = strategyMock; + strategies[1] = delegationManager.beaconChainETHStrategy(); + strategies[2] = strategyMock3; + uint256[] memory amounts = new uint256[](3); + amounts[0] = 1e18; + amounts[1] = 2e18; + amounts[2] = 3e18; + + ( + IDelegationManager.Withdrawal memory withdrawal, + bytes32 withdrawalRoot + ) = _setUpWithdrawalStruct_MultipleStrategies({ + staker: staker, + withdrawer: withdrawer, + strategyArray: strategies, + shareAmounts: amounts + }); + + // give both the operators a bunch of delegated shares, so we can decrement them when queuing the withdrawal + cheats.startPrank(address(delegationManager.strategyManager())); + for (uint256 i = 0; i < strategies.length; ++i) { + delegationManager.increaseDelegatedShares(staker, strategies[i], amounts[i]); + delegationManager.increaseDelegatedShares(withdrawer, strategies[i], amounts[i]); + } + cheats.stopPrank(); + + // queue the withdrawal + cheats.startPrank(staker); + delegationManager.queueWithdrawal(strategies, amounts, withdrawer); + cheats.stopPrank(); + + for (uint256 i = 0; i < strategies.length; ++i) { + require(delegationManager.operatorShares(operator_for_staker, strategies[i]) == 0, + "staker operator shares incorrect after queueing"); + require(delegationManager.operatorShares(operator_for_withdrawer, strategies[i]) == amounts[i], + "withdrawer operator shares incorrect after queuing"); + } + + // complete the withdrawal + cheats.startPrank(withdrawer); + IERC20[] memory tokens; + delegationManager.completeQueuedWithdrawal( + withdrawal, + tokens, + 0 /*middlewareTimesIndex*/, + false /*receiveAsTokens*/ + ); + cheats.stopPrank(); + + for (uint256 i = 0; i < strategies.length; ++i) { + if (strategies[i] != delegationManager.beaconChainETHStrategy()) { + require(delegationManager.operatorShares(operator_for_staker, strategies[i]) == 0, + "staker operator shares incorrect after completing withdrawal"); + require(delegationManager.operatorShares(operator_for_withdrawer, strategies[i]) == 2 * amounts[i], + "withdrawer operator shares incorrect after completing withdrawal"); + } else { + require(delegationManager.operatorShares(operator_for_staker, strategies[i]) == amounts[i], + "staker operator beaconChainETHStrategy shares incorrect after completing withdrawal"); + require(delegationManager.operatorShares(operator_for_withdrawer, strategies[i]) == amounts[i], + "withdrawer operator beaconChainETHStrategy shares incorrect after completing withdrawal"); + } + } + } + /** * INTERNAL / HELPER FUNCTIONS */ From 8a338a065335703a72607c12d79ce19fcf9018ff Mon Sep 17 00:00:00 2001 From: ChaoticWalrus <93558947+ChaoticWalrus@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:58:23 -0700 Subject: [PATCH 2/2] fix to flaky test this test failed when the caller was fuzzed to be the ProxyAdmin --- src/test/unit/EigenPodUnit.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/EigenPodUnit.t.sol b/src/test/unit/EigenPodUnit.t.sol index 1ad502e05..6e4fa44a8 100644 --- a/src/test/unit/EigenPodUnit.t.sol +++ b/src/test/unit/EigenPodUnit.t.sol @@ -102,7 +102,7 @@ contract EigenPodUnitTests is EigenPodTests { } //post M2, all new pods deployed will have "hasRestaked = true". THis tests that - function testDeployedPodIsRestaked(address podOwner) public { + function testDeployedPodIsRestaked(address podOwner) public fuzzedAddress(podOwner) { cheats.startPrank(podOwner); eigenPodManager.createPod(); cheats.stopPrank();