For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

1

Deploy the protocol and add a validator

  • Deploy the staking protocol contracts.

  • Add a validator (Validator1) to the system.

2

Add multiple tokens as reward tokens and accrue commission

  • Set TokenA and TokenB as reward tokens (isRewardToken[TokenA] = true, isRewardToken[TokenB] = true).

  • Users stake and generate rewards, causing Validator1 to accrue commission in both TokenA and TokenB.

3

Remove TokenA from the reward token list

  • Call the function to remove TokenA as a reward token (isRewardToken[TokenA] = false).

  • TokenB remains an active reward token.

4

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.

5

Result

  • Validator1 can only claim commission for tokens that are still active reward tokens.

  • Any commission accrued in TokenA before its removal is lost and cannot be claimed, while commission for TokenB (still active) can be claimed as expected.

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?