53072 sc high ceil vs floor rounding mismatch causes systematic underpayment and unclaimed yield leakage
Submitted on Aug 14th 2025 at 18:52:35 UTC by @r1ver for Attackathon | Plume Network
Report ID: #53072
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/lib/PlumeRewardLogic.sol
Impacts: Theft of unclaimed yield
Description
Brief / Intro
In plume/src/lib/PlumeRewardLogic.sol, per-user commission uses ceiling division while validator commission accrues with floor division, so user deductions can exceed validator accrual; the excess isn’t credited to anyone, causing systematic underpayment and unclaimed-yield leakage.
Vulnerability Details
In plume/src/lib/PlumeRewardLogic.sol, updateRewardPerTokenForValidator calculates validator commission accrual using floor division:
// Use regular division (floor) for validator's accrued commission
uint256 commissionDeltaForValidator = (
grossRewardForValidatorThisSegment * commissionRateForSegment
) / PlumeStakingStorage.REWARD_PRECISION;But per-user commission deduction in _calculateRewardsCore uses ceiling division:
Because Solidity lacks decimals and any non-integer division rounds, applying ceil per user per time-segment makes the sum of user-side commissions often exceed the validator’s floor-accrued commission. The difference is neither credited to validators nor returned to users, creating unclaimed-yield leakage and systematic underpayment that grows with more users, more segments, and more rate changes.
Impact Details
Users are systematically underpaid because per-user ceil commission can exceed validator floor-accrued commission, and the excess is not credited to anyone, causing accumulating unclaimed-yield leakage and breaking the accounting invariant (user_net + validator_commission < gross), which undermines auditability.
Proof of Concept
A test demonstrating the mismatch:
Run it with: forge test RoundingMismatchPOC -vvv
References
https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/lib/PlumeRewardLogic.sol#L184-L187
https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/lib/PlumeRewardLogic.sol#L346-L355
Notes / Remediation Suggestions (observational)
Was this helpful?