Validators can retroactively apply higher commission rates to historical rewards due to a missing initial commission checkpoint in addValidator(). When users claim rewards that accrued during periods with lower commission rates, the system incorrectly applies the current commission rate to the entire historical period, resulting in permanent theft of user funds.
Vulnerability Details
addValidator() in ValidatorFacet.sol creates initial reward rate checkpoints but fails to create an initial commission checkpoint:
functionaddValidator(...){ validator.commission = commission;// Creates reward checkpoints but NOT commission checkpointfor(uint256 i =0; i < rewardTokens.length; i++){ PlumeRewardLogic.createRewardRateCheckpoint($, token, validatorId, currentGlobalRate);}// MISSING: PlumeRewardLogic.createCommissionRateCheckpoint($, validatorId, commission);}
The function that queries historical commission rates, when it finds no commission checkpoints, falls back to the validator's current commission value:
This allows a validator to set an initial commission (or default) and later increase the commission; because no initial checkpoint exists, all historical reward calculations that probe past timestamps will see the new (higher) commission and apply it retroactively.
Illustrative exploitation scenario
1
Validator created with 0% commission
A validator is added with commission set to 0% but no commission checkpoint is recorded.
2
Users stake and rewards accumulate
Users stake with this validator and rewards accrue over time (under the expectation of 0% commission).
3
Validator increases commission
The validator increases commission to, e.g., 50% — this action creates the first commission checkpoint.
4
Users claim historical rewards but lose funds
When users later claim rewards that accrued during the earlier period, the contract queries historical commission rates but finds no checkpoint for that earlier period and falls back to the current commission (50%). The claim incorrectly takes 50% of past rewards.
Impact Details
Direct loss of user reward funds. Affects all users who staked with validators before their first commission change. The longer the delay between validator creation and the first commission change, the greater the potential theft.
Proof of Concept
Add the following test to PlumeStakingDiamond.t.sol to reproduce:
If you want, I can propose a minimal patch (code snippet) to ensure an initial commission checkpoint is created in addValidator() and adjust getEffectiveCommissionRateAt() fallback behavior to avoid using the current commission for past timestamps.