Skip to content

Commit 590031b

Browse files
committed
test: clean up and minor refactors
1 parent f2e52b0 commit 590031b

File tree

1 file changed

+40
-45
lines changed

1 file changed

+40
-45
lines changed

src/test/integration/tests/Rounding.t.sol

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ contract Integration_Rounding is IntegrationCheckUtils {
1717
OperatorSet mOpSet; // "manipOpSet" used for magnitude manipulation
1818
OperatorSet rOpSet; // Redistributable opset used to exploit precision loss and trigger redistribution
1919

20+
uint numSlashes = 50;
21+
2022
function _init() internal override {
2123
_configAssetTypes(HOLDS_LST);
2224

@@ -28,7 +30,8 @@ contract Integration_Rounding is IntegrationCheckUtils {
2830
// Prepares to add non-attacker stake into the protocol. Can be any amount > 0.
2931
// Note that the honest stake does not need to be allocated anywhere, so long as it's in the same strategy.
3032
goodStaker = new User("GoodStaker");
31-
deal(address(token), address(goodStaker), uint256(1e18));
33+
deal(address(token), address(goodStaker), uint256(1e18));
34+
goodStaker.depositIntoEigenlayer(strategy.toArray(), 1e18.toArrayU256());
3235

3336
// Register attacker as operator and create attacker-controlled AVS/OpSets
3437
attacker.registerAsOperator(0);
@@ -45,36 +48,33 @@ contract Integration_Rounding is IntegrationCheckUtils {
4548
}
4649

4750
// TODO: consider incremental manual fuzzing from 1 up to WAD - 1
48-
function test_rounding_allMagsSlashed(uint16 slashes, uint64 initialWadToSlash, uint64 _initTokenBalance, uint24 r) public rand(r) {
51+
function test_rounding_allMagsSlashed(
52+
uint64 initialWadToSlash,
53+
uint64 _initTokenBalance
54+
) public rand(0) {
4955
vm.pauseGasMetering();
50-
// Bound slashes to a reasonable range, with at least 1 slash.
51-
// Note: Runs after 2500 hit OOG errors with default gas.
52-
slashes = uint16(bound(slashes, 1, 5000));
53-
54-
// We do two slashes, the sum of which slash 1 WAD (all operator magnitude) in total.
55-
// Each slash requires at least 1 mag. As such, we need to bound wadToSlash to 1 <= wadToSlash <= WAD - 1.
56+
// Don't slash 100% as we will do multiple slashes
5657
initialWadToSlash = uint64(bound(initialWadToSlash, 1, WAD - 1));
57-
58-
// Bound initTokenBalance to a reasonable range to avoid overflow, with at least 1 token.
59-
// Using ~18.45 quintillion tokens max (should be enough for any realistic test).
60-
initTokenBalance = uint64(bound(_initTokenBalance, 1, type(uint64).max));
58+
// Ensure attacker has at least one token
59+
initTokenBalance = _initTokenBalance > 0 ? _initTokenBalance : _initTokenBalance + 1;
6160
deal(address(token), address(attacker), initTokenBalance);
6261

63-
_magnitudeManipulation(initialWadToSlash); // Manipulate operator magnitude for a given strategy.
64-
_deposit(initialWadToSlash); // Setup operator with new opSet as well as honest stake in same strategy.
62+
// Use modifyAllocation+slashOperator to arbitrarily set operator max magnitude
63+
_magnitudeManipulation(initialWadToSlash);
64+
_deposit();
6565

6666
// Perform slashes to gradually whittle down operator magnitude, as well as produce slash escrows.
67-
for (uint16 i = 0; i < slashes; i++) {
68-
// Upper bound is less than WAD to leave some mag for final slash
69-
uint64 wadToSlash = uint64(_randUint(1, WAD - 1));
67+
// Since we're doing multiple slashes, never slash 100%.
68+
for (uint16 i = 0; i < numSlashes; i++) {
69+
uint64 wadToSlash = uint64(cheats.randomUint(1, WAD - 1));
7070
_slash(wadToSlash);
7171
}
7272

73-
// Perform final slash to attempt to extract surplus value, where WAD represents 100% of operator magnitude.
73+
// Perform final 100% slash to extract any remaining tokens.
7474
_slash(WAD);
7575

7676
// Release all escrows to the redistributionRecipient (attacker).
77-
_release(slashes);
77+
_release();
7878

7979
// Check for any surplus value extracted by attacker. If found, we've proven the existence of the exploit.
8080
// Unchecked to avoid overflow reverting. Safe because token balances are bounded by uint64.
@@ -93,33 +93,30 @@ contract Integration_Rounding is IntegrationCheckUtils {
9393
}
9494
}
9595

96-
function test_rounding_partialMagsSlashed(uint16 slashes, uint64 initialWadToSlash, uint64 _initTokenBalance, uint24 r) public rand(r) {
96+
function test_rounding_partialMagsSlashed(
97+
uint64 initialWadToSlash,
98+
uint64 _initTokenBalance
99+
) public rand(0) {
97100
vm.pauseGasMetering();
98-
// Bound slashes to a reasonable range, with at least 1 slash.
99-
// Note: Runs after 2500 hit OOG errors with default gas.
100-
slashes = uint16(bound(slashes, 0, 500));
101-
102-
// We do two slashes, the sum of which slash 1 WAD (all operator magnitude) in total.
103-
// Each slash requires at least 1 mag. As such, we need to bound wadToSlash to 1 <= wadToSlash <= WAD - 1.
101+
// Don't slash 100% as we will do multiple slashes
104102
initialWadToSlash = uint64(bound(initialWadToSlash, 1, WAD - 1));
105-
106-
// Bound initTokenBalance to a reasonable range to avoid overflow, with at least 1 token.
107-
// Using ~18.45 quintillion tokens max (should be enough for any realistic test).
108-
initTokenBalance = uint64(bound(_initTokenBalance, 1, type(uint64).max));
103+
// Ensure attacker has at least one token
104+
initTokenBalance = _initTokenBalance > 0 ? _initTokenBalance : _initTokenBalance + 1;
109105
deal(address(token), address(attacker), initTokenBalance);
110106

111-
_magnitudeManipulation(initialWadToSlash); // Manipulate operator magnitude for a given strategy.
112-
_deposit(initialWadToSlash); // Setup operator with new opSet as well as honest stake in same strategy.
107+
// Use modifyAllocation+slashOperator to arbitrarily set operator max magnitude
108+
_magnitudeManipulation(initialWadToSlash);
109+
_deposit();
113110

114111
// Perform slashes to gradually whittle down operator magnitude, as well as produce slash escrows.
115-
for (uint16 i = 0; i < slashes; i++) {
116-
// Upper bound is less than WAD to leave some mag for final slash
117-
uint64 wadToSlash = uint64(_randUint(1, WAD - 1));
112+
// Since we're doing multiple slashes, never slash 100%.
113+
for (uint16 i = 0; i < numSlashes; i++) {
114+
uint64 wadToSlash = uint64(cheats.randomUint(1, WAD - 1));
118115
_slash(wadToSlash);
119116
}
120117

121118
// Release all escrows to the redistributionRecipient (attacker).
122-
_release(slashes);
119+
_release();
123120

124121
// Withdraw all attacker deposits.
125122
(, uint256[] memory depositShares) = strategyManager.getDeposits(address(attacker));
@@ -182,20 +179,18 @@ contract Integration_Rounding is IntegrationCheckUtils {
182179
_print("deallocate");
183180
}
184181

185-
function _deposit(uint64 wadToSlash) internal {
182+
function _deposit() internal {
186183
// Allocate all remaining magnitude to redistributable opset.
184+
uint64 allocatableMagnitude = allocationManager.getAllocatableMagnitude(address(attacker), strategy);
187185
attacker.modifyAllocations(AllocateParams({
188186
operatorSet: rOpSet,
189187
strategies: strategy.toArray(),
190-
newMagnitudes: (WAD - wadToSlash).toArrayU64()
188+
newMagnitudes: (allocatableMagnitude).toArrayU64()
191189
}));
192190

193191
// Deposit all attacker assets into Eigenlayer.
194192
attacker.depositIntoEigenlayer(strategy.toArray(), token.balanceOf(address(attacker)).toArrayU256());
195193

196-
// Deposit all honest stake into Eigenlayer.
197-
goodStaker.depositIntoEigenlayer(strategy.toArray(), token.balanceOf(address(goodStaker)).toArrayU256());
198-
199194
_print("deposit");
200195
}
201196

@@ -212,19 +207,19 @@ contract Integration_Rounding is IntegrationCheckUtils {
212207
_print("slash");
213208
}
214209

215-
function _release(uint64 slashes) internal {
210+
function _release() internal {
216211
// Roll forward past the escrow delay.
217212
rollForward({blocks: slashEscrowFactory.getGlobalEscrowDelay() + 1});
218213

219214
// Release funds.
220-
for (uint32 i = 1; i <= slashes; i++) {
215+
for (uint32 i = 1; i <= numSlashes; i++) {
221216
vm.prank(address(attacker));
222217
slashEscrowFactory.releaseSlashEscrow(rOpSet, i);
223218
}
224219

225220
// Release final escrow.
226221
vm.prank(address(attacker));
227-
slashEscrowFactory.releaseSlashEscrow(rOpSet, uint256(slashes) + 1);
222+
slashEscrowFactory.releaseSlashEscrow(rOpSet, uint256(numSlashes) + 1);
228223

229224
_print("release");
230225
}
@@ -274,4 +269,4 @@ contract Integration_Rounding is IntegrationCheckUtils {
274269

275270
console.log("\n ===\n".cyan());
276271
}
277-
}
272+
}

0 commit comments

Comments
 (0)