60019 sc high off by one in stargate sol claimabledelegationperiods lets exited nfts siphon validator rewards leading to protocol insolvency
Submitted on Nov 17th 2025 at 15:40:21 UTC by @ElouJoe for Audit Comp | Vechain | Stargate Hayabusa
Report ID: #60019
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:
Protocol insolvency
Theft of unclaimed yield
Description
Brief/Intro
An off-by-one in Stargate.sol’s _claimableDelegationPeriods allows an exited NFT to keep claiming future validator rewards after its delegation ended, diverting other delegators’ VTHO and ultimately draining the reward pool to insolvency.
Vulnerability Details
When an exit is requested, endPeriod is set. After the user claims through the true endPeriod, lastClaimedPeriod = endPeriod, so nextClaimablePeriod becomes endPeriod + 1 and the check endPeriod > nextClaimablePeriod fails. The code falls back to (nextClaimablePeriod, completedPeriods) and treats the NFT as still active. This lets post-exit periods be claimed indefinitely.
Affected code: _claimableDelegationPeriods in packages/contracts/contracts/Stargate.sol.
Impact Details
Theft of other delegators’ unclaimed yield each completed period (misrouted to the exited NFT).
Persistent drain escalates to Critical: Protocol insolvency as the reward stream is continuously siphoned.
References
Source: https://github.com/immunefi-team/audit-comp-vechain-stargate-hayabusa/tree/main/packages/contracts/contracts/Stargate.sol
In-repo PoC: packages/contracts/test/unit/Stargate/DelegationBugGhostRewards.test.ts Run: yarn hardhat test --network hardhat test/unit/Stargate/DelegationBugGhostRewards.test.ts
Link to Proof of Concept
https://gist.github.com/eloufirjawad/283c7077fdccd6eee3953ff4125a5be6
Proof of Concept
What proves the bug
After claiming through
endPeriod,claimableRewardsremains positive for each new completed period andclaimRewardscontinues paying the exited NFT.Root cause: once
lastClaimedPeriod == endPeriod,nextClaimablePeriod = endPeriod + 1, makingendPeriod > nextClaimablePeriodfalse;_claimableDelegationPeriodsfalls back to(nextClaimablePeriod, completedPeriods), treating the NFT as still active and enabling post‑exit claims.
How to run the in-repo PoC
One-liner (copy/paste):
Two-step:
If you want, I can:
Extract the exact vulnerable code snippet from the referenced repository and include a minimal annotated excerpt,
Suggest a minimal patch (preserving original semantics) to fix the off-by-one logic.
Was this helpful?