1
0
forked from mico/idle_moloch

Merged latest main

This commit is contained in:
mic0 2024-10-29 12:12:55 +01:00
commit 64b9be5ae8
Signed by: mico
GPG Key ID: A3F8023524CF1C8D
3 changed files with 230 additions and 15 deletions

File diff suppressed because one or more lines are too long

View File

@ -24,13 +24,30 @@ contract RaidGeld is ERC20, Ownable, Constants {
address public pool; address public pool;
// Uniswap // Uniswap
ISwapRouter02 private constant router = ISwapRouter02(SWAP_ROUTER); ISwapRouter02 private constant router = ISwapRouter02(SWAP_ROUTER);
// Events
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
);
// Modifier for functions that should only be available to registered players // Modifier for functions that should only be available to registered players
modifier onlyPlayer() { modifier onlyPlayer() {
require(players[msg.sender].created_at != 0, "Not an initiated player"); require(players[msg.sender].created_at != 0, "Not an initiated player");
_; _;
} }
// Modifier for functions that should only be available to non initialized players
modifier newPlayer() { modifier newPlayer() {
require(players[msg.sender].created_at == 0, "Whoops, player already exists :)"); require(players[msg.sender].created_at == 0, "Whoops, player already exists :)");
@ -47,15 +64,21 @@ contract RaidGeld is ERC20, Ownable, Constants {
// Mint some starting tokens to the player // Mint some starting tokens to the player
_mint(player, INITIAL_GELD); _mint(player, INITIAL_GELD);
// Set initial states // Set initial states
players[player] = players[msg.sender] = Player({
Player({total_minted: INITIAL_GELD, created_at: block.timestamp, last_raided_at: block.timestamp}); total_minted: INITIAL_GELD,
armies[player] = Army({ created_at: block.timestamp,
last_raided_at: block.timestamp
});
armies[msg.sender] = Army({
moloch_denier: Raider({level: 0}), moloch_denier: Raider({level: 0}),
apprentice: Raider({level: 0}), apprentice: Raider({level: 0}),
anointed: Raider({level: 0}), anointed: Raider({level: 0}),
champion: Raider({level: 0}), champion: Raider({level: 0}),
profit_per_second: 0 profit_per_second: 0
}); });
// Emit event
emit PlayerRegistered(msg.sender, INITIAL_GELD);
} }
// New player want to register with ETH // New player want to register with ETH
@ -101,11 +124,14 @@ contract RaidGeld is ERC20, Ownable, Constants {
// Manual minting for itchy fingers // Manual minting for itchy fingers
function raid() external onlyPlayer { function raid() external onlyPlayer {
performRaid(msg.sender); uint256 totalMinted = performRaid(msg.sender);
// Emit event
emit RaidPerformed(msg.sender, totalMinted, balanceOf(msg.sender));
} }
// Helper so we can use it when buying units too // Helper so we can use it when buying units too
function performRaid(address player) private { function performRaid(address player) private returns (uint256) {
uint256 time_past = block.timestamp - players[player].last_raided_at; uint256 time_past = block.timestamp - players[player].last_raided_at;
uint256 new_geld = armies[player].profit_per_second * time_past; uint256 new_geld = armies[player].profit_per_second * time_past;
@ -114,6 +140,8 @@ contract RaidGeld is ERC20, Ownable, Constants {
_mint(player, new_geld); _mint(player, new_geld);
players[player].last_raided_at = block.timestamp; players[player].last_raided_at = block.timestamp;
players[player].total_minted += new_geld; players[player].total_minted += new_geld;
return players[player].total_minted;
} }
// Function to get Player struct // Function to get Player struct
@ -151,13 +179,24 @@ contract RaidGeld is ERC20, Ownable, Constants {
currentLevel = army.champion.level; currentLevel = army.champion.level;
} }
uint256 cost = RaidGeldUtils.calculateUnitPrice(unit, currentLevel, n_units); uint256 cost = RaidGeldUtils.calculateUnitPrice(
unit,
currentLevel,
n_units
);
// First trigger a raid so player receives what he is due at to this moment // First trigger a raid so player receives what he is due at to this moment
uint256 time_past = block.timestamp - players[msg.sender].last_raided_at; uint256 time_past = block.timestamp -
players[msg.sender].last_raided_at;
uint256 new_geld = armies[msg.sender].profit_per_second * time_past; uint256 new_geld = armies[msg.sender].profit_per_second * time_past;
require(balanceOf(msg.sender) + new_geld > cost, "Not enough GELD to add this unit"); require(
performRaid(msg.sender); balanceOf(msg.sender) + new_geld >= cost,
"Not enough GELD to add this unit"
);
uint256 totalMinted = performRaid(msg.sender);
// Emit event
emit RaidPerformed(msg.sender, totalMinted, balanceOf(msg.sender));
// TODO: Since we are first minting then burning the token, this could be simplified // TODO: Since we are first minting then burning the token, this could be simplified
// by first calculating the difference and then minting / burning in just one operation // by first calculating the difference and then minting / burning in just one operation
@ -182,10 +221,25 @@ contract RaidGeld is ERC20, Ownable, Constants {
// update profite per second // update profite per second
army.profit_per_second = RaidGeldUtils.calculateProfitsPerSecond(army); army.profit_per_second = RaidGeldUtils.calculateProfitsPerSecond(army);
// Emit event
emit UnitAdded(
msg.sender,
unit,
n_units,
cost,
balanceOf(msg.sender),
army.moloch_denier.level,
army.apprentice.level,
army.anointed.level,
army.champion.level
);
} }
receive() external payable { receive() external payable {
revert("No plain Ether accepted, use register() function to check in :)"); revert(
"No plain Ether accepted, use register() function to check in :)"
);
} }
// Revert any non-function-call Ether transfers or calls to non-existent functions // Revert any non-function-call Ether transfers or calls to non-existent functions

View File

@ -15,6 +15,25 @@ contract raid_geldTest is Test, Constants {
address public player2; address public player2;
address public owner; 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 { function setUp() public {
owner = address(0x126); owner = address(0x126);
player1 = address(0x123); player1 = address(0x123);
@ -42,7 +61,7 @@ contract raid_geldTest is Test, Constants {
function test_00_no_fallback() public { function test_00_no_fallback() public {
vm.expectRevert(); vm.expectRevert();
// Send Ether with some data to trigger fallback // Send Ether with some data to trigger fallback
(bool success,) = address(raid_geld).call{value: 0.1 ether}("0x1234"); (bool success, ) = address(raid_geld).call{value: 0.1 ether}("0x1234");
} }
function test_01_no_receive() public { function test_01_no_receive() public {
@ -57,7 +76,9 @@ contract raid_geldTest is Test, Constants {
uint256 contractBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); uint256 contractBalance = raid_geld.daoToken().balanceOf(address(raid_geld));
uint256 userBalance = address(player1).balance; uint256 userBalance = address(player1).balance;
// Send registration fee ETH to the contract // Making sure event is emitted when player is registered
vm.expectEmit(address(raid_geld));
emit PlayerRegistered(player1, raid_geld.INITIAL_GELD());
registerPlayer(); registerPlayer();
// Check that initialraid_geld.is received by the player // Check that initialraid_geld.is received by the player
@ -91,7 +112,8 @@ contract raid_geldTest is Test, Constants {
uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld));
// Send registration fee ETH to the contract // Making sure event is emitted when player is registered
// doesnt test player emitted event because other events get emitted before it
registerPlayerWithDaoToken(); registerPlayerWithDaoToken();
// Check that initial raid_geld is received by the player // Check that initial raid_geld is received by the player
@ -121,6 +143,8 @@ contract raid_geldTest is Test, Constants {
// Switch to Player 1 and register it // Switch to Player 1 and register it
vm.startPrank(player1); vm.startPrank(player1);
// doesnt test player emitted event because other events get emitted before it
registerPlayerWithDaoToken(); registerPlayerWithDaoToken();
// Switch back to owner and withdraw funds // Switch back to owner and withdraw funds
@ -149,6 +173,11 @@ contract raid_geldTest is Test, Constants {
bool is_registered = raid_geld.isRegistered(player1); bool is_registered = raid_geld.isRegistered(player1);
assertEq(is_registered, false); assertEq(is_registered, false);
vm.startPrank(player1); 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(); registerPlayer();
is_registered = raid_geld.isRegistered(player1); is_registered = raid_geld.isRegistered(player1);
assertEq(is_registered, true); assertEq(is_registered, true);
@ -156,6 +185,11 @@ contract raid_geldTest is Test, Constants {
function test_06_add_unit() public { function test_06_add_unit() public {
vm.startPrank(player1); 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(); registerPlayer();
vm.expectRevert(); vm.expectRevert();
@ -170,6 +204,25 @@ contract raid_geldTest is Test, Constants {
uint256 unit_level = army.moloch_denier.level; uint256 unit_level = army.moloch_denier.level;
uint256 balance = raid_geld.balanceOf(player1); uint256 balance = raid_geld.balanceOf(player1);
uint256 income_per_sec = army.profit_per_second; 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 // Add 1 unit
raid_geld.addUnit(0, 1); raid_geld.addUnit(0, 1);
uint256 unitPrice = RaidGeldUtils.calculateUnitPrice(0, 0, 1); uint256 unitPrice = RaidGeldUtils.calculateUnitPrice(0, 0, 1);
@ -198,23 +251,63 @@ contract raid_geldTest is Test, Constants {
vm.startPrank(player1); vm.startPrank(player1);
registerPlayer(); 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 // bought 1 moloch_denier
raid_geld.addUnit(0, 1); raid_geld.addUnit(0, 1);
vm.warp(block.timestamp + 15); vm.warp(block.timestamp + 15);
uint256 balance = raid_geld.balanceOf(player1); 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 // Trigger raid funds minting
raid_geld.raid(); raid_geld.raid();
// New balance should be larger // New balance should be larger
uint256 newBalance = raid_geld.balanceOf(player1); uint256 newBalance = raid_geld.balanceOf(player1);
Player memory player = raid_geld.getPlayer(player1); player = raid_geld.getPlayer(player1);
uint256 last_raided_at = player.last_raided_at; uint256 last_raided_at = player.last_raided_at;
assertLt(balance, newBalance); assertLt(balance, newBalance);
// After wait time passes raid should bring in profits again // After wait time passes raid should bring in profits again
vm.warp(block.timestamp + 15); vm.warp(block.timestamp + 15);
amountMinted = army.profit_per_second * 15;
emit RaidPerformed(
address(player1),
player.total_minted + amountMinted,
balance + amountMinted
);
raid_geld.raid(); raid_geld.raid();
// Balance should reflect that // Balance should reflect that