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

51966 sc low totalamountclaimable reverts instead of returning the claimable reward for historical tokens

Submitted on Aug 6th 2025 at 21:32:59 UTC by @holydevoti0n for Attackathon | Plume Network

  • Report ID: #51966

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/plume/src/facets/StakingFacet.sol

  • Impacts:

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

The totalAmountClaimable() function reverts when called for historical reward tokens, even if users still have claimable balances.

Vulnerability Details

The function StakingFacet.totalAmountClaimable checks for $.isRewardToken:

    /**
     * @notice Get the total amount of a specific token claimable across all users.
     * @param token Address of the token to check.
     * @return amount Total amount of the token claimable.
     */
    function totalAmountClaimable(
        address token
    ) external view returns (uint256 amount) {
        PlumeStakingStorage.Layout storage $ = PlumeStakingStorage.layout();
            
             // @audit - revert when token is historical reward token
@>        require($.isRewardToken[token], "Token is not a reward token");
        // Return the total claimable amount
        return $.totalClaimableByToken[token];
    }

But historical reward tokens were once reward tokens that accrued rewards; they may also have amounts to be claimable.

Impact Details

It is not possible to see the amount claimable of a specific token across all users when the token to be consulted is a historical reward token.

Check against isHistoricalRewardToken instead of the current isRewardToken mapping to allow access to all tokens that have ever been valid rewards.

Proposed diff:

Proof of Concept

Context

  • An active reward token accrues rewards over time. Several users can claim their rewards.

  • Admin removes the reward token, but it remains active as a historical reward token, so users can claim it.

1

Reproduce - step

User calls totalAmountClaimable passing the recently removed token as a parameter, expecting to see the total amount to be claimed by all users.

2

Reproduce - step

totalAmountClaimable reverts as it checks for isRewardToken instead of isHistoricalRewardToken.

Result: The function works partially, but reverts when tokens are historical reward tokens.

Was this helpful?