52944 sc high the requestcommisionclaim function can only claim commission on tokens that are currently reward tokens
Submitted on: Aug 14th 2025 at 12:48:09 UTC by @frolic for Attackathon | Plume Network
Report ID: #52944
Report Type: Smart Contract
Report severity: High
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/ValidatorFacet.sol
Impacts: Permanent freezing of funds
Description
Brief / Intro
In the ValidatorFacet contract, the requestCommissionClaim function only allows validators to claim commission on tokens that are currently configured as reward tokens. If a token is removed from the reward token list, any unclaimed commission for that token becomes permanently inaccessible to the validator. This results in a direct loss of earned commission for validators whenever a reward token is removed.
Vulnerability Details
The requestCommissionClaim function includes a check that requires the token to be an active reward token before a commission claim can be made:
function requestCommissionClaim(
uint16 validatorId,
address token
)
external
onlyValidatorAdmin(validatorId)
nonReentrant
_validateValidatorExists(validatorId)
_validateIsToken(token) // <-- Only allows currently active reward tokens
{
...
}The _validateIsToken(token) modifier enforces that the token must still be present in the isRewardToken mapping. If a token is removed from the reward token list, this check fails, and the validator cannot claim any accrued commission for that token. As a result, any commission earned but not yet claimed for removed tokens is lost, and there is no mechanism for recovery.
Impact Details
Validators lose access to their accrued commission for any token that is removed from the reward token list.
This can result in significant financial loss for validators, especially if tokens are removed unexpectedly or without warning.
There is no workaround for affected validators except for a contract upgrade or manual intervention.
Proof of Concept
Validator attempts to claim commission for both tokens
Validator1 calls
requestCommissionClaim(validatorId, TokenA).The call reverts due to the
_validateIsToken(token)check, since TokenA is no longer a reward token.The accrued commission for TokenA is now permanently inaccessible.
Validator1 calls
requestCommissionClaim(validatorId, TokenB).The call succeeds, and Validator1 receives the accrued commission for TokenB.
References
ValidatorFacet.sol - requestCommissionClaim function https://github.com/plumenetwork/contracts/blob/fe67a98fa4344520c5ff2ac9293f5d9601963983/plume/src/facets/ValidatorFacet.sol#L500
PlumeStakingStorage.layout().isRewardToken mapping https://github.com/plumenetwork/contracts/blob/fe67a98fa4344520c5ff2ac9293f5d9601963983/plume/src/lib/PlumeStakingStorage.sol#L64
Was this helpful?