// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; import {stdStorage, StdStorage} from "forge-std/Test.sol"; import {RaidGeld, Army, Player} from "../src/RaidGeld.sol"; import "../src/RaidGeldUtils.sol"; import {Constants} from "../src/Constants.sol"; contract raid_geldTest is Test, Constants { using stdStorage for StdStorage; RaidGeld public raid_geld; address public player1; address public player2; address public owner; function setUp() public { owner = address(0x126); player1 = address(0x123); vm.deal(owner, 10 ether); fundAccount(player1); vm.prank(owner); raid_geld = new RaidGeld(DAO_TOKEN, POOL); } function fundAccount(address _acc) private { vm.deal(_acc, 10 ether); stdstore .target(DAO_TOKEN) .sig("balanceOf(address)") .with_key(_acc) .checked_write(100 ether); } function registerPlayer() private { raid_geld.register{value: raid_geld.BUY_IN_AMOUNT()}(); } function registerPlayerWithDaoToken() private { raid_geld.daoToken().approve(address(raid_geld), raid_geld.BUY_IN_DAO_TOKEN_AMOUNT()); raid_geld.register(); } function test_00_no_fallback() public { vm.expectRevert(); // Send Ether with some data to trigger fallback (bool success,) = address(raid_geld).call{value: 0.1 ether}("0x1234"); } function test_01_no_receive() public { vm.startPrank(player1); vm.expectRevert(); payable(address(raid_geld)).transfer(0.1 ether); } function test_02_1_registrationWithEth() public { vm.startPrank(player1); uint256 initialBalance = address(raid_geld).balance; // Send registration fee ETH to the contract registerPlayer(); // Check that initialraid_geld.is received by the player assertEq(raid_geld.balanceOf(player1), raid_geld.INITIAL_GELD()); // Verify the contract balance is updated assertEq(address(raid_geld).balance, initialBalance + raid_geld.BUY_IN_AMOUNT()); // Verify player is set initially Player memory player = raid_geld.getPlayer(player1); assertEq(player.total_minted, raid_geld.INITIAL_GELD()); assertEq(player.created_at, block.timestamp); assertEq(player.last_raided_at, block.timestamp); Army memory army = raid_geld.getArmy(player1); assertEq(army.moloch_denier.level, 0); assertEq(army.apprentice.level, 0); assertEq(army.anointed.level, 0); assertEq(army.champion.level, 0); } function test_02_2_registrationWithDaoToken() public { vm.startPrank(player1); uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); // Send registration fee ETH to the contract registerPlayerWithDaoToken(); // Check that initialraid_geld.is received by the player assertEq(raid_geld.balanceOf(player1), raid_geld.INITIAL_GELD()); // Verify the contract dao token balance is updated assertEq(raid_geld.daoToken().balanceOf(address(raid_geld)), initialBalance + raid_geld.BUY_IN_DAO_TOKEN_AMOUNT()); // Verify player is set initially Player memory player = raid_geld.getPlayer(player1); assertEq(player.total_minted, raid_geld.INITIAL_GELD()); assertEq(player.created_at, block.timestamp); assertEq(player.last_raided_at, block.timestamp); Army memory army = raid_geld.getArmy(player1); assertEq(army.moloch_denier.level, 0); assertEq(army.apprentice.level, 0); assertEq(army.anointed.level, 0); assertEq(army.champion.level, 0); } function test_03_funds_can_be_withdrawn() public { uint256 initialBalance = owner.balance; // Switch to Player 1 and register it vm.startPrank(player1); registerPlayer(); // Switch back to owner and withdraw funds vm.startPrank(owner); raid_geld.withdraw(); uint256 newBalance = owner.balance; uint256 newContractBalance = address(raid_geld).balance; // contract balance should be empty assertEq(newContractBalance, 0); // owner should have the extra funds assertEq(newBalance, initialBalance + raid_geld.BUY_IN_AMOUNT()); } function test_04_only_owner_can_withdraw() public { // Register player 1 vm.startPrank(player1); registerPlayer(); // attempt to withdraw with player 1, it should fail vm.expectRevert(); raid_geld.withdraw(); } function test_05_is_registered() public { bool is_registered = raid_geld.isRegistered(player1); assertEq(is_registered, false); vm.startPrank(player1); registerPlayer(); is_registered = raid_geld.isRegistered(player1); assertEq(is_registered, true); } function test_06_add_unit() public { vm.startPrank(player1); registerPlayer(); vm.expectRevert(); // units should be in range raid_geld.addUnit(100, 1); // Player should have enough tokens to burn to get units vm.expectRevert(); raid_geld.addUnit(1, 100); Army memory army = raid_geld.getArmy(player1); uint256 unit_level = army.moloch_denier.level; uint256 balance = raid_geld.balanceOf(player1); uint256 income_per_sec = army.profit_per_second; // Add 1 unit raid_geld.addUnit(0, 1); uint256 unitPrice = RaidGeldUtils.calculateUnitPrice(0, 0, 1); // Check that those tokens were burnt // WARN: In addUnit will mint additional tokens but they are not calculated // into this because the test doesnt move the blockchain so no extra tokens // are minted to the user uint256 newBalance = raid_geld.balanceOf(player1); assertEq(newBalance, balance - unitPrice); army = raid_geld.getArmy(player1); // Check that unit level increased uint256 new_unit_level = army.moloch_denier.level; assertEq(new_unit_level, unit_level + 1); // Check that user income per second increased uint256 new_income_per_sec = army.profit_per_second; assertLt(income_per_sec, new_income_per_sec); } function test_07_raid() public { // Let some time pass so we dont start at block timestamp 0 vm.warp(120); // Register player 1 vm.startPrank(player1); registerPlayer(); // bought 1 moloch_denier raid_geld.addUnit(0, 1); uint256 balance = raid_geld.balanceOf(player1); // Warp time a bit so first raid doesnt fail vm.warp(block.timestamp + raid_geld.RAID_WAIT()); // Trigger raid funds minting raid_geld.raid(); // New balance should be larger uint256 newBalance = raid_geld.balanceOf(player1); Player memory player = raid_geld.getPlayer(player1); uint256 last_raided_at = player.last_raided_at; assertLt(balance, newBalance); // Expect fail if we raid again, we need to wait a bit vm.expectRevert(); raid_geld.raid(); // After wait time passes raid should work again vm.warp(block.timestamp + raid_geld.RAID_WAIT()); raid_geld.raid(); // Balance should reflect that uint256 newestBalance = raid_geld.balanceOf(player1); player = raid_geld.getPlayer(player1); uint256 last_raided_at_2 = player.last_raided_at; assertLt(newBalance, newestBalance); assertLt(last_raided_at, last_raided_at_2); } }