sherlock-audit / 2024-07-kwenta-staking-contracts-judging

4 stars 4 forks source link

0xShax2nk.in - Inaccurate scaling factor is used for Reward calculations for USDC Tokens in StakingRewardsV2 #144

Closed sherlock-admin4 closed 3 months ago

sherlock-admin4 commented 3 months ago

0xShax2nk.in

High

Inaccurate scaling factor is used for Reward calculations for USDC Tokens in StakingRewardsV2

Summary

The StakingRewardsV2 contract manages staking and rewards for KWENTA and USDC tokens. However, the contract currently uses a scaling factor of 1e18 for both KWENTA and USDC in reward calculations. Since KWENTA has 18 decimals and USDC has 6 decimals, this mismatch leads to incorrect reward calculations for USDC tokens.

Vulnerability Detail

he StakingRewardsV2 contract currently uses a scaling factor of 1e18 for both KWENTA and USDC in reward calculations, which is incorrect for USDC due to its 6 decimal places. This mismatch leads to incorrect reward calculations for USDC, causing inflated or deflated reward amounts.

Impact

Code Snippet

https://github.com/sherlock-audit/2024-07-kwenta-staking-contracts/blob/0527fb7425206a3338c23177416436c6286cedf9/token/contracts/StakingRewardsV2.sol#L447

function rewardPerTokenUSDC() public view returns (uint256) {
    uint256 allTokensStaked = totalSupply();

    if (allTokensStaked == 0) {
        return rewardPerTokenStoredUSDC;
    }

    return rewardPerTokenStoredUSDC
        + (((lastTimeRewardApplicable() - lastUpdateTime) * rewardRateUSDC * 1e18) / allTokensStaked);
}

https://github.com/sherlock-audit/2024-07-kwenta-staking-contracts/blob/0527fb7425206a3338c23177416436c6286cedf9/token/contracts/StakingRewardsV2.sol#L472

function earnedUSDC(address _account) public view returns (uint256) {
    uint256 totalBalance = balanceOf(_account);

    return ((totalBalance * (rewardPerTokenUSDC() - userRewardPerTokenPaidUSDC[_account])) / 1e18)
        + rewardsUSDC[_account];
}

Tool used

Manual Review

Recommendation

Use 1e6 as scaling factor for the USDC tokens (6 decimals).

function rewardPerTokenUSDC() public view returns (uint256) {
    uint256 allTokensStaked = totalSupply();

    if (allTokensStaked == 0) {
        return rewardPerTokenStoredUSDC;
    }

--    return rewardPerTokenStoredUSDC
--        + (((lastTimeRewardApplicable() - lastUpdateTime) * rewardRateUSDC * 1e18) / allTokensStaked);
++   return rewardPerTokenStoredUSDC
++        + (((lastTimeRewardApplicable() - lastUpdateTime) * rewardRateUSDC * 1e18) / allTokensStaked);

}
function earnedUSDC(address _account) public view returns (uint256) {
    uint256 totalBalance = balanceOf(_account);

--   return ((totalBalance * (rewardPerTokenUSDC() - userRewardPerTokenPaidUSDC[_account])) / 1e18)
--        + rewardsUSDC[_account];
++     return ((totalBalance * (rewardPerTokenUSDC() - userRewardPerTokenPaidUSDC[_account])) / 1e18)
++        + rewardsUSDC[_account];
}