// SPDX-License-Identifier: MIT // Foundry test — place at test/SimpleStaking.t.sol // Run: forge test -vv pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../src/SimpleStaking.sol"; contract SimpleStakingTest is Test { SimpleStaking staking; address owner = address(this); address alice = address(0xA11CE); address bob = address(0xB0B); uint256 constant RATE = 1e9; // 1e9 / 1e18 per sec per wei function setUp() public { staking = new SimpleStaking(RATE); vm.deal(address(this), 10 ether); vm.deal(alice, 10 ether); vm.deal(bob, 10 ether); staking.fundRewards{value: 1 ether}(); } function testStakeIncreasesBalances() public { vm.prank(alice); staking.stake{value: 0.5 ether}(); (uint256 amt,,) = staking.stakes(alice); assertEq(amt, 0.5 ether); assertEq(staking.totalStaked(), 0.5 ether); } function testRewardsAccrueLinearly() public { vm.prank(alice); staking.stake{value: 1 ether}(); skip(100); uint256 pending = staking.pendingRewards(alice); assertEq(pending, uint256(100) * RATE); } function testClaimTransfersRewards() public { vm.prank(alice); staking.stake{value: 1 ether}(); skip(50); uint256 before = alice.balance; vm.prank(alice); staking.claimRewards(); assertGt(alice.balance, before); (, uint256 debt,) = staking.stakes(alice); assertEq(debt, 0); } function testUnstakePartial() public { vm.startPrank(alice); staking.stake{value: 1 ether}(); staking.unstake(0.4 ether); vm.stopPrank(); (uint256 amt,,) = staking.stakes(alice); assertEq(amt, 0.6 ether); } function testRevertUnstakeTooMuch() public { vm.startPrank(alice); staking.stake{value: 0.1 ether}(); vm.expectRevert(bytes("invalid amount")); staking.unstake(1 ether); vm.stopPrank(); } function testOnlyOwnerSetsRate() public { vm.prank(alice); vm.expectRevert(bytes("not owner")); staking.setRewardRate(1); } }