60586 sc high incorrect double reduction of effective stake in stargate sol

Submitted on Nov 24th 2025 at 08:05:31 UTC by @T0nraq for Audit Comp | Vechain | Stargate Hayabusaarrow-up-right

  • Report ID: #60586

  • Report Type: Smart Contract

  • Report severity: High

  • Target: https://github.com/immunefi-team/audit-comp-vechain-stargate-hayabusa/tree/main/packages/contracts/contracts/Stargate.sol

  • Impacts:

    • Permanent freezing of funds

Description

Description:

When a user requests a delegation exit and subsequently unstakes their NFT after the validator has exited, the contract logic can trigger a double reduction of the validator's effective stake for the same token. This occurs because both requestDelegationExit() and unstake() call _updatePeriodEffectiveStake() to decrease the validator's effective stake, but for overlapping periods and the same token.

Relevant Code Snippets:

requestDelegationExit()

// decrease the effective stake
// Get the latest completed period of the validator
(, , , uint32 completedPeriods) = $.protocolStakerContract.getValidationPeriodDetails(
    delegation.validator
);
// decrease the effective stake
_updatePeriodEffectiveStake($, delegation.validator, _tokenId, completedPeriods + 2, false);

unstake()

_updatePeriodEffectiveStake()

Steps to Reproduce/Attack path:

  1. Stake and delegate an NFT to a validator.

  2. Call requestDelegationExit(tokenId) for the NFT.

  3. Advance the validator to VALIDATOR_STATUS_EXITED.

  4. Call unstake(tokenId) for the same NFT.

  5. Observe that the validator's effective stake is reduced twice for the same token in future periods.

Expected Behavior: The validator's effective stake should only be reduced once per token exit event, regardless of whether the user unstakes after requesting a delegation exit.

Actual Behavior: The effective stake is reduced twice: once during requestDelegationExit() and again during unstake(), resulting in an incorrect accounting of the validator's effective stake.

Impact:

  • Will affect reward calculations.

  • Over-penalizes the validator's effective stake.

  • May lead to inconsistencies in protocol accounting and user expectations.

  • Some users may not be able to exit delegations as it could cause an underflow

Suggested Fix:

  • Track whether the effective stake has already been reduced for a given token/period, and prevent redundant reductions in unstake().

  • Refactor the logic so that only one reduction occurs per exit/unstake lifecycle.

Proof of Concept

Proof of Concept

Add the following unit test to stake.test.ts

Was this helpful?