60210 sc high during a validator exit users will be unable to unstake due to underflow
Submitted on Nov 20th 2025 at 00:08:26 UTC by @oxrex for Audit Comp | Vechain | Stargate Hayabusa
Report ID: #60210
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
Brief / Intro
During a validator EXIT, users will be unable to unstake due to an underflow issue inside the unstake() function.
Vulnerability Details
The unstaking process in the current implementation of Vechain staking is implemented in two main user actions:
User requests delegation exit
A user requests to exit delegation validator X. In
requestDelegationExitthe validator's effective stake for the next period is reduced:
function requestDelegationExit(
uint256 _tokenId
) external whenNotPaused onlyTokenOwner(_tokenId) nonReentrant {
...
// decrease the effective stake
_updatePeriodEffectiveStake($, delegation.validator, _tokenId, completedPeriods + 2, false);
emit DelegationExitRequested(_tokenId, delegation.validator, delegationId, exitBlock);
}If the validator has not been exited before the user calls unstake(), the user receives their VET back as expected.
However, a problematic sequence creates an underflow:
This double deduction creates two failure modes:
If the user is the sole delegator to that validator, the second deduction causes an underflow, permanently locking the user's tokens.
If there are multiple delegators, the second deduction corrupts the validator's effective stake and will cause other delegators' future unstake calls to underflow as well, propagating the issue.
Relevant excerpt from unstake():
The PoC attached with this report demonstrates the bug. The fix is to avoid decreasing effective stake twice for the same delegation/validator (i.e., ensure _updatePeriodEffectiveStake isn't called redundantly when the exit was already processed in requestDelegationExit).
Impact Details
Complete lock of the user's VET tokens (the token.vetAmountStaked associated with the NFT). The only contract function that sends out those VET tokens is unstake(), so this underflow can permanently prevent users from reclaiming funds.
References
https://github.com/immunefi-team/audit-comp-vechain-stargate-hayabusa/blob/main/packages/contracts/contracts/Stargate.sol#L276-L283
Proof of Concept
Was this helpful?