50082 sc low protocol lets validators operate with dust amounts making attacks risk free

Submitted on Jul 21st 2025 at 15:10:02 UTC by @holydevoti0n for Attackathon | Plume Network

  • Report ID: #50082

  • Report Type: Smart Contract

  • Report severity: Low

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

  • Impacts:

    • Permanent freezing of funds

    • Protocol insolvency

Description

Brief/Intro

The _unstake function doesn't check if the remaining stake amount is below the minimum stake amount, allowing validators to operate actively while having a dust amount of funds staked (i.e., 1 wei).

Vulnerability Details

The protocol does not enforce the minimum stake amount when a user partially unstakes. It allows stakers/validators to remain with stake amounts below minStakeAmount.

Vulnerable snippet:

https://github.com/immunefi-team/attackathon-plume-network/blob/580cc6d61b08a728bd98f11b9a2140b84f41c802/plume/src/facets/StakingFacet.sol#L366-L390

With the current logic, validators can operate with dust amounts, increasing the likelihood of validators acting maliciously. The invariant that every active validator holds at least the minimum stake amount is broken.

Examples of consequences:

  • Two malicious validators could skip voting in the slashing process to avoid each other being slashed.

  • Admin deactivates the two validators above; new/existing validators can repeat the same behavior when their stake/funds are dust/below the minimum stake amount.

  • Malicious validators acting together can vote to slash legitimate validators, reducing their funds to zero.

Impact

The protocol permits partial unstaking that drops validators below minimum stake requirements, enabling validators to act maliciously with minimal financial risk.

Recommendation

Enforce the minimum stake amount when a user partially unstakes. Suggested patch:

Add a custom error (e.g., StakeAmountTooSmall) if not already present, and ensure the check is consistent with any edge-cases (e.g., full unstake vs partial unstake).

Proof of Concept

Add the PoC below into PlumeStakingDiamond.t.sol:

Run:

Output:

Was this helpful?