diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol index 7c4e0bc..8c95e8c 100644 --- a/src/RaidGeld.sol +++ b/src/RaidGeld.sol @@ -143,12 +143,6 @@ contract RaidGeld is ERC20, Ownable, Constants { return 4; } - // Allows the owner to withdraw DAO tokens - function withdraw() external onlyOwner { - uint256 amount = daoToken.balanceOf(address(this)); - daoToken.transfer(owner(), amount); - } - // Manual minting for itchy fingers function raid() external onlyActiveSession { performRaid(msg.sender); @@ -264,7 +258,7 @@ contract RaidGeld is ERC20, Ownable, Constants { _burn(msg.sender, geld_to_burn); uint256 reward = RaidGeldUtils.calculateBossReward(boss_to_attack.level, BUY_IN_DAO_TOKEN_AMOUNT); players[msg.sender].total_rewards += reward; - daoToken.transferFrom(address(this), msg.sender, reward); + daoToken.transfer(msg.sender, reward); if (boss_to_attack.level == 6) { // User ascends! Moloch is defeated, user can start a new run players[msg.sender].prestige_level += 1; diff --git a/src/RaidGeldUtils.sol b/src/RaidGeldUtils.sol index d92f6f0..5f42d1f 100644 --- a/src/RaidGeldUtils.sol +++ b/src/RaidGeldUtils.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.13; import {Army} from "../src/RaidGeldStructs.sol"; -import {console} from "forge-std/Test.sol"; library RaidGeldUtils { uint256 public constant PRECISION = 10000; @@ -98,7 +97,7 @@ library RaidGeldUtils { // TODO: This could as well just be pre-calculated uint256 cumulativeChance = getBossCumulativeChance(bossLevel); // 0 - 1e18 range uint256 rewardMultiplier = ((2 * (1e18 - cumulativeChance)) ** 2) / 1e18; - return (baseReward * rewardMultiplier); + return (baseReward * rewardMultiplier) / 1e18; } // Calculates whether user survives the fight @@ -130,7 +129,8 @@ library RaidGeldUtils { // TODO: Implement actual randomness function random(uint256 prevrandao, uint256 min, uint256 max) internal pure returns (uint256) { // returns 0 - 100 - require(max >= min, "Max must be greater than or equal to min"); + require(max > min, "Max must be greater than min"); + require(max < type(uint256).max, "Dont use largest possible uint"); uint256 range = max - min + 1; return min + (uint256(keccak256(abi.encodePacked(prevrandao))) % range); } diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol index 2bb65bd..62ff7e6 100644 --- a/test/RaidGeld.t.sol +++ b/test/RaidGeld.t.sol @@ -134,38 +134,7 @@ contract raid_geldTest is Test, Constants { 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 { + function test_03_is_registered() public { bool is_registered = raid_geld.isRegistered(player1); assertEq(is_registered, false); vm.startPrank(player1); @@ -179,7 +148,7 @@ contract raid_geldTest is Test, Constants { assertEq(is_registered, true); } - function test_06_add_unit() public { + function test_04_add_unit() public { vm.startPrank(player1); // Making sure event is emitted when player is registered @@ -229,7 +198,7 @@ contract raid_geldTest is Test, Constants { assertLt(income_per_sec, new_income_per_sec); } - function test_07_raid() public { + function test_05_raid() public { // Let some time pass so we dont start at block timestamp 0 vm.warp(120); @@ -286,13 +255,13 @@ contract raid_geldTest is Test, Constants { assertLt(last_raided_at, last_raided_at_2); } - function test_08_attack_boss() public { + function test_06_attack_boss() public { // Let some time pass so we dont start at block timestamp 0 vm.warp(120); // Register player 1 vm.startPrank(player1); - registerPlayer(); + registerPlayerWithDaoToken(); raid_geld.addUnit(0, 1); Boss memory boss = raid_geld.getBoss(player1); diff --git a/test/RaidGeldUtils.t.sol b/test/RaidGeldUtils.t.sol index 7502ba9..bedb1f4 100644 --- a/test/RaidGeldUtils.t.sol +++ b/test/RaidGeldUtils.t.sol @@ -88,7 +88,33 @@ contract raid_geldTest is Test { } } - function test_2_calculateBossFight_probabilities() public { + function test_21_random(uint256 seed, uint256 min, uint256 max) public pure { + vm.assume(min < max); + vm.assume(max < type(uint256).max); + uint256 random = RaidGeldUtils.random(seed, min, max); + vm.assertTrue(random >= min && random <= max, "random() fell outside its range"); + } + + function test_22_random_range(uint256 min, uint256 max) public { + vm.assume(max > min); + vm.assume(max - min < 100); + vm.assume(max < type(uint256).max); + uint256 range = max - min + 1; + bool[] memory seen = new bool[](range); + uint256 count = 0; + for (uint256 i = 0; i < 100000; i++) { + uint256 result = RaidGeldUtils.random(block.prevrandao + i, min, max); + uint256 index = result - min; + if (!seen[index]) { + seen[index] = true; + count++; + } + if (count == range) break; + } + assertEq(count, range, "Not all values in the interval were generated"); + } + + function test_3_calculateBossFight_probabilities() public { uint256[7] memory probabilities = [uint256(99), uint256(89), uint256(80), uint256(70), uint256(62), uint256(51), uint256(40)]; uint256 totalRuns = 1000;