// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.13; import "forge-std/Test.sol"; import "forge-std/console.sol"; import "../src/BloodX.sol"; import "../src/StakeX.sol"; contract BloodXTest is Test { BloodX public bloodX; StakeX public stakeX; uint256 constant MAX_INT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; function setUp() public { bloodX = new BloodX("name", "SYM"); stakeX = new StakeX("nameStake", "SYS", address(bloodX)); bloodX.setStakingContract(address(stakeX)); } function test_MintStakeUnstake(address account, uint256 amount) public { vm.assume(amount > 1); vm.assume(amount < MAX_INT / 100000 ether); vm.assume(account != address(0)); vm.assume(account != address(bloodX)); vm.assume(account != address(stakeX)); // test mint uint256 totalSupplyBefore = bloodX.totalSupply(); uint256 balanceBefore = bloodX.balanceOf(account); bloodX.purchase(account, amount); uint256 totalAfter = bloodX.totalSupply(); assertEq(totalAfter, totalSupplyBefore + amount, "total supply should match"); assertEq(bloodX.balanceOf(account), balanceBefore + amount, "balance should match"); // test stake uint256 newStake = amount / 2 * 100000 ether / totalAfter; { uint256 outstandingBefore = stakeX.totalSupply(); uint256 stakeBalanceBefore = stakeX.balanceOf(account); vm.prank(account); bloodX.stake(account, amount / 2); assertEq(bloodX.totalSupply(), totalSupplyBefore + (amount - (amount / 2)), "total supply should match after stake"); assertEq(bloodX.balanceOf(account), balanceBefore + (amount - (amount / 2)), "balance should match after stake"); assertEq(outstandingBefore + newStake, stakeX.totalSupply(), "outstanding supply should match"); assertEq(stakeBalanceBefore + newStake, stakeX.balanceOf(account), "balance of stake account should match"); } // test unstake { (uint256 totalBefore, uint256 leftBefore,) = stakeX.getUnstakeSlot(account); vm.prank(account); stakeX.unstake(account, newStake / 2); uint256 timeBefore = block.timestamp; vm.warp(timeBefore + 60 * 60 * 36); stakeX.unstakeTick(account); (uint256 total, uint256 left, uint256 start) = stakeX.getUnstakeSlot(account); assertEq(total, totalBefore + (newStake / 2), "total unstake should match"); assertApproxEqAbs(left, leftBefore + (newStake / 4), 1); assertEq(start, timeBefore, "time unstake should match"); vm.warp(timeBefore + 60 * 60 * 72); stakeX.unstakeTick(account); } } }