From 7a32129f7e0ef920a7066aeb741967e9bf9f2273 Mon Sep 17 00:00:00 2001 From: Mitja Belak Date: Fri, 25 Oct 2024 11:12:51 +0200 Subject: [PATCH] Ran forge fmt + solved client bug with amounts being much too high due to change in contract calculations --- app/src/components/Counter.tsx | 12 +++++------- app/src/providers/PlayerProvider.tsx | 2 +- src/RaidGeld.sol | 8 ++++---- src/RaidGeldStructs.sol | 4 +--- src/RaidGeldUtils.sol | 7 ++----- test/RaidGeld.t.sol | 4 ++-- test/RaidGeldUtils.t.sol | 29 +++++++++++++--------------- 7 files changed, 28 insertions(+), 38 deletions(-) diff --git a/app/src/components/Counter.tsx b/app/src/components/Counter.tsx index 5a85ce7..5d924b3 100644 --- a/app/src/components/Counter.tsx +++ b/app/src/components/Counter.tsx @@ -8,14 +8,12 @@ const calculateBalance = (balance: bigint, perSecond: bigint, lastRaidedAt: bigi (new Date()).getTime() - parseInt(lastRaidedAt.toString()) * 1000; return ( balance + - (BigInt(millisecondsSinceLastRaid) * (perSecond * BigInt(10000) /* decimals */) + (BigInt(millisecondsSinceLastRaid) * perSecond / BigInt(1000) /* deduct milliseconds*/)) } -export const toReadable = (value: bigint, applyTokenDivision?: boolean) => { - if (applyTokenDivision) { - value = value / BigInt(10000); - } +export const toReadable = (value: bigint) => { + value = value / BigInt(10000); const suffixes = [ { value: BigInt('1000'), suffix: 'thousand' }, { value: BigInt('1000000'), suffix: 'million' }, @@ -64,8 +62,8 @@ const Counter = () => { balance, army?.profit_per_second ?? BigInt(0), player?.last_raided_at ?? BigInt(0) - ), true); - availableBalance.current = toReadable(balance, true); + )); + availableBalance.current = toReadable(balance); render(); }, 100); return () => clearInterval(tickInterval) diff --git a/app/src/providers/PlayerProvider.tsx b/app/src/providers/PlayerProvider.tsx index c139b5c..8221e9b 100644 --- a/app/src/providers/PlayerProvider.tsx +++ b/app/src/providers/PlayerProvider.tsx @@ -91,7 +91,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => { } }); - console.log(player) + console.log(player, army) const register = useCallback(() => { writeContract({ diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol index a70b9e6..52c96a4 100644 --- a/src/RaidGeld.sol +++ b/src/RaidGeld.sol @@ -63,7 +63,7 @@ contract RaidGeld is ERC20, Ownable { // Helper so we can use it when buying units too function performRaid(address player) private { uint256 time_past = block.timestamp - players[player].last_raided_at; - + uint256 new_geld = armies[player].profit_per_second * time_past; // TODO: Pink noise, make it so sometimes its better than expected @@ -109,14 +109,14 @@ contract RaidGeld is ERC20, Ownable { } 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 performRaid(msg.sender); require(balanceOf(msg.sender) > cost, "Not enough GELD to add this much"); - + // 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 - // then burn the cost of the new army + // then burn the cost of the new army _burn(msg.sender, cost); // Increase level diff --git a/src/RaidGeldStructs.sol b/src/RaidGeldStructs.sol index c846e87..9846c09 100644 --- a/src/RaidGeldStructs.sol +++ b/src/RaidGeldStructs.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; - - struct Raider { uint16 level; } @@ -19,4 +17,4 @@ struct Player { uint256 total_minted; uint256 created_at; uint256 last_raided_at; -} \ No newline at end of file +} diff --git a/src/RaidGeldUtils.sol b/src/RaidGeldUtils.sol index e5a5427..9b6581e 100644 --- a/src/RaidGeldUtils.sol +++ b/src/RaidGeldUtils.sol @@ -4,15 +4,12 @@ pragma solidity ^0.8.13; import {Army} from "../src/RaidGeldStructs.sol"; library RaidGeldUtils { - uint256 public constant PRECISION = 10000; - uint256 constant BASE_PRICE = 380000; uint256 constant PRICE_FACTOR = 11500; uint256 constant APPRENTICE_PROFIT = 61000; uint256 constant ANOINTED_PROFIT = 6 * 64000; - uint256 constant CHAMPION_PROFIT = 67000 * 61000 * 64000/ PRECISION / PRECISION; - + uint256 constant CHAMPION_PROFIT = 67000 * 61000 * 64000 / PRECISION / PRECISION; function calculateUnitPrice(uint8 unit, uint16 currentLevel, uint16 units) internal pure returns (uint256) { require(unit <= 3, "No matching unit found"); @@ -37,7 +34,7 @@ library RaidGeldUtils { uint256 apprentice_profit = army.apprentice.level * APPRENTICE_PROFIT; - uint256 anointed_profit = army.anointed.level * ANOINTED_PROFIT; + uint256 anointed_profit = army.anointed.level * ANOINTED_PROFIT; uint256 champion_profit = army.champion.level * CHAMPION_PROFIT; diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol index c704c5d..375fb31 100644 --- a/test/RaidGeld.t.sol +++ b/test/RaidGeld.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; import {RaidGeld, Army, Player} from "../src/RaidGeld.sol"; -import "../src/RaidGeldUtils.sol"; +import "../src/RaidGeldUtils.sol"; contract raid_geldTest is Test { RaidGeld public raid_geld; @@ -124,7 +124,7 @@ contract raid_geldTest is Test { // 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 + // 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); diff --git a/test/RaidGeldUtils.t.sol b/test/RaidGeldUtils.t.sol index 88771fb..8de1385 100644 --- a/test/RaidGeldUtils.t.sol +++ b/test/RaidGeldUtils.t.sol @@ -3,14 +3,14 @@ pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; import {Army, Raider} from "../src/RaidGeld.sol"; -import "../src/RaidGeldUtils.sol"; +import "../src/RaidGeldUtils.sol"; contract raid_geldTest is Test { - function test_0_unit_price() pure public { + function test_0_unit_price() public pure { // buying 1 unit of moloch_denier uint256 basePriceMolochDenier = RaidGeldUtils.calculateUnitPrice(0, 0, 1); assertEq(basePriceMolochDenier, RaidGeldUtils.BASE_PRICE); - + // buying 3 units // has to be a bit more than 3 * 38 = 114 uint256 price = RaidGeldUtils.calculateUnitPrice(0, 0, 3); @@ -30,28 +30,25 @@ contract raid_geldTest is Test { function test_1_profits_per_second(uint16 _dLvl, uint16 _apLvl, uint16 _anLvl, uint16 _cLvl) public { Army memory army = Army({ - moloch_denier: Raider({ level: 1}), - apprentice: Raider({ level: 0}), - anointed: Raider({ level: 0}), - champion: Raider({ level: 0}), + moloch_denier: Raider({level: 1}), + apprentice: Raider({level: 0}), + anointed: Raider({level: 0}), + champion: Raider({level: 0}), profit_per_second: 0 // irrelevant for this test }); uint256 profits_per_second = RaidGeldUtils.calculateProfitsPerSecond(army); assertEq(profits_per_second, RaidGeldUtils.PRECISION); army = Army({ - moloch_denier: Raider({ level: _dLvl}), - apprentice: Raider({ level: _apLvl}), - anointed: Raider({ level: _anLvl}), - champion: Raider({ level: _cLvl}), + moloch_denier: Raider({level: _dLvl}), + apprentice: Raider({level: _apLvl}), + anointed: Raider({level: _anLvl}), + champion: Raider({level: _cLvl}), profit_per_second: 0 // irrelevant for this test }); profits_per_second = RaidGeldUtils.calculateProfitsPerSecond(army); - uint256 expected = - _dLvl * RaidGeldUtils.PRECISION + - _apLvl * RaidGeldUtils.APPRENTICE_PROFIT + - _anLvl * RaidGeldUtils.ANOINTED_PROFIT + - _cLvl * RaidGeldUtils.CHAMPION_PROFIT; + uint256 expected = _dLvl * RaidGeldUtils.PRECISION + _apLvl * RaidGeldUtils.APPRENTICE_PROFIT + + _anLvl * RaidGeldUtils.ANOINTED_PROFIT + _cLvl * RaidGeldUtils.CHAMPION_PROFIT; assertEq(profits_per_second, expected); } }