Merge pull request 'contract-events' (#4) from contract-events into main
Some checks are pending
CI / Foundry project (push) Waiting to run
Some checks are pending
CI / Foundry project (push) Waiting to run
Reviewed-on: #4
This commit is contained in:
commit
504197e83c
@ -1 +1 @@
|
||||
Subproject commit 8f24d6b04c92975e0795b5868aa0d783251cdeaa
|
||||
Subproject commit 1eea5bae12ae557d589f9f0f0edae2faa47cb262
|
||||
@ -15,6 +15,25 @@ contract RaidGeld is ERC20, Ownable {
|
||||
mapping(address => Player) private players;
|
||||
mapping(address => Army) private armies;
|
||||
|
||||
// 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 onlyPlayer() {
|
||||
require(players[msg.sender].created_at != 0, "Not an initiated player");
|
||||
@ -25,15 +44,21 @@ contract RaidGeld is ERC20, Ownable {
|
||||
|
||||
// This effectively registers the user
|
||||
function register() external payable {
|
||||
require(players[msg.sender].created_at == 0, "Whoops, player already exists :)");
|
||||
require(
|
||||
players[msg.sender].created_at == 0,
|
||||
"Whoops, player already exists :)"
|
||||
);
|
||||
require(msg.value == BUY_IN_AMOUNT, "Incorrect buy in amount");
|
||||
|
||||
// Mint some starting tokens to the player
|
||||
_mint(msg.sender, INITIAL_GELD);
|
||||
|
||||
// Set initial states
|
||||
players[msg.sender] =
|
||||
Player({total_minted: INITIAL_GELD, created_at: block.timestamp, last_raided_at: block.timestamp});
|
||||
players[msg.sender] = Player({
|
||||
total_minted: INITIAL_GELD,
|
||||
created_at: block.timestamp,
|
||||
last_raided_at: block.timestamp
|
||||
});
|
||||
armies[msg.sender] = Army({
|
||||
moloch_denier: Raider({level: 0}),
|
||||
apprentice: Raider({level: 0}),
|
||||
@ -41,6 +66,9 @@ contract RaidGeld is ERC20, Ownable {
|
||||
champion: Raider({level: 0}),
|
||||
profit_per_second: 0
|
||||
});
|
||||
|
||||
// Emit event
|
||||
emit PlayerRegistered(msg.sender, INITIAL_GELD);
|
||||
}
|
||||
|
||||
// Override for default number of decimals
|
||||
@ -55,11 +83,14 @@ contract RaidGeld is ERC20, Ownable {
|
||||
|
||||
// Manual minting for itchy fingers
|
||||
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
|
||||
function performRaid(address player) private {
|
||||
function performRaid(address player) private returns (uint256) {
|
||||
uint256 time_past = block.timestamp - players[player].last_raided_at;
|
||||
uint256 new_geld = armies[player].profit_per_second * time_past;
|
||||
|
||||
@ -68,6 +99,8 @@ contract RaidGeld is ERC20, Ownable {
|
||||
_mint(player, new_geld);
|
||||
players[player].last_raided_at = block.timestamp;
|
||||
players[player].total_minted += new_geld;
|
||||
|
||||
return players[player].total_minted;
|
||||
}
|
||||
|
||||
// Function to get Player struct
|
||||
@ -105,13 +138,24 @@ contract RaidGeld is ERC20, Ownable {
|
||||
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
|
||||
|
||||
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;
|
||||
require(balanceOf(msg.sender) + new_geld > cost, "Not enough GELD to add this unit");
|
||||
performRaid(msg.sender);
|
||||
require(
|
||||
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
|
||||
// by first calculating the difference and then minting / burning in just one operation
|
||||
@ -136,10 +180,25 @@ contract RaidGeld is ERC20, Ownable {
|
||||
|
||||
// update profite per second
|
||||
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 {
|
||||
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
|
||||
|
||||
@ -11,6 +11,24 @@ contract raid_geldTest is Test {
|
||||
address public player2;
|
||||
address public owner;
|
||||
|
||||
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);
|
||||
@ -27,7 +45,7 @@ contract raid_geldTest is Test {
|
||||
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");
|
||||
(bool success, ) = address(raid_geld).call{value: 0.1 ether}("0x1234");
|
||||
}
|
||||
|
||||
function test_01_no_receive() public {
|
||||
@ -41,6 +59,11 @@ contract raid_geldTest is Test {
|
||||
|
||||
uint256 initialBalance = address(raid_geld).balance;
|
||||
|
||||
// Making sure event is emitted when player is registered
|
||||
vm.expectEmit(address(raid_geld));
|
||||
|
||||
emit PlayerRegistered(player1, raid_geld.INITIAL_GELD());
|
||||
|
||||
// Send registration fee ETH to the contract
|
||||
registerPlayer();
|
||||
|
||||
@ -48,7 +71,10 @@ contract raid_geldTest is Test {
|
||||
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());
|
||||
assertEq(
|
||||
address(raid_geld).balance,
|
||||
initialBalance + raid_geld.BUY_IN_AMOUNT()
|
||||
);
|
||||
|
||||
// Verify player is set initially
|
||||
Player memory player = raid_geld.getPlayer(player1);
|
||||
@ -69,6 +95,12 @@ contract raid_geldTest is Test {
|
||||
|
||||
// Switch to Player 1 and register it
|
||||
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();
|
||||
|
||||
// Switch back to owner and withdraw funds
|
||||
@ -86,6 +118,12 @@ contract raid_geldTest is Test {
|
||||
function test_04_only_owner_can_withdraw() public {
|
||||
// Register player 1
|
||||
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();
|
||||
|
||||
// attempt to withdraw with player 1, it should fail
|
||||
@ -97,6 +135,12 @@ contract raid_geldTest is Test {
|
||||
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);
|
||||
@ -104,6 +148,12 @@ contract raid_geldTest is Test {
|
||||
|
||||
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();
|
||||
@ -118,6 +168,25 @@ contract raid_geldTest is Test {
|
||||
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);
|
||||
@ -146,23 +215,63 @@ contract raid_geldTest is Test {
|
||||
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 memory player = raid_geld.getPlayer(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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user