59563 sc high exited delegators can claim rewards indefinitely after exit

Submitted on Nov 13th 2025 at 15:11:46 UTC by @dray for Audit Comp | Vechain | Stargate Hayabusaarrow-up-right

  • Report ID: #59563

  • 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: Theft of unclaimed yield

Description

Brief/Intro

A critical flaw in Stargate._claimableDelegationPeriods allows users who have exited their delegations to continue claiming rewards indefinitely from periods that occur after their exit. Once a delegator calls requestDelegationExit and completes their exit period, they should no longer earn rewards. However, the contract's logic incorrectly computes the claimable period range for exited delegations, enabling them to claim from all future periods as long as their validator continues producing blocks. Each call to claimRewards siphons VTHO that should have been distributed exclusively to active delegators, creating a permanent reward drain.

Vulnerability Details

Background

Expected lifecycle:

1

Stake and delegate

User stakes VET → mints NFT.

2

Delegate

User delegates the NFT → VET locked in ProtocolStaker; rewards accrue period by period.

3

Request exit

User requests delegation exit → ProtocolStaker sets endPeriod for the delegation.

4

Exit completes

When the period completes, the delegation status becomes EXITED.

5

No new rewards expected

From this point, no new rewards should accrue; user can withdraw stake or leave the NFT idle.

Actual behavior

Because of how Stargate._claimableDelegationPeriods computes the next claim window, an EXITED delegation retains a moving claim range that advances with every new validator period. The contract continues to treat the exited delegator as eligible for rewards, so repeated calls to claimRewards siphon future earnings forever.

Root Cause

The bug lives in _claimableDelegationPeriods (lines ~880–927 of Stargate.sol). Relevant excerpt:

When the delegator first claims after exit:

  • nextClaimablePeriod equals the first unclaimed period (still ≤ endPeriod).

  • The endPeriod > nextClaimablePeriod branch executes, returning [nextClaimable, endPeriod].

  • claimRewards sets lastClaimedPeriod to endPeriod.

On the next call:

  • nextClaimablePeriod = endPeriod + 1.

  • The exit branch condition endPeriod > nextClaimablePeriod fails.

  • The fallback branch sees nextClaimablePeriod < currentValidatorPeriod (validator kept producing blocks).

  • It therefore returns (endPeriod + 1, completedPeriods) – periods entirely beyond endPeriod.

Since _claimableRewardsForPeriod and delegatorsEffectiveStake[validator] still reflect the old stake (no checkpoint subtraction until unstake or redelegation), the exited delegator receives a legitimate share of each future period’s rewards.

Why exit does not stop the leakage

  • _updatePeriodEffectiveStake(..., false) runs only when the delegator withdraws or redelegates; simply exiting does not reduce the validator’s effective stake history.

  • lastClaimedPeriod is updated after every claim but no flag signals that the delegation ended permanently.

  • The endPeriod > nextClaimablePeriod guard uses a strict inequality. After successfully claiming through the end period, the guard no longer triggers and the fallback logic treats the exited delegator as active.

Impact Details

Direct impact

  • Exited delegators can keep farming VTHO rewards indefinitely without restaking.

  • Honest active delegators see reduced rewards each period, proportional to the attacker’s historical effective stake.

Proof of Concept

chevron-rightView PoC test (Hardhat / TypeScript)hashtag

References

(Links to code or documentation can be added here if available.)

Was this helpful?