60466 sc medium maxclaimableperiodsexceeded lock zero reward backlog permanently locks nfts

Submitted on Nov 23rd 2025 at 01:02:20 UTC by @arunabha003 for Audit Comp | Vechain | Stargate Hayabusaarrow-up-right

  • Report ID: #60466

  • Report Type: Smart Contract

  • Report severity: Medium

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

  • Impacts:

    • Permanent freezing of funds

Description

Brief

The Stargate contract contains a logic flaw in _claimRewards() that permanently locks NFTs when validators produce many periods with zero rewards. The function returns early at line 759 when claimableAmount == 0 without updating lastClaimedPeriod, preventing the period backlog from being reduced. When the number of claimable periods exceeds maxClaimablePeriods (default 832), the guard check in unstake() and delegate() reverts with MaxClaimablePeriodsExceeded, making it impossible to unstake or redelegate the NFT and access the staked VET. As a result, the user cannot unstake and retrieve their staked VET, which constitutes permanent freezing of funds.

Vulnerability Details

The vulnerability exists in the reward claiming and period tracking logic across multiple functions in Stargate.sol:

Location 1: _claimRewards() - Lines 757-760

function _claimRewards(StargateStorage storage $, uint256 _tokenId) private {
    (uint32 firstClaimablePeriod, uint32 lastClaimablePeriod) = _claimableDelegationPeriods($, _tokenId);
    // ... max period check ...
    uint256 claimableAmount = _claimableRewards($, _tokenId, 0);
    
    if (claimableAmount == 0) {
        return;  // Early return without updating lastClaimedPeriod
    }
    
    $.lastClaimedPeriod[_tokenId] = lastClaimablePeriod;  // Only reached when claimableAmount > 0
    // ... transfer and emit ...
}

Location 2: _exceedsMaxClaimablePeriods() - Lines 956-973

Location 3: unstake() - Lines 299-302

Location 4: _delegate() - Lines 431-435

Exploit Path:

  1. User delegates NFT to validator

  2. Validator completes many periods (> maxClaimablePeriods) without producing rewards

    • Validator is offline or inactive

    • Testnet/devnet without reward distribution configured

    • Validator misconfiguration

  3. User calls claimRewards(tokenId)

    • _claimableRewards() returns 0

    • _claimRewards() returns early at line 759

    • lastClaimedPeriod[tokenId] not updated

  4. Period backlog continues growing: lastClaimablePeriod - firstClaimablePeriod > maxClaimablePeriods

  5. User calls unstake(tokenId)

    • _exceedsMaxClaimablePeriods() returns true

    • Transaction reverts with MaxClaimablePeriodsExceeded

  6. User attempts to redelegate via delegate(tokenId, newValidator)

    • _exceedsMaxClaimablePeriods() returns true

    • Transaction reverts with MaxClaimablePeriodsExceeded

  7. NFT permanently locked with no recovery mechanism

Time makes the problem worse: each new period increases the backlog, and calling claimRewards() has no effect since it continues returning early without updating lastClaimedPeriod.

Impact Details

Users whose delegated validators go inactive for extended periods lose permanent access to their staked VET. The NFT becomes permanently locked once the period backlog exceeds maxClaimablePeriods. No admin function exists to force-unstake, manually update lastClaimedPeriod, or bypass the guard check. No time-based unlock exists. The funds remain locked indefinitely.

This scenario is realistic in several contexts:

  • Validators going offline during network issues or maintenance

  • Testnet/devnet deployments where reward distribution is not configured

  • Early mainnet deployment before reward mechanisms are fully operational

  • Validator misconfigurations that prevent reward distribution

Financial impact scales with the number of affected delegators and their stake amounts. VeChain Stargate NFT levels range from 600,000 VET (Level 1) to 25,000,000 VET (Level 7). If multiple validators become inactive, hundreds or thousands of delegators could be affected, with total locked value potentially reaching hundreds of millions of VET.

This constitutes permanent freezing of funds per Immunefi's Critical impact definition: "user is no longer able to withdraw their funds" with no recovery mechanism.

Proof of Concept

Proof of Concept

Test File: packages/contracts/test/integration/MaxClaimablePeriodsLockPOC.test.ts

Running the POC

Actual Test Output

Complete POC Code

File: packages/contracts/test/integration/MaxClaimablePeriodsLockPOC.test.ts

Was this helpful?