50409 sc high validator will lose comission
Submitted on Jul 24th 2025 at 10:46:43 UTC by @shadowHunter for Attackathon | Plume Network
Report ID: #50409
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/ValidatorFacet.sol
Impacts:
Theft of unclaimed yield
Description
Brief/Intro
It seems that currently the contract does not provide any way for a Validator to claim commission on removed tokens (historical). This will cause a genuine Validator to lose commissions.
On removing a token, the contract correctly calls updateRewardPerTokenForValidator to calculate commission till now but fails to provide a way to claim this.
Vulnerability Details
See Proof of Concept section.
Impact Details
Validator will lose commission.
Recommendation
Instead of using _validateIsToken(token) in requestCommissionClaim, check that token is not part of both historical and current reward tokens before rejecting.
Proof of Concept
Step
This calls updateRewardPerTokenForValidator to ensure commission till now is settled:
for (uint256 i = 0; i < $.validatorIds.length; i++) {
uint16 validatorId = $.validatorIds[i];
// Final update to current time to settle all rewards up to this point
PlumeRewardLogic.updateRewardPerTokenForValidator($, token, validatorId);
// Create a final checkpoint with a rate of 0 to stop further accrual definitively.
PlumeRewardLogic.createRewardRateCheckpoint($, token, validatorId, 0);
}Step
The implementation calculates and accumulates the validator commission:
uint256 commissionDeltaForValidator = (
grossRewardForValidatorThisSegment * commissionRateForSegment
) / PlumeStakingStorage.REWARD_PRECISION;
if (commissionDeltaForValidator > 0) {
$.validatorAccruedCommission[validatorId][token] += commissionDeltaForValidator;
}Step
Post removal of T1, V1 wants to claim the commission using requestCommissionClaim which calls _validateIsToken(token):
function requestCommissionClaim(
uint16 validatorId,
address token
)
external
onlyValidatorAdmin(validatorId)
nonReentrant
_validateValidatorExists(validatorId)
_validateIsToken(token)
{
...
}Was this helpful?