60259 sc low malicious user can bypass maturity period for newly added levels

  • Submitted on: Nov 20th 2025 at 15:41:53 UTC by @danvinci_20

  • Report ID: #60259

  • Report Type: Smart Contract

  • Report severity: Low

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

  • Impacts: Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

Description

Summary

The system allows creation of new staking levels via addLevel(), and each level is expected to require a boost fee to skip maturity before delegation. During the upgrade, initializeV3() sets the boostPricePerBlock values only for pre-existing levels. However, new levels added after the upgrade do not store or initialize any boostPricePerBlock value. Because the boost amount is computed as:

boostAmount = maturityBlocksRemaining * boostPricePerBlock

new levels default to boostPricePerBlock = 0, resulting in boostAmount = 0. As a result, users can stake and instantly delegate without paying the intended VTHO boost fee, effectively bypassing the maturity period entirely.

This breaks the economic model of the system and violates the expected requirement that skipping maturity must incur cost.

Vulnerability Details

Relevant code paths:

During upgrade:

Only provided levelIds receive boost price updates.

Adding new levels:

There is no assignment to set the boostPricePerBlock for the new level, so new levels implicitly use the storage default value of 0.

Because boosting costs 0 for new levels, any user can perform the following sequence and bypass maturity:

1

Stake into a newly added level

User stakes to a level that was added after the upgrade and therefore has boostPricePerBlock = 0.

2

Automatically boost for free

Because boostAmount = maturityBlocksRemaining * boostPricePerBlock and boostPricePerBlock == 0, the computed boosting cost is zero.

3

Instantly delegate

The user delegates immediately, effectively bypassing the intended maturity waiting period without incurring the expected VTHO cost.

Impact

This is a broken system behavior. The core issue is that the logic does not enforce boost price requirements for new levels and there is no functionality to set the boostPricePerBlock in a separate transaction for a specific level at creation time. This allows users to bypass maturity without payment and undermines the protocol staking economics.

Recommendation

Modify addLevel to allow setting the boostPricePerBlock when creating a new level (for example, include a parameter in addLevel or ensure addLevel initializes boostPricePerBlock to a non-zero value, or require an explicit setter callable only by level operators immediately after creation). Ensure upgrade and initialization paths cover future-added levels or add validation preventing zero-priced boosts for levels where maturity/boosting is expected.

Proof of Concept

The reporter provided integration tests demonstrating the issue. Run with: yarn hardhat test --network vechain_solo test/integration/Delegation.test.ts

Two relevant test cases are summarized below.

chevron-right1) Test showing boost is charged for previous levelshashtag

Test excerpt:

Test output shows VTHO balance decreased as expected for old levels:

chevron-right2) Test showing newly added level has boostAmt == 0hashtag

Test excerpt:

Test output shows boost amount is zero for newly added level:


If you want, I can:

  • Propose a small code patch (diff) to initialize boostPricePerBlock in addLevel or add a setter restricted to the appropriate role.

  • Draft unit tests to prevent regression.

Was this helpful?