52464 sc high commission rounding mismatch under payment bug
Submitted on Aug 11th 2025 at 01:06:24 UTC by @BeastBoy for Attackathon | Plume Network
Report ID: #52464
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/lib/PlumeRewardLogic.sol
Impacts: Protocol insolvency
Summary
A rounding mismatch between how validator commission and per-user commission are computed causes a systematic loss (burn) of reward funds. Validator commission uses floor division while user commission uses ceiling division. The mismatch means Σ(user commissions) > validator’s accrued commission, permanently shaving small amounts from the reward pool every settlement.
Description
In updateRewardPerTokenForValidator the validator’s commission is calculated with floor division:
uint256 grossReward = (totalStaked * rewardPerTokenIncrease) / REWARD_PRECISION;
uint256 commissionDeltaForValidator = (grossReward * commissionRateForSegment) / REWARD_PRECISION;
validatorAccruedCommission += commissionDeltaForValidator;This rounds down. In _calculateRewardsCore, each user’s commission is charged with ceiling division:
uint256 grossUser = (userStake * rewardPerTokenDelta) / REWARD_PRECISION;
uint256 commissionForThisSegment = _ceilDiv(grossUser * effectiveCommissionRate, REWARD_PRECISION);
totalCommissionAmountDelta += commissionForThisSegment;Rounding up per-staker but rounding down for the validator’s total introduces a consistent deficit: users collectively pay more commission than the validator receives. No reconciliation logic restores the difference.
Example: two stakers with a 1 Wei reward can cause users to pay 2 Wei of commission while the validator receives 0 Wei — permanently removing 2 Wei from the pool.
Impact
Stakers are systematically under-paid per user per segment, silently draining value from the reward pool. Over time this can lead to significant loss of funds and protocol insolvency.
Recommendation
Proof of Concept
Notes
Do not change any external links or query parameters; the target file link above is preserved as-is.
The core issue is a deterministic arithmetic rounding inconsistency — fixing it requires making rounding symmetric between the aggregated validator calculation and per-user calculations.
Was this helpful?