Skip to content

Commit 1d926f2

Browse files
authored
Merge pull request #293 from Layr-Labs/test/strategy-manager-cleanup
StrategyManager Unit Test Refactor
2 parents d498377 + d30521e commit 1d926f2

10 files changed

+1154
-819
lines changed

src/test/WithdrawalMigration.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pragma solidity =0.8.12;
33

44
import "../test/EigenLayerTestHelper.t.sol";
5-
import "./unit/Utils.sol";
5+
import "src/test/utils/Utils.sol";
66
import "./mocks/ERC20Mock.sol";
77

88
///@notice This set of tests shadow forks the contracts from M1, queues withdrawals, and tests the migration functionality

src/test/tree/EigenPodManager.tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
├── EigenPodManager Tree (*** denotes that integrationt tests are needed to validate path)
2+
├── when contract is deployed and initialized
3+
│ └── it should properly set storage
4+
├── when initialize called again
5+
│ └── it should revert
6+
├── when createPod called
7+
│ ├── given the user has already created a pod
8+
│ │ └── it should revert
9+
│ ├── given that the max number of pods has been deployed
10+
│ │ └── it should revert
11+
│ └── given the user has not created a pod
12+
│ └── it should deploy a pod
13+
├── when stake is called
14+
│ ├── given the user has not created a pod
15+
│ │ └── it should deploy a pod
16+
│ └── given the user has already created a pod
17+
│ └── it should call stake on the eigenPod
18+
├── when setMaxPods is called
19+
│ ├── given the user is not the pauser
20+
│ │ └── it should revert
21+
│ └── given the user is the pauser
22+
│ └── it should set the max pods
23+
├── when updateBeaconChainOracle is called
24+
│ ├── given the user is not the owner
25+
│ │ └── it should revert
26+
│ └── given the user is the owner
27+
│ └── it should set the beacon chain oracle
28+
├── when addShares is called
29+
│ ├── given that the caller is not the delegationManager
30+
│ │ └── it should revert
31+
│ ├── given that the podOwner address is 0
32+
│ │ └── it should revert
33+
│ ├── given that the shares amount is negative
34+
│ │ └── it should revert
35+
│ ├── given that the shares is not a whole gwei amount
36+
│ │ └── it should revert
37+
│ └── given that all of the above conditions are satisfied
38+
│ └── it should update the podOwnerShares
39+
├── when removeShares is called
40+
│ ├── given that the caller is not the delegationManager
41+
│ │ └── it should revert
42+
│ ├── given that the shares amount is negative
43+
│ │ └── it should revert
44+
│ ├── given that the shares is not a whole gwei amount
45+
│ │ └── it should revert
46+
│ ├── given that removing shares results in the pod owner having negative shares
47+
│ │ └── it should revert
48+
│ └── given that all of the above conditions are satisfied
49+
│ └── it should update the podOwnerShares
50+
├── when withdrawSharesAsTokens is called
51+
│ ├── given that the podOwner is address 0
52+
│ │ └── it should revert
53+
│ ├── given that the destination is address 0
54+
│ │ └── it should revert
55+
│ ├── given that the shares amount is negative
56+
│ │ └── it should revert
57+
│ ├── given that the shares is not a whole gwei amount
58+
│ │ └── it should revert
59+
│ ├── given that the current podOwner shares are negative
60+
│ │ ├── given that the shares to withdraw are larger in magnitude than the shares of the podOwner
61+
│ │ │ └── it should set the podOwnerShares to 0 and decrement shares to withdraw by the share deficit
62+
│ │ └── given that the shares to withdraw are smaller in magnitude than shares of the podOwner
63+
│ │ └── it should increment the podOwner shares by the shares to withdraw
64+
│ └── given that the pod owner shares are positive
65+
│ └── it should withdraw restaked ETH from the eigenPod
66+
├── when shares are adjusted ***
67+
│ ├── given that sharesBefore is negative or 0
68+
│ │ ├── given that sharesAfter is negative or zero
69+
│ │ │ └── the change in delegateable shares should be 0
70+
│ │ └── given that sharesAfter is positive
71+
│ │ └── the change in delegateable shares should be positive
72+
│ └── given that sharesBefore is positive
73+
│ ├── given that sharesAfter is negative or zero
74+
│ │ └── the change in delegateable shares is negative sharesBefore
75+
│ └── given that sharesAfter is positive
76+
│ └── the change in delegateable shares is the difference between sharesAfter and sharesBefore
77+
└── when recordBeaconChainETHBalanceUpdate is called
78+
├── given that the podOwner's eigenPod is not the caller
79+
│ └── it should revert
80+
├── given that the podOwner is a zero address
81+
│ └── it should revert
82+
├── given that sharesDelta is not a whole gwei amount
83+
│ ├── it should revert
84+
│ └── given that the shares delta is valid
85+
│ └── it should update the podOwnerShares
86+
├── given that the change in delegateable shares is positive ***
87+
│ └── it should increase delegated shares on the delegationManager
88+
├── given that the change in delegateable shares is negative ***
89+
│ └── it should decrease delegated shares on the delegationManager
90+
├── given that the change in delegateable shares is 0 ***
91+
│ └── it should only update the podOwnerShares
92+
└── given that the function is reentered ***
93+
└── it should revert

src/test/tree/EigenPodManagerUnit.tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
├── EigenPodManager Tree (*** denotes that integrationt tests are needed to validate path)
1+
├── EigenPodManager Tree (*** denotes that integration tests are needed to validate path)
22
├── when contract is deployed and initialized
33
│ └── it should properly set storage
44
├── when initialize called again
@@ -23,7 +23,7 @@
2323
├── when updateBeaconChainOracle is called
2424
│ ├── given the user is not the owner
2525
│ │ └── it should revert
26-
│ └── given the user is the owner
26+
│ └── given the user is the owner
2727
│ └── it should set the beacon chain oracle
2828
├── when addShares is called
2929
│ ├── given that the caller is not the delegationManager
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
├── StrategyManagerUnit.t.sol (*** denotes that integration tests are needed to validate path)
2+
├── initialize
3+
| ├── given that initialized is only called once
4+
│ │ └── it should set the storage variables correctly (owner, strategyWhitelister, pauserRegistry)
5+
│ └── given that initialize is called again
6+
│ └── it should revert
7+
├── depositIntoStrategy()
8+
│ ├── given that deposits paused
9+
│ │ └── it should revert
10+
│ ├── given the function is re-entered
11+
│ │ └── it should revert
12+
│ ├── given that the strategy is not whitelisted
13+
│ │ └── it should revert
14+
│ ├── given the token safeTransferFrom() reverts
15+
│ │ └── it should revert
16+
│ └── given that token safeTransferFrom() succeeds
17+
│ ├── given the staker has existing shares in strategy (not first deposit)
18+
│ │ └── it should increase shares, nonce. while stakerStrategyListLength is unchanged
19+
│ ├── given the staker has no existing shares in strategy (first deposit)
20+
│ │ └── stakerStrategyListLength increases by 1 and shares increase
21+
│ ├── given the staker has delegated to a operator ***
22+
│ │ └── it should deposit successfully with shares increase, including delegated shares
23+
│ └── given the staker is not delegated
24+
│ └── it should deposit successfully with shares increase
25+
├── depositIntoStrategyWithSignature()
26+
│ ├── given that deposits paused
27+
│ │ └── it should revert
28+
│ ├── given the function is re-entered
29+
│ │ └── it should revert
30+
│ ├── given the signature expired
31+
│ │ └── it should revert
32+
│ ├── given that deposits paused and strategy not whitelisted
33+
│ │ └── it should revert
34+
│ ├── given the staker is a EOA
35+
│ │ ├── given the signature verification fails
36+
│ │ │ └── it should revert
37+
│ │ └── given the signature verification succeeds
38+
│ │ ├── given the token safeTransferFrom reverts
39+
│ │ │ └── it should revert
40+
│ │ └── given the token safeTransferFrom succeeds
41+
│ │ ├── given that the staker has delegated to a operator ***
42+
│ │ │ └── it should deposit successfully with shares and nonce increase, including delegated shares
43+
│ │ └── given that the staker is not delegated
44+
│ │ └── it should deposit successfully with shares and nonce increase
45+
│ └── given the staker is a contract
46+
│ ├── given the contract isn't EIP1271 compliant
47+
│ │ └── it should revert
48+
│ ├── given the signature verification fails, isValidSignature() return != EIP1271_MAGICVALUE
49+
│ │ └── it should revert
50+
│ └── given the signature verification succeeds, isValidSignature() returns EIP1271_MAGICVALUE
51+
│ ├── given the token safeTransferFrom reverts
52+
│ │ └── it should revert
53+
│ └── given the token safeTransferFrom succeeds
54+
│ ├── given the staker has delegated to a operator ***
55+
│ │ └── it should deposit successfully with shares and nonce increase, including delegated shares
56+
│ └── given the staker is not delegated
57+
│ └── it should deposit successfully with shares and nonce increase
58+
├── removeShares()
59+
│ ├── given not called by DelegationManager
60+
│ │ └── it should revert
61+
│ ├── given the share amount is 0
62+
│ │ └── it should revert
63+
│ ├── given the share amount is too high, higher than deposited amount
64+
│ │ └── it should revert
65+
│ ├── given the share amount is equal to the deposited amount
66+
│ │ └── staker shares should be 0 with decremented stakerStrategyListLength
67+
│ └── given the share amount is less than the deposited amount
68+
│ └── staker shares should now be deposited - shares amount, unchanged stakerStrategyListLength
69+
├── addShares()
70+
│ ├── given not called by DelegationManager
71+
│ │ └── it should revert
72+
│ ├── given the share amount is 0
73+
│ │ └── it should revert
74+
│ ├── given the staker is 0 address
75+
│ │ └── it should revert
76+
│ ├── given adding shares with 0 existing shares
77+
│ │ └── it should increase shares and increment stakerStrategyListLength
78+
│ ├── given adding shares with 0 existing shares and staker has MAX_STAKER_STRATEGY_LIST_LENGTH
79+
│ │ └── it should revert
80+
│ └── given the adding shares with > 0 existing shares
81+
│ └── it should increase shares, unchanged stakerStrategyListLength
82+
├── withdrawSharesAsTokens()
83+
│ ├── given not called by DelegationManager
84+
│ │ └── it should revert
85+
│ └── given that deposited strategy is called
86+
│ │ └── it should withdraw tokens from strategy with token balanceOf() update
87+
├── setStrategyWhitelister()
88+
│ ├── given not called by owner
89+
│ │ └── it should revert
90+
│ └── given called by owner address
91+
│ └── it should update strategyWhitelister address
92+
├── addStrategiesToDepositWhitelist()
93+
│ ├── given not called by strategyWhitelister address
94+
│ │ └── it should revert
95+
│ └── given the strategyWhitelister address is called
96+
│ ├── given adding one single strategy that is already whitelisted
97+
│ │ └── it should not emit StrategyAddedToDepositWhitelist with mapping still true
98+
│ ├── given adding one single strategy
99+
│ │ └── it should whitelist the new strategy with mapping set to true
100+
│ └── given adding multiple strategies to whitelist
101+
│ └── it should whitelist all new strategies with mappings set to true
102+
└── removeStrategiesFromDepositWhitelist()
103+
├── given not called by strategyWhitelister address
104+
│ └── it should revert
105+
└── given called by strategyWhitelister address
106+
├── given removing one single strategy that is not whitelisted
107+
│ └── it shouldn't emit StrategyRemovedFromDepositWhitelist with mapping still false
108+
├── given removing one single strategy
109+
│ └── it should de-whitelist the new strategy with mapping set to false
110+
└── given removing multiple strategies to whitelist
111+
└── it should de-whitelist all specified strategies with mappings set to false

src/test/unit/EigenPodManagerUnit.t.sol

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@ import "forge-std/Test.sol";
66

77
import "../../contracts/pods/EigenPodManager.sol";
88
import "../../contracts/pods/EigenPodPausingConstants.sol";
9-
import "../../contracts/permissions/PauserRegistry.sol";
109

1110
import "../events/IEigenPodManagerEvents.sol";
1211
import "../utils/EigenLayerUnitTestSetup.sol";
1312
import "../harnesses/EigenPodManagerWrapper.sol";
14-
import "../mocks/DelegationManagerMock.sol";
15-
import "../mocks/SlasherMock.sol";
16-
import "../mocks/StrategyManagerMock.sol";
1713
import "../mocks/EigenPodMock.sol";
1814
import "../mocks/ETHDepositMock.sol";
1915

@@ -24,14 +20,7 @@ contract EigenPodManagerUnitTests is EigenLayerUnitTestSetup {
2420

2521
using stdStorage for StdStorage;
2622

27-
// Proxy Admin & Pauser Registry
28-
ProxyAdmin public proxyAdmin;
29-
PauserRegistry public pauserRegistry;
30-
3123
// Mocks
32-
StrategyManagerMock public strategyManagerMock;
33-
DelegationManagerMock public delegationManagerMock;
34-
SlasherMock public slasherMock;
3524
IETHPOSDeposit public ethPOSMock;
3625
IEigenPod public eigenPodMockImplementation;
3726
IBeacon public eigenPodBeacon; // Proxy for eigenPodMockImplementation
@@ -43,19 +32,10 @@ contract EigenPodManagerUnitTests is EigenLayerUnitTestSetup {
4332
IEigenPod public defaultPod;
4433
address public initialOwner = address(this);
4534

46-
function setUp() virtual public {
47-
// Deploy ProxyAdmin
48-
proxyAdmin = new ProxyAdmin();
49-
50-
// Initialize PauserRegistry
51-
address[] memory pausers = new address[](1);
52-
pausers[0] = pauser;
53-
pauserRegistry = new PauserRegistry(pausers, unpauser);
35+
function setUp() virtual override public {
36+
EigenLayerUnitTestSetup.setUp();
5437

5538
// Deploy Mocks
56-
slasherMock = new SlasherMock();
57-
delegationManagerMock = new DelegationManagerMock();
58-
strategyManagerMock = new StrategyManagerMock();
5939
ethPOSMock = new ETHPOSDepositMock();
6040
eigenPodMockImplementation = new EigenPodMock();
6141
eigenPodBeacon = new UpgradeableBeacon(address(eigenPodMockImplementation));
@@ -72,7 +52,7 @@ contract EigenPodManagerUnitTests is EigenLayerUnitTestSetup {
7252
address(
7353
new TransparentUpgradeableProxy(
7454
address(eigenPodManagerImplementation),
75-
address(proxyAdmin),
55+
address(eigenLayerProxyAdmin),
7656
abi.encodeWithSelector(
7757
EigenPodManager.initialize.selector,
7858
type(uint256).max /*maxPods*/,
@@ -91,9 +71,8 @@ contract EigenPodManagerUnitTests is EigenLayerUnitTestSetup {
9171
// Set defaultPod
9272
defaultPod = eigenPodManager.getPod(defaultStaker);
9373

94-
// Exclude the zero address, the proxyAdmin and the eigenPodManager itself from fuzzed inputs
74+
// Exclude the zero address, and the eigenPodManager itself from fuzzed inputs
9575
addressIsExcludedFromFuzzedInputs[address(0)] = true;
96-
addressIsExcludedFromFuzzedInputs[address(proxyAdmin)] = true;
9776
addressIsExcludedFromFuzzedInputs[address(eigenPodManager)] = true;
9877
}
9978

@@ -541,7 +520,7 @@ contract EigenPodManagerUnitTests_ShareAdjustmentCalculationTests is EigenPodMan
541520
slasherMock,
542521
delegationManagerMock
543522
);
544-
proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(address(eigenPodManager))), address(eigenPodManagerWrapper));
523+
eigenLayerProxyAdmin.upgrade(TransparentUpgradeableProxy(payable(address(eigenPodManager))), address(eigenPodManagerWrapper));
545524
}
546525

547526
function testFuzz_shareAdjustment_negativeToNegative(int256 sharesBefore, int256 sharesAfter) public {
@@ -575,4 +554,4 @@ contract EigenPodManagerUnitTests_ShareAdjustmentCalculationTests is EigenPodMan
575554
int256 sharesDelta = eigenPodManagerWrapper.calculateChangeInDelegatableShares(sharesBefore, sharesAfter);
576555
assertEq(sharesDelta, sharesAfter - sharesBefore, "Shares delta must be equal to the difference between sharesAfter and sharesBefore");
577556
}
578-
}
557+
}

src/test/unit/SlasherUnit.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import "../mocks/Reverter.sol";
1818

1919
import "../mocks/ERC20Mock.sol";
2020

21-
import "./Utils.sol";
21+
import "src/test/utils/Utils.sol";
2222

2323
contract SlasherUnitTests is Test, Utils {
2424

0 commit comments

Comments
 (0)