WETH fees sent to the staking contract, if there are no tokens staked, will be lost forever.
Consider the following POC:
import "forge-std/Test.sol";
import "../src/Staking.sol";
import {ERC20, WETH} from "solady/src/tokens/WETH.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 StakingTest is Test {
Staking public staking;
WETH public wethToken;
TERC20 public stakingToken;
address public staker1 = address(0x1);
address public owner = address(0x3);
function setUp() public {
stakingToken = new TERC20();
wethToken = new WETH();
vm.deal(owner, 1000 ether);
vm.startPrank(owner);
staking = new Staking(address(stakingToken), address(wethToken));
stakingToken.mint(owner, 100 ether);
wethToken.deposit{value: 50 ether}();
}
function test_rewardsNoTokenStaked() public {
vm.startPrank(owner);
stakingToken.transfer(staker1, 20 ether);
//deposit 10 weth with no token staked.
wethToken.transfer(address(staking), 10 ether);
// users stake the tokens
vm.startPrank(staker1);
stakingToken.approve(address(staking), 20 ether);
staking.deposit(20 ether);
// claim the weth rewards
vm.startPrank(staker1);
staking.claim();
assertEq(wethToken.balanceOf(address(staking)) / 1 ether, 10);
assertEq(wethToken.balanceOf(address(staker1)) / 1 ether, 0);
// the first 10 weth are forever stuck on the contract
console.log("staking contract weth balance", wethToken.balanceOf(address(staking)) / 1 ether);
console.log("staker 1 eth balance", wethToken.balanceOf(staker1)/ 1 ether);
}
Permanent loss of WETH in this specific circumstance.
Foundry
Make sure there is always a small amount of token staked on the staking contract.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.