289 lines
10 KiB
Solidity
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);
|
|
}
|
|
}
|