diff --git a/packages/horizon/contracts/staking/HorizonStakingExtension.sol b/packages/horizon/contracts/staking/HorizonStakingExtension.sol index ac9dc6bc8..3b42ebf1a 100644 --- a/packages/horizon/contracts/staking/HorizonStakingExtension.sol +++ b/packages/horizon/contracts/staking/HorizonStakingExtension.sol @@ -286,9 +286,8 @@ contract HorizonStakingExtension is HorizonStakingBase, IHorizonStakingExtension // Slashing more tokens than freely available (over allocation condition) // Unlock locked tokens to avoid the indexer to withdraw them - uint256 tokensAvailable = indexerStake.tokensStaked - - indexerStake.__DEPRECATED_tokensAllocated - - indexerStake.__DEPRECATED_tokensLocked; + uint256 tokensUsed = indexerStake.__DEPRECATED_tokensAllocated + indexerStake.__DEPRECATED_tokensLocked; + uint256 tokensAvailable = tokensUsed > indexerStake.tokensStaked ? 0 : indexerStake.tokensStaked - tokensUsed; if (tokens > tokensAvailable && indexerStake.__DEPRECATED_tokensLocked > 0) { uint256 tokensOverAllocated = tokens - tokensAvailable; uint256 tokensToUnlock = MathUtils.min(tokensOverAllocated, indexerStake.__DEPRECATED_tokensLocked); diff --git a/packages/horizon/test/staking/slash/legacySlash.t.sol b/packages/horizon/test/staking/slash/legacySlash.t.sol index 760978aae..f5595fdac 100644 --- a/packages/horizon/test/staking/slash/legacySlash.t.sol +++ b/packages/horizon/test/staking/slash/legacySlash.t.sol @@ -180,4 +180,29 @@ contract HorizonStakingLegacySlashTest is HorizonStakingTest { vm.expectRevert("!beneficiary"); staking.legacySlash(users.indexer, slashTokens, reward, address(0)); } + + function test_LegacySlash_WhenTokensAllocatedGreaterThanStake() + public + useIndexer + useLegacySlasher(users.legacySlasher) + { + // Setup indexer with: + // - tokensStaked = 1000 GRT + // - tokensAllocated = 800 GRT + // - tokensLocked = 300 GRT + // This means tokensUsed (1100 GRT) > tokensStaked (1000 GRT) + _setIndexer( + users.indexer, + 1000 ether, // tokensStaked + 800 ether, // tokensAllocated + 300 ether, // tokensLocked + 0 // tokensLockedUntil + ); + + // Send tokens manually to staking + token.transfer(address(staking), 1100 ether); + + resetPrank(users.legacySlasher); + _legacySlash(users.indexer, 1000 ether, 500 ether, makeAddr("fisherman")); + } }