// 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"; import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.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); stdstore.target(WETH).sig("balanceOf(address)").with_key(_acc).checked_write(100 ether); } function getPoolLiquidity() public view { IUniswapV3Pool pool = IUniswapV3Pool(POOL); console.log(pool.liquidity()); } function registerPlayer() private { getPoolLiquidity(); raid_geld.weth().approve(address(raid_geld), raid_geld.BUY_IN_AMOUNT()); raid_geld.register_eth(); } function registerPlayerWithDaoToken() private { raid_geld.daoToken().approve(address(raid_geld), raid_geld.BUY_IN_DAO_TOKEN_AMOUNT()); raid_geld.register_dao(); } 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 initial raid_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_01_ETH_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_03_02_RGCVII_funds_can_be_withdrawn() public { uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); // Switch to Player 1 and register it vm.startPrank(player1); registerPlayerWithDaoToken(); // Switch back to owner and withdraw funds vm.startPrank(owner); raid_geld.withdraw_dao(); uint256 newBalance = raid_geld.daoToken().balanceOf(address(owner)); uint256 newContractBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); // contract balance should be empty assertEq(newContractBalance, 0); // owner should have the extra funds assertGt(newBalance, initialBalance); } 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); vm.warp(block.timestamp + 15); uint256 balance = raid_geld.balanceOf(player1); // 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); // After wait time passes raid should bring in profits again vm.warp(block.timestamp + 15); 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); } }