60192 sc high users can claim delegation rewards after exit endperiod has passed

Submitted on Nov 19th 2025 at 18:41:47 UTC by @Rhaydden for Audit Comp | Vechain | Stargate Hayabusaarrow-up-right

  • Report ID: #60192

  • 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

A logic gap in Stargate’s reward claim window computation allows a token to claim delegation rewards for periods after its delegation has ended.

In Stargate.sol::_claimableDelegationPeriods, the delegation ended branch only triggers when endPeriod > nextClaimablePeriod. If nextClaimablePeriod >= endPeriod, the code falls through to the active/past branch and returns the current completed periods, effectively green-lighting claims for periods strictly after endPeriod.

Stargate.solarrow-up-right:

// Lines ~916-930
if (
    endPeriod != type(uint32).max &&
    endPeriod < currentValidatorPeriod &&
    endPeriod > nextClaimablePeriod
) {
    return (nextClaimablePeriod, endPeriod);
}

// check that the start period is before the current validator period
if (nextClaimablePeriod < currentValidatorPeriod) {
    return (nextClaimablePeriod, completedPeriods);
}

When nextClaimablePeriod == endPeriod: this should clamp to endPeriod, but if the user had already claimed through endPeriod, nextClaimablePeriod becomes endPeriod + 1 and the function returns a range that includes periods after endPeriod.

When nextClaimablePeriod > endPeriod (exhausted): the function still falls through and returns (nextClaimablePeriod, completedPeriods).

Finding description and impact

Exited delegators can claim rewards for a period in which they were no longer delegated. This is a direct transfer of unclaimed yield from active delegators to an ex-delegator.

High - Theft of unclaimed yield

Consider a scenario where:

  • User delegates at period 1 and requests exit at period 3 (endPeriod = 3).

  • User claims up to period 3 (so lastClaimedPeriod = 3).

  • Later, validator advances to period 5.

  • The function returns (4, 4) as claimable periods for the user, allowing a claim for period 4 even though the delegation ended at period 3.

triangle-exclamation

Clamp strictly when the delegation has ended, and guard the exhausted case:

Proof of concept

Created a test file packages/contracts/test/unit/Stargate/PostExitClaimPoC.test.ts demonstrating a token claiming rewards for a period after its delegation ended.

TypeScript/Hardhat test used as PoC:

Run command used:

VITE_APP_ENV=local yarn workspace @repo/contracts hardhat test --network hardhat test/unit/Stargate/PostExitClaimPoC.test.ts

chevron-rightLogshashtag

Was this helpful?