For the complete documentation index, see llms.txt. This page is also available as Markdown.

51519 sc low unstake does not validate users remaing stake

Submitted on Aug 3rd 2025 at 16:53:12 UTC by @funkornaut for Attackathon | Plume Network

  • Report ID: #51519

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/StakingFacet.sol

Description

Brief / Intro

Stakers can end up with a staked balance that is less than minStakeAmount after calling unstake.

Vulnerability Details

Staking requires users to stake at least a minStakeAmount. Users can unstake a specific amount via:

function unstake(uint16 validatorId, uint256 amount)

Within the internal _unstake(uint16 validatorId, uint256 amount) implementation there is no validation ensuring the staker's remaining stake is at least minStakeAmount. As a result, a user who originally met the minimum can partially unstake and remain with a balance below the minimum.

Impact Details

  • Possible reward calculation truncation: The reward computation multiplies the (now tiny) user stake with a per-token reward delta and divides by a precision constant:

    uint256 grossRewardForSegment =
        (userStakedAmount * rewardPerTokenDeltaForUserInSegment) / PlumeStakingStorage.REWARD_PRECISION;

    For extremely small userStakedAmount values, the multiplication may be smaller than REWARD_PRECISION, causing truncation to 0 and permanent loss of accumulated rewards.

  • State inconsistency and future protocol risks:

    • Validator relationship tracking: Users with tiny stakes remain in validator staker lists indefinitely.

    • Economic model violation: minStakeAmount exists to ensure meaningful participation; leaving sub-minimum stakes undermines intended reward behavior.

    • Potential DoS vector: Attackers could create many tiny stakes across validators. While current code may not iterate these arrays in harmful ways, future changes that iterate them could be vulnerable to gas-limit attacks.

References

  • https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/StakingFacet.sol?utm_source=immunefi#L366-L390

  • https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/lib/PlumeRewardLogic.sol#L339-#L341

Proof of Concept

1

Step

User stakes 1 ETH (meets minStakeAmount).

2

Step

User unstakes 0.999999... ETH, leaving 1 wei staked:

3

Step

Result:

  • User now has 1 wei staked (below minStakeAmount).

  • Reward calculations can truncate to 0.

  • User remains in the validator's staker list indefinitely.

Was this helpful?