@@ -18,6 +18,7 @@ import "src/test/integration/users/User_M1.t.sol";
18
18
abstract contract IntegrationBase is IntegrationDeployer , TypeImporter {
19
19
using StdStyle for * ;
20
20
using SlashingLib for * ;
21
+ using Math for uint256 ;
21
22
using Strings for * ;
22
23
using print for * ;
23
24
@@ -68,6 +69,35 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
68
69
return (staker, strategies, tokenBalances);
69
70
}
70
71
72
+ function _newBasicStaker () internal returns (User, IStrategy[] memory , uint [] memory ) {
73
+ string memory stakerName;
74
+
75
+ User staker;
76
+ IStrategy[] memory strategies;
77
+ uint [] memory tokenBalances;
78
+
79
+ if (! isUpgraded) {
80
+ stakerName = string .concat ("M2Staker " , cheats.toString (numStakers));
81
+
82
+ (staker, strategies, tokenBalances) = _randUser (stakerName);
83
+
84
+ stakersToMigrate.push (staker);
85
+ } else {
86
+ stakerName = string .concat ("staker " , cheats.toString (numStakers));
87
+
88
+ (staker, strategies, tokenBalances) = _randUser (stakerName);
89
+ }
90
+
91
+ assert_HasUnderlyingTokenBalances (staker, strategies, tokenBalances, "_newRandomStaker: failed to award token balances " );
92
+
93
+ numStakers++ ;
94
+ assembly { // TODO HACK
95
+ mstore (strategies, 1 )
96
+ mstore (tokenBalances, 1 )
97
+ }
98
+ return (staker, strategies, tokenBalances);
99
+ }
100
+
71
101
/**
72
102
* @dev Create a new operator according to configured random variants.
73
103
* This user will immediately deposit their randomized assets into eigenlayer.
@@ -835,6 +865,29 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
835
865
}
836
866
}
837
867
868
+ function assert_Snap_Slashed_SlashableStake (
869
+ User operator ,
870
+ OperatorSet memory operatorSet ,
871
+ SlashingParams memory params ,
872
+ string memory err
873
+ ) internal {
874
+ uint [] memory curSlashableStake = _getMinSlashableStake (operator, operatorSet, params.strategies);
875
+ uint [] memory prevSlashableStake = _getPrevMinSlashableStake (operator, operatorSet, params.strategies);
876
+
877
+ Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, params.strategies);
878
+ Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, params.strategies);
879
+
880
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
881
+ uint expectedSlashed = SlashingLib.calcSlashedAmount ({
882
+ operatorShares: prevSlashableStake[i],
883
+ prevMaxMagnitude: prevMagnitudes[i].max,
884
+ newMaxMagnitude: curMagnitudes[i].max
885
+ });
886
+
887
+ assertEq (curSlashableStake[i], prevSlashableStake[i] - expectedSlashed, err);
888
+ }
889
+ }
890
+
838
891
function assert_Snap_StakeBecameAllocated (
839
892
User operator ,
840
893
OperatorSet memory operatorSet ,
@@ -877,6 +930,29 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
877
930
}
878
931
}
879
932
933
+ function assert_Snap_Slashed_AllocatedStake (
934
+ User operator ,
935
+ OperatorSet memory operatorSet ,
936
+ SlashingParams memory params ,
937
+ string memory err
938
+ ) internal {
939
+ uint [] memory curAllocatedStake = _getAllocatedStake (operator, operatorSet, params.strategies);
940
+ uint [] memory prevAllocatedStake = _getPrevAllocatedStake (operator, operatorSet, params.strategies);
941
+
942
+ Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, params.strategies);
943
+ Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, params.strategies);
944
+
945
+ for (uint i = 0 ; i < curAllocatedStake.length ; i++ ) {
946
+ uint expectedSlashed = SlashingLib.calcSlashedAmount ({
947
+ operatorShares: prevAllocatedStake[i],
948
+ prevMaxMagnitude: prevMagnitudes[i].max,
949
+ newMaxMagnitude: curMagnitudes[i].max
950
+ });
951
+
952
+ assertEq (curAllocatedStake[i], prevAllocatedStake[i] - expectedSlashed, err);
953
+ }
954
+ }
955
+
880
956
function assert_Snap_Added_EncumberedMagnitude (
881
957
User operator ,
882
958
IStrategy[] memory strategies ,
@@ -918,6 +994,20 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
918
994
}
919
995
}
920
996
997
+ function assert_Snap_Slashed_EncumberedMagnitude (
998
+ User operator ,
999
+ SlashingParams memory params ,
1000
+ string memory err
1001
+ ) internal {
1002
+ Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, params.strategies);
1003
+ Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, params.strategies);
1004
+
1005
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1006
+ uint expectedSlashed = prevMagnitudes[i].encumbered.mulWadRoundUp (params.wadsToSlash[i]);
1007
+ assertEq (curMagnitudes[i].encumbered, prevMagnitudes[i].encumbered - expectedSlashed, err);
1008
+ }
1009
+ }
1010
+
921
1011
function assert_Snap_Added_AllocatableMagnitude (
922
1012
User operator ,
923
1013
IStrategy[] memory strategies ,
@@ -948,14 +1038,14 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
948
1038
function assert_Snap_Removed_AllocatableMagnitude (
949
1039
User operator ,
950
1040
IStrategy[] memory strategies ,
951
- uint64 [] memory magnitudeAllocated ,
1041
+ uint64 [] memory magnitudeRemoved ,
952
1042
string memory err
953
1043
) internal {
954
1044
Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, strategies);
955
1045
Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, strategies);
956
1046
957
1047
for (uint i = 0 ; i < strategies.length ; i++ ) {
958
- assertEq (curMagnitudes[i].allocatable, prevMagnitudes[i].allocatable - magnitudeAllocated [i], err);
1048
+ assertEq (curMagnitudes[i].allocatable, prevMagnitudes[i].allocatable - magnitudeRemoved [i], err);
959
1049
}
960
1050
}
961
1051
@@ -1009,6 +1099,21 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
1009
1099
}
1010
1100
}
1011
1101
1102
+ function assert_Snap_Slashed_Allocation (
1103
+ User operator ,
1104
+ OperatorSet memory operatorSet ,
1105
+ SlashingParams memory params ,
1106
+ string memory err
1107
+ ) internal {
1108
+ Allocation[] memory curAllocations = _getAllocations (operator, operatorSet, params.strategies);
1109
+ Allocation[] memory prevAllocations = _getPrevAllocations (operator, operatorSet, params.strategies);
1110
+
1111
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1112
+ uint expectedSlashed = prevAllocations[i].currentMagnitude.mulWadRoundUp (params.wadsToSlash[i]);
1113
+ assertEq (curAllocations[i].currentMagnitude, prevAllocations[i].currentMagnitude - expectedSlashed, err);
1114
+ }
1115
+ }
1116
+
1012
1117
function assert_Snap_Unchanged_MaxMagnitude (
1013
1118
User operator ,
1014
1119
IStrategy[] memory strategies ,
@@ -1022,6 +1127,20 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
1022
1127
}
1023
1128
}
1024
1129
1130
+ function assert_Snap_Slashed_MaxMagnitude (
1131
+ User operator ,
1132
+ SlashingParams memory params ,
1133
+ string memory err
1134
+ ) internal {
1135
+ Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, params.strategies);
1136
+ Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, params.strategies);
1137
+
1138
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1139
+ uint expectedSlashed = prevMagnitudes[i].max.mulWadRoundUp (params.wadsToSlash[i]);
1140
+ assertEq (curMagnitudes[i].max, prevMagnitudes[i].max - expectedSlashed, err);
1141
+ }
1142
+ }
1143
+
1025
1144
function assert_Snap_Allocations_Slashed (
1026
1145
SlashingParams memory slashingParams ,
1027
1146
OperatorSet memory operatorSet ,
@@ -1237,6 +1356,47 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
1237
1356
}
1238
1357
}
1239
1358
1359
+ function assert_Snap_Slashed_OperatorShares (
1360
+ User operator ,
1361
+ SlashingParams memory params ,
1362
+ string memory err
1363
+ ) internal {
1364
+ uint [] memory curShares = _getOperatorShares (operator, params.strategies);
1365
+ uint [] memory prevShares = _getPrevOperatorShares (operator, params.strategies);
1366
+
1367
+ Magnitudes[] memory curMagnitudes = _getMagnitudes (operator, params.strategies);
1368
+ Magnitudes[] memory prevMagnitudes = _getPrevMagnitudes (operator, params.strategies);
1369
+
1370
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1371
+ uint expectedSlashed = SlashingLib.calcSlashedAmount ({
1372
+ operatorShares: prevShares[i],
1373
+ prevMaxMagnitude: prevMagnitudes[i].max,
1374
+ newMaxMagnitude: curMagnitudes[i].max
1375
+ });
1376
+
1377
+ assertEq (curShares[i], prevShares[i] - expectedSlashed, err);
1378
+ }
1379
+ }
1380
+
1381
+ function assert_Snap_Increased_BurnableShares (
1382
+ User operator ,
1383
+ SlashingParams memory params ,
1384
+ string memory err
1385
+ ) internal {
1386
+ uint [] memory curBurnable = _getBurnableShares (params.strategies);
1387
+ uint [] memory prevBurnable = _getPrevBurnableShares (params.strategies);
1388
+
1389
+ uint [] memory curShares = _getOperatorShares (operator, params.strategies);
1390
+ uint [] memory prevShares = _getPrevOperatorShares (operator, params.strategies);
1391
+
1392
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1393
+ uint slashedAtLeast = prevShares[i] - curShares[i];
1394
+
1395
+ // Not factoring in slashable shares in queue here, because that gets more complex (TODO)
1396
+ assertTrue (curBurnable[i] >= (prevBurnable[i] + slashedAtLeast), err);
1397
+ }
1398
+ }
1399
+
1240
1400
/*******************************************************************************
1241
1401
SNAPSHOT ASSERTIONS: STAKER SHARES
1242
1402
*******************************************************************************/
@@ -1787,12 +1947,34 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
1787
1947
Magnitudes[] memory magnitudes = _getMagnitudes (operator, strategies);
1788
1948
1789
1949
for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1790
- IStrategy strategy = params.strategies[i];
1791
1950
uint64 halfAvailable = uint64 (magnitudes[i].allocatable) / 2 ;
1792
1951
params.newMagnitudes[i] = allocations[i].currentMagnitude + halfAvailable;
1793
1952
}
1794
1953
}
1795
1954
1955
+ /// @dev Generate params to allocate a random portion of available magnitude to each strategy
1956
+ /// in the operator set. All strategies will have a nonzero allocation, and the minimum allocation
1957
+ /// will be 10% of available magnitude
1958
+ function _genAllocation_Rand (
1959
+ User operator ,
1960
+ OperatorSet memory operatorSet
1961
+ ) internal returns (AllocateParams memory params ) {
1962
+ params.operatorSet = operatorSet;
1963
+ params.strategies = allocationManager.getStrategiesInOperatorSet (operatorSet);
1964
+ params.newMagnitudes = new uint64 [](params.strategies.length );
1965
+
1966
+ Allocation[] memory allocations = _getAllocations (operator, operatorSet, params.strategies);
1967
+ Magnitudes[] memory magnitudes = _getMagnitudes (operator, params.strategies);
1968
+
1969
+ for (uint i = 0 ; i < params.strategies.length ; i++ ) {
1970
+ // minimum of 10%, maximum of 100%. increments of 10%.
1971
+ uint r = _randUint ({min: 1 , max: 10 });
1972
+ uint64 allocation = uint64 (magnitudes[i].allocatable) / uint64 (r);
1973
+
1974
+ params.newMagnitudes[i] = allocations[i].currentMagnitude + allocation;
1975
+ }
1976
+ }
1977
+
1796
1978
/// @dev Generates params for a half deallocation from all strategies the operator is allocated to in the operator set
1797
1979
function _genDeallocation_HalfRemaining (
1798
1980
User operator ,
@@ -1838,12 +2020,46 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
1838
2020
User operator ,
1839
2021
OperatorSet memory operatorSet ,
1840
2022
IStrategy[] memory strategies
1841
- ) internal view returns (AllocateParams memory params ) {
2023
+ ) internal pure returns (AllocateParams memory params ) {
1842
2024
params.operatorSet = operatorSet;
1843
2025
params.strategies = strategies;
1844
2026
params.newMagnitudes = new uint64 [](params.strategies.length );
1845
2027
}
1846
2028
2029
+ /// Generate random slashing between 1 and 99%
2030
+ function _genSlashing_Rand (
2031
+ User operator ,
2032
+ OperatorSet memory operatorSet
2033
+ ) internal returns (SlashingParams memory params ) {
2034
+ params.operator = address (operator);
2035
+ params.operatorSetId = operatorSet.id;
2036
+ params.description = "genSlashing_Half " ;
2037
+ params.strategies = allocationManager.getStrategiesInOperatorSet (operatorSet).sort ();
2038
+ params.wadsToSlash = new uint [](params.strategies.length );
2039
+
2040
+ /// 1% * rand(1, 99)
2041
+ uint slashWad = 1e16 * _randUint ({min: 1 , max: 99 });
2042
+
2043
+ for (uint i = 0 ; i < params.wadsToSlash.length ; i++ ) {
2044
+ params.wadsToSlash[i] = slashWad;
2045
+ }
2046
+ }
2047
+
2048
+ function _genSlashing_Half (
2049
+ User operator ,
2050
+ OperatorSet memory operatorSet
2051
+ ) internal view returns (SlashingParams memory params ) {
2052
+ params.operator = address (operator);
2053
+ params.operatorSetId = operatorSet.id;
2054
+ params.description = "genSlashing_Half " ;
2055
+ params.strategies = allocationManager.getStrategiesInOperatorSet (operatorSet).sort ();
2056
+ params.wadsToSlash = new uint [](params.strategies.length );
2057
+
2058
+ for (uint i = 0 ; i < params.wadsToSlash.length ; i++ ) {
2059
+ params.wadsToSlash[i] = 1e17 ;
2060
+ }
2061
+ }
2062
+
1847
2063
function _randWadToSlash () internal returns (uint ) {
1848
2064
return _randUint ({ min: 0.01 ether, max: 1 ether });
1849
2065
}
@@ -2371,6 +2587,38 @@ abstract contract IntegrationBase is IntegrationDeployer, TypeImporter {
2371
2587
return allocationManager.isMemberOfOperatorSet (address (operator), operatorSet);
2372
2588
}
2373
2589
2590
+ function _getPrevBurnableShares (IStrategy[] memory strategies ) internal timewarp () returns (uint [] memory ) {
2591
+ return _getBurnableShares (strategies);
2592
+ }
2593
+
2594
+ function _getBurnableShares (IStrategy[] memory strategies ) internal view returns (uint [] memory ) {
2595
+ uint [] memory burnableShares = new uint [](strategies.length );
2596
+
2597
+ for (uint i = 0 ; i < strategies.length ; i++ ) {
2598
+ if (strategies[i] == beaconChainETHStrategy) {
2599
+ burnableShares[i] = eigenPodManager.burnableETHShares ();
2600
+ } else {
2601
+ burnableShares[i] = strategyManager.getBurnableShares (strategies[i]);
2602
+ }
2603
+ }
2604
+
2605
+ return burnableShares;
2606
+ }
2607
+
2608
+ function _getPrevSlashableSharesInQueue (User operator , IStrategy[] memory strategies ) internal timewarp () returns (uint [] memory ) {
2609
+ return _getSlashableSharesInQueue (operator, strategies);
2610
+ }
2611
+
2612
+ function _getSlashableSharesInQueue (User operator , IStrategy[] memory strategies ) internal view returns (uint [] memory ) {
2613
+ uint [] memory slashableShares = new uint [](strategies.length );
2614
+
2615
+ for (uint i = 0 ; i < strategies.length ; i++ ) {
2616
+ slashableShares[i] = delegationManager.getSlashableSharesInQueue (address (operator), strategies[i]);
2617
+ }
2618
+
2619
+ return slashableShares;
2620
+ }
2621
+
2374
2622
/// @dev Uses timewarp modifier to get operator shares at the last snapshot
2375
2623
function _getPrevOperatorShares (
2376
2624
User operator ,
0 commit comments