50392 sc insight phantom commission burn

Submitted on Jul 24th 2025 at 07:58:33 UTC by @BeastBoy for Attackathon | Plume Network

  • Report ID: #50392

  • Report Type: Smart Contract

  • Report severity: Insight

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

  • Impacts:

    • Protocol insolvency

Description

Within _calculateRewardsCore each segment’s user commission is computed using ceiling division:

uint256 commissionForThisSegment =
    _ceilDiv(grossRewardForSegment * effectiveCommissionRate, REWARD_PRECISION);

This rounds any fractional dust up, deducting

ceil(X / P) – floor(X / P) ≥ 1

from the user. However, in updateRewardPerTokenForValidator the validator’s commission is credited using plain floor division:

uint256 commissionDeltaForValidator =
    (grossRewardForValidatorThisSegment * commissionRateForSegment) / REWARD_PRECISION;

The extra “1‑unit” dust never appears in validatorAccruedCommission or totalClaimableByToken, nor is totalCommissionAmountDelta ever written back to storage. As a result, every segment silently “burns” the rounding difference.

Impact

Users collectively lose a non‑negligible amount of tokens over time as these rounding deltas are irretrievably removed from the system.

Recommendation

Unify the rounding mode by replacing the ceiling division in _calculateRewardsCore with floor division to match the validator side, ensuring no dust is charged beyond what the validator receives.

Proof of Concept

Mathematical proof & realistic demonstration (expand to view)

Mathematical rounding proof (pseudo test)

Real-world scenario demonstration

Was this helpful?