Staking reward does not accumulate for users if no additional WETH(staking rewards is deposited into Staking.sol).
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {Staking} from "../src/Staking.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol";
contract testStaking is Test {
ERC20Mock public weth;
ERC20Mock public stakingToken;
Staking public staking;
uint256 startAt;
uint256 public wethAmount = 10e18;
address public user1 = makeAddr("user1");
address public user2 = makeAddr("user2");
address public user3 = makeAddr("user3");
function setUp() public {
weth = new ERC20Mock();
stakingToken = new ERC20Mock();
staking= new Staking(address(stakingToken), address(weth));
weth.mint(address(staking), wethAmount);
stakingToken.mint(user1, 100e18);
stakingToken.mint(user2, 100e18);
stakingToken.mint(user3, 100e18);
vm.startPrank(user1);
stakingToken.approve(address(staking), 100e18);
staking.deposit(100e18);
startAt = block.timestamp;
vm.stopPrank();
}
function testStakingAttack()public{
vm.startPrank(user2);
stakingToken.approve(address(staking), 100e18);
staking.deposit(100e18);
vm.stopPrank();
vm.startPrank(user3);
stakingToken.approve(address(staking), 100e18);
staking.deposit(100e18);
vm.stopPrank();
vm.warp(startAt + 10 days);
vm.startPrank(user1);
uint256 rewardsAccumulatedInMapping = staking.claimable(user1);
console.log("user1 rewards accumulated based on internal accounting");
console.logUint(rewardsAccumulatedInMapping);
staking.claim();
console.log("user1 WETH balance after claim");
console.logUint(weth.balanceOf(user1));
vm.stopPrank();
}
}
I am not sure what the best mitigation approach is here. This contract does not provide how staking reward is calculated. There are also other glaring issues with this contract that need to be addressed.