If the reward are sent to contract before any user stakes, it can be lost.
In case there is no staking and there is a transfer of WETH to this contract as rewards, it will be stuck in this contract because the deposit will increase the amount of TKN in contract first and then update the index and balance state variables.
pragma solidity ^0.8.13;
import {Test, console2} from "forge-std/Test.sol";
import "../src/Staking.sol";
import {ERC20} from "solady/src/tokens/ERC20.sol";
contract TERC20 is ERC20 {
function name() public pure override returns (string memory) {
return "Test ERC20";
}
function symbol() public pure override returns (string memory) {
return "TERC20";
}
function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}
}
contract POCTest is Test {
Staking public staking;
TERC20 public beedle;
TERC20 public weth;
address public attacker = address(0x1);
address public staker = address(0x2);
function setUp() public {
beedle = new TERC20();
weth = new TERC20();
staking = new Staking(address(beedle), address(weth));
beedle.mint(staker, 10e18);
}
function testStuckRewardDeposit() public {
weth.mint(address(staking), 1e18);
vm.startPrank(staker);
beedle.approve(address(staking), 10e18);
staking.deposit(10e18);
vm.stopPrank();
vm.prank(staker);
staking.claim();
console2.log("Staker claim: ", weth.balanceOf(staker));
console2.log("Contract balance: ", weth.balanceOf(address(staking)));
}
}
Lost the first reward.
The recommendation is to create an extra function to retrieve the rewards in case there is no TKN balance in the contract.