Compare commits

..

No commits in common. "5b0d24ccbae1fe3b97d45ce72e6521ec1bec99fb" and "4bcf23a9acadaaee2844dcdc843dc314feb227e5" have entirely different histories.

6 changed files with 16 additions and 94 deletions

View File

@ -4,10 +4,7 @@ Idle game & shitcoin advanture dedicated to cohort VII of Raid Guild.
## Set up for local DEV ## Set up for local DEV
### 1. Run `anvil` to setup local RPC as a fork of base mainnet ### 1. Run `anvil` to setup local RPC
`anvil --rpc-url <you'r base mainnet rpc url>`
you can get a free rpc url by registering with https://alchemy.com and creating and app
### 2. Deploy contract ### 2. Deploy contract
@ -17,14 +14,14 @@ Either use `./deploy_contract.sh` script (!! change contract values and set priv
Move to `app` dir, install deps via `npm install` and run `npm run dev` to start the dev server. Move to `app` dir, install deps via `npm install` and run `npm run dev` to start the dev server.
#### 3. 1. Point Metamask to Anvil network for local dev #### 3. 1. Run `cast rpc anvil_mine`
#### 3. 2. Change `app/contract_address.ts` to match your program address if needed This is so time gets set on the local chain, otherwise you will start at 0 time and first mint will give you bajillion GELD.
#### 3. 2. Point Metamask to Anvil network for local dev
#### 3. 3. Change `app/contract_address.ts` to match your program address if needed
### 4. Local development requires mining blocks by hand ### 4. Local development requires mining blocks by hand
Call `cast rpc anvil_mine` to mine next block, otherwise it wont ever progress and time "stands still" as far as the game is concerned Call `cast rpc anvil_mine` to mine next block, otherwise it wont ever progress and time "stands still" as far as the game is concerned
### 5. Fork tests
forge test --rpc-url <you'r base mainnet rpc url>

View File

@ -4,16 +4,14 @@ pragma solidity ^0.8.13;
import {Script, console} from "forge-std/Script.sol"; import {Script, console} from "forge-std/Script.sol";
import {RaidGeld} from "../src/RaidGeld.sol"; import {RaidGeld} from "../src/RaidGeld.sol";
import {Constants} from "../src/Constants.sol"; contract RaidGeldScript is Script {
contract RaidGeldScript is Script, Constants {
RaidGeld public raidgeld; RaidGeld public raidgeld;
function setUp() public {} function setUp() public {}
function run() public { function run() public {
vm.startBroadcast(); vm.startBroadcast();
raidgeld = new RaidGeld(DAO_TOKEN, POOL); raidgeld = new RaidGeld();
vm.stopBroadcast(); vm.stopBroadcast();
} }
} }

View File

@ -1,8 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract Constants {
//base addresses
address public constant DAO_TOKEN = 0x11dC980faf34A1D082Ae8A6a883db3A950a3c6E8;
address public constant POOL = 0x27004f6d0c1bB7979367D32Ba9d6DF6d61A18926;
}

View File

@ -6,44 +6,28 @@ import "@openzeppelin/contracts/access/Ownable.sol";
import {RaidGeldUtils} from "../src/RaidGeldUtils.sol"; import {RaidGeldUtils} from "../src/RaidGeldUtils.sol";
import {Army, Player, Raider} from "../src/RaidGeldStructs.sol"; import {Army, Player, Raider} from "../src/RaidGeldStructs.sol";
contract RaidGeld is ERC20, Ownable { contract RaidGeld is ERC20, Ownable {
uint256 public constant MANTISSA = 1e4; uint256 public constant MANTISSA = 1e4;
uint256 public constant BUY_IN_AMOUNT = 0.00005 ether; 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 INITIAL_GELD = 50 * MANTISSA;
uint256 public constant RAID_WAIT = 15 seconds; uint256 public constant RAID_WAIT = 15 seconds;
mapping(address => Player) private players; mapping(address => Player) private players;
mapping(address => Army) private armies; mapping(address => Army) private armies;
ERC20 public daoToken;
address public pool;
// 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");
_; _;
} }
constructor(address _daoToken, address _pool) ERC20("Raid Geld", "GELD") Ownable(msg.sender) { constructor() 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 // This effectively registers the user
function register() external payable { 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 :)");
if (msg.value != 0) {
require(msg.value == BUY_IN_AMOUNT, "Incorrect buy in amount"); 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 some starting tokens to the player
_mint(msg.sender, INITIAL_GELD); _mint(msg.sender, INITIAL_GELD);

View File

@ -2,16 +2,10 @@
pragma solidity ^0.8.13; pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol"; 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 {RaidGeld, Army, Player} from "../src/RaidGeld.sol";
import "../src/RaidGeldUtils.sol"; import "../src/RaidGeldUtils.sol";
import {Constants} from "../src/Constants.sol";
contract raid_geldTest is Test, Constants {
using stdStorage for StdStorage;
contract raid_geldTest is Test {
RaidGeld public raid_geld; RaidGeld public raid_geld;
address public player1; address public player1;
address public player2; address public player2;
@ -21,28 +15,14 @@ contract raid_geldTest is Test, Constants {
owner = address(0x126); owner = address(0x126);
player1 = address(0x123); player1 = address(0x123);
vm.deal(owner, 10 ether); vm.deal(owner, 10 ether);
fundAccount(player1); vm.deal(player1, 10 ether);
vm.prank(owner); vm.prank(owner);
raid_geld = new RaidGeld(DAO_TOKEN, POOL); raid_geld = new RaidGeld();
}
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 { function registerPlayer() private {
raid_geld.register{value: raid_geld.BUY_IN_AMOUNT()}(); 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 { function test_00_no_fallback() public {
vm.expectRevert(); vm.expectRevert();
@ -56,7 +36,7 @@ contract raid_geldTest is Test, Constants {
payable(address(raid_geld)).transfer(0.1 ether); payable(address(raid_geld)).transfer(0.1 ether);
} }
function test_02_1_registrationWithEth() public { function test_02_registration() public {
vm.startPrank(player1); vm.startPrank(player1);
uint256 initialBalance = address(raid_geld).balance; uint256 initialBalance = address(raid_geld).balance;
@ -84,35 +64,6 @@ contract raid_geldTest is Test, Constants {
assertEq(army.champion.level, 0); 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 { function test_03_funds_can_be_withdrawn() public {
uint256 initialBalance = owner.balance; uint256 initialBalance = owner.balance;

View File

@ -2,7 +2,7 @@
pragma solidity ^0.8.13; pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol"; import {Test, console} from "forge-std/Test.sol";
import {Army, Raider} from "../src/RaidGeldStructs.sol"; import {Army, Raider} from "../src/RaidGeld.sol";
import "../src/RaidGeldUtils.sol"; import "../src/RaidGeldUtils.sol";
contract raid_geldTest is Test { contract raid_geldTest is Test {