1
0
forked from mico/idle_moloch
idle_moloch/test/RaidGeld.t.sol
2024-10-30 12:34:58 +01:00

289 lines
10 KiB
Solidity

// 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;
event Approval(address indexed owner, address indexed spender, uint256 value);
event PlayerRegistered(address indexed player, uint256 initialGeld);
event RaidPerformed(address indexed player, uint256 totalMinted, uint256 geldBalance);
event UnitAdded(
address indexed player,
uint8 unitType,
uint16 nUnits,
uint256 cost,
uint256 geldBalance,
uint16 molochDenierLevel,
uint16 apprenticeLevel,
uint16 anointedLevel,
uint16 championLevel
);
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);
raid_geld.weth().deposit{value: 5 ether}();
}
function fundAccount(address _acc) private {
vm.deal(_acc, 10 ether);
stdstore.target(DAO_TOKEN).sig("balanceOf(address)").with_key(_acc).checked_write(1000 ether);
}
function registerPlayer() private {
raid_geld.register_eth{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_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 contractBalance = raid_geld.daoToken().balanceOf(address(raid_geld));
uint256 userBalance = address(player1).balance;
// Making sure event is emitted when player is registered
vm.expectEmit(address(raid_geld));
emit PlayerRegistered(player1, raid_geld.INITIAL_GELD());
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
uint256 contractBalance2 = raid_geld.daoToken().balanceOf(address(raid_geld));
uint256 userBalance2 = address(player1).balance;
// Contract should get DAO tokens
assertLt(contractBalance, contractBalance2);
// Player should lose ETH
assertEq(userBalance2, userBalance - 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));
// Making sure event is emitted when player is registered
// doesnt test player emitted event because other events get emitted before it
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_dao_token_can_be_withdrawn() public {
uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld));
// Switch to Player 1 and register it
vm.startPrank(player1);
// doesnt test player emitted event because other events get emitted before it
registerPlayerWithDaoToken();
// Switch back to owner and withdraw funds
vm.startPrank(owner);
raid_geld.withdraw();
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);
// Making sure event is emitted when player is registered
vm.expectEmit(address(raid_geld));
emit PlayerRegistered(player1, raid_geld.INITIAL_GELD());
registerPlayer();
is_registered = raid_geld.isRegistered(player1);
assertEq(is_registered, true);
}
function test_06_add_unit() public {
vm.startPrank(player1);
// Making sure event is emitted when player is registered
vm.expectEmit(address(raid_geld));
emit PlayerRegistered(player1, raid_geld.INITIAL_GELD());
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;
uint256 cost = RaidGeldUtils.calculateUnitPrice(0, 0, 1);
uint256 playerBalance = raid_geld.balanceOf(address(player1));
// Making sure event is emitted when player adds a unit
vm.expectEmit(address(raid_geld));
emit UnitAdded(address(player1), 0, 1, cost, playerBalance - cost, 1, 0, 0, 0);
// 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();
uint256 cost = RaidGeldUtils.calculateUnitPrice(0, 0, 1);
uint256 playerBalance = raid_geld.balanceOf(address(player1));
// Making sure event is emitted when player adds a unit
vm.expectEmit(address(raid_geld));
emit UnitAdded(address(player1), 0, 1, cost, playerBalance - cost, 1, 0, 0, 0);
// bought 1 moloch_denier
raid_geld.addUnit(0, 1);
vm.warp(block.timestamp + 15);
uint256 balance = raid_geld.balanceOf(player1);
Army memory army = raid_geld.getArmy(player1);
Player memory player = raid_geld.getPlayer(player1);
uint256 amountMinted = army.profit_per_second * 15;
// Making sure event is emitted when player performs a raid
vm.expectEmit(address(raid_geld));
emit RaidPerformed(address(player1), player.total_minted + amountMinted, balance + amountMinted);
// Trigger raid funds minting
raid_geld.raid();
// New balance should be larger
uint256 newBalance = raid_geld.balanceOf(player1);
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);
amountMinted = army.profit_per_second * 15;
emit RaidPerformed(address(player1), player.total_minted + amountMinted, balance + amountMinted);
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);
}
}