diff --git a/README.md b/README.md index ead054e..03e38c0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Idle game & shitcoin advanture dedicated to cohort VII of Raid Guild. ## Set up for local DEV ### 1. Run `anvil` to setup local RPC as a fork of base mainnet -anvil --rpc-url +`anvil --rpc-url ` + +you can get a free rpc url by registering with https://alchemy.com and creating and app ### 2. Deploy contract diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol index 30e6350..71cab5a 100644 --- a/src/RaidGeld.sol +++ b/src/RaidGeld.sol @@ -6,10 +6,13 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import {RaidGeldUtils} from "../src/RaidGeldUtils.sol"; import {Army, Player, Raider} from "../src/RaidGeldStructs.sol"; + contract RaidGeld is ERC20, Ownable { uint256 public constant MANTISSA = 1e4; uint256 public constant BUY_IN_AMOUNT = 0.00005 ether; + uint256 public immutable BUY_IN_DAO_TOKEN_AMOUNT; + uint256 public constant INITIAL_GELD = 50 * MANTISSA; uint256 public constant RAID_WAIT = 15 seconds; @@ -28,12 +31,19 @@ contract RaidGeld is ERC20, Ownable { constructor(address _daoToken, address _pool) ERC20("Raid Geld", "GELD") Ownable(msg.sender) { daoToken = ERC20(_daoToken); pool = _pool; + BUY_IN_DAO_TOKEN_AMOUNT = 50 * 10 ** daoToken.decimals(); } // This effectively registers the user function register() external payable { require(players[msg.sender].created_at == 0, "Whoops, player already exists :)"); - require(msg.value == BUY_IN_AMOUNT, "Incorrect buy in amount"); + if (msg.value != 0) { + require(msg.value == BUY_IN_AMOUNT, "Incorrect buy in amount"); + } else { + //@notice this is not safe for arbitrary tokens, which may not follow the interface eg. USDT + //@notice but should be fine for the DAO token + require(daoToken.transferFrom(msg.sender, address(this), BUY_IN_DAO_TOKEN_AMOUNT), "Failed to transfer DAO tokens"); + } // Mint some starting tokens to the player _mint(msg.sender, INITIAL_GELD); diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol index 8a00a7b..aeea89d 100644 --- a/test/RaidGeld.t.sol +++ b/test/RaidGeld.t.sol @@ -2,11 +2,16 @@ 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; @@ -16,14 +21,28 @@ contract raid_geldTest is Test, Constants { owner = address(0x126); player1 = address(0x123); vm.deal(owner, 10 ether); - vm.deal(player1, 10 ether); + fundAccount(player1); vm.prank(owner); raid_geld = new RaidGeld(DAO_TOKEN, POOL); } + function fundAccount(address _acc) private { + vm.deal(_acc, 10 ether); + stdstore + .target(DAO_TOKEN) + .sig("balanceOf(address)") + .with_key(_acc) + .checked_write(100 ether); + + } function registerPlayer() private { raid_geld.register{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(); + } + function test_00_no_fallback() public { vm.expectRevert(); @@ -37,7 +56,7 @@ contract raid_geldTest is Test, Constants { payable(address(raid_geld)).transfer(0.1 ether); } - function test_02_registration() public { + function test_02_1_registrationWithEth() public { vm.startPrank(player1); uint256 initialBalance = address(raid_geld).balance; @@ -65,6 +84,35 @@ contract raid_geldTest is Test, Constants { assertEq(army.champion.level, 0); } + function test_02_2_registrationWithDaoToken() public { + vm.startPrank(player1); + + uint256 initialBalance = raid_geld.daoToken().balanceOf(address(raid_geld)); + + // Send registration fee ETH to the contract + registerPlayerWithDaoToken(); + + // Check that initialraid_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_funds_can_be_withdrawn() public { uint256 initialBalance = owner.balance;