Skip to content

Commit d6d376c

Browse files
committed
fix: legacy slashing underflow (TRST-H08)
1 parent 6e00d17 commit d6d376c

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

packages/horizon/contracts/staking/HorizonStakingExtension.sol

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension
286286

287287
// Slashing more tokens than freely available (over allocation condition)
288288
// Unlock locked tokens to avoid the indexer to withdraw them
289-
uint256 tokensAvailable = indexerStake.tokensStaked -
290-
indexerStake.__DEPRECATED_tokensAllocated -
291-
indexerStake.__DEPRECATED_tokensLocked;
289+
uint256 tokensUsed = indexerStake.__DEPRECATED_tokensAllocated + indexerStake.__DEPRECATED_tokensLocked;
290+
uint256 tokensAvailable = tokensUsed > indexerStake.tokensStaked ? 0 : indexerStake.tokensStaked - tokensUsed;
292291
if (tokens > tokensAvailable && indexerStake.__DEPRECATED_tokensLocked > 0) {
293292
uint256 tokensOverAllocated = tokens - tokensAvailable;
294293
uint256 tokensToUnlock = MathUtils.min(tokensOverAllocated, indexerStake.__DEPRECATED_tokensLocked);

packages/horizon/test/staking/slash/legacySlash.t.sol

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,29 @@ contract HorizonStakingLegacySlashTest is HorizonStakingTest {
180180
vm.expectRevert("!beneficiary");
181181
staking.legacySlash(users.indexer, slashTokens, reward, address(0));
182182
}
183+
184+
function test_LegacySlash_WhenTokensAllocatedGreaterThanStake()
185+
public
186+
useIndexer
187+
useLegacySlasher(users.legacySlasher)
188+
{
189+
// Setup indexer with:
190+
// - tokensStaked = 1000 GRT
191+
// - tokensAllocated = 800 GRT
192+
// - tokensLocked = 300 GRT
193+
// This means tokensUsed (1100 GRT) > tokensStaked (1000 GRT)
194+
_setIndexer(
195+
users.indexer,
196+
1000 ether, // tokensStaked
197+
800 ether, // tokensAllocated
198+
300 ether, // tokensLocked
199+
0 // tokensLockedUntil
200+
);
201+
202+
// Send tokens manually to staking
203+
token.transfer(address(staking), 1100 ether);
204+
205+
resetPrank(users.legacySlasher);
206+
_legacySlash(users.indexer, 1000 ether, 500 ether, makeAddr("fisherman"));
207+
}
183208
}

0 commit comments

Comments
 (0)