Assessment reports>PDT Staking V2>Medium findings>PDT can be set as a reward token and withdrawn by admin
Category: Protocol Risks

PDT can be set as a reward token and withdrawn by admin

Medium Severity
Medium Impact
Medium Likelihood

Description

The function registerNewRewardToken allows an admin address with the role TOKEN_MANAGER to call it.

function registerNewRewardToken(address newRewardToken) external onlyRole(TOKEN_MANAGER) {
    require(newRewardToken != address(0), "Invalid reward token");

    uint256 numOfRewardTokens = rewardTokenList.length;

    for (uint256 itTokenIndex = 0; itTokenIndex < numOfRewardTokens; ) {
        if (rewardTokenList[itTokenIndex] == newRewardToken) {
            revert DuplicatedRewardToken(newRewardToken);
        }

        unchecked {
            ++itTokenIndex;
        }
    }

    // If newRewardToken is not found in rewardTokenList, then add it
    rewardTokenList.push(newRewardToken);

    emit RegisterNewRewardToken(currentEpochId, newRewardToken);
}

The registerNewRewardToken function currently lacks a check to prevent the staked PDT token from being registered as a reward token.

Impact

Reward tokens owned by the StakedPDT contract can be withdrawn by the admin using withdrawRewardTokens. This leads to a centralization risk as it allows a compromised admin account to withdraw PDT tokens staked by the users.

Recommendations

Add the following check to registerNewRewardToken.

function registerNewRewardToken(address newRewardToken) external onlyRole(TOKEN_MANAGER) {
    require(newRewardToken != pdt, "Invalid reward token");

Remediation

This issue has been acknowledged by Paragons DAO, and a fix was implemented in commit afcf3d16.

Zellic © 2025Back to top ↑