Mining or raiding mechanic works now
Some checks are pending
CI / Foundry project (push) Waiting to run

This commit is contained in:
mic0 2024-10-22 14:46:50 +02:00
parent bbf2a1874f
commit ec10cb11cc
Signed by: mico
GPG Key ID: A3F8023524CF1C8D
7 changed files with 55 additions and 80 deletions

View File

@ -1,66 +1,15 @@
## Foundry # SLAY THE MOLOCH
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** Idle game & shitcoin advanture dedicated to cohort VII of Raid Guild.
Foundry consists of: ## Set up
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). 1. Run `anvil` to setup local RPC
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
## Documentation 2. Deploy contract
https://book.getfoundry.sh/ Either use `./deploy_contract.sh` script (!! change contract values and set private key to $DEV_PRIVATE_KEY for it to work) or call those things by hand.
## Usage 3. Local development requires mining blocks by hand
### Build 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
```shell
$ forge build
```
### Test
```shell
$ forge test
```
### Format
```shell
$ forge fmt
```
### Gas Snapshots
```shell
$ forge snapshot
```
### Anvil
```shell
$ anvil
```
### Deploy
```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```
### Cast
```shell
$ cast <subcommand>
```
### Help
```shell
$ forge --help
$ anvil --help
$ cast --help
```

View File

@ -1,7 +1,9 @@
import { usePlayer } from '../providers/PlayerProvider';
import styles from '../styles/Background.module.css'; import styles from '../styles/Background.module.css';
const Tower = () => { const Tower = () => {
return <div className={`${styles.tower} ${styles.background_asset}`} /> const { raid } = usePlayer();
return <div onClick={raid} className={`${styles.tower} ${styles.background_asset}`} />
} }
export default Tower export default Tower

View File

@ -9,7 +9,7 @@ const Home: NextPage = () => {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<Head> <Head>
<title>Slay Moloch</title> <title>Slay The Moloch</title>
<meta <meta
content="Slay the moloch, earn shiny GELD" content="Slay the moloch, earn shiny GELD"
name="Slay the moloch, earn shiny GELD" name="Slay the moloch, earn shiny GELD"

View File

@ -1,4 +1,4 @@
import React, { createContext, ReactNode, useCallback, useContext } from 'react' import React, { createContext, ReactNode, useCallback, useContext, useEffect } from 'react'
import { useAccount, useReadContract, useWriteContract } from 'wagmi' import { useAccount, useReadContract, useWriteContract } from 'wagmi'
import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json" import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json"
import { parseEther } from 'viem' import { parseEther } from 'viem'
@ -11,6 +11,7 @@ export interface PlayerContextType {
user: null | string, user: null | string,
balance: bigint, balance: bigint,
register: () => void; register: () => void;
raid: () => void
} }
const PlayerContext = createContext<PlayerContextType>({ const PlayerContext = createContext<PlayerContextType>({
@ -18,11 +19,14 @@ const PlayerContext = createContext<PlayerContextType>({
user: null, user: null,
balance: BigInt(0), balance: BigInt(0),
register: () => { }, register: () => { },
raid: () => { },
}); });
const PlayerProvider = ({ children }: { children: ReactNode }) => { const PlayerProvider = ({ children }: { children: ReactNode }) => {
const { address, isConnected } = useAccount(); const { address, isConnected } = useAccount();
const { writeContract } = useWriteContract(); const { writeContract, error } = useWriteContract();
const { data: isRegistered } = useReadContract({ const { data: isRegistered } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
@ -34,9 +38,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
} }
}); });
console.log("IS REGISTERED", isRegistered, address) const { data: balance, } = useReadContract({
const { data: balance, error, refetch: refetchBalance } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'balanceOf', functionName: 'balanceOf',
@ -47,9 +49,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
} }
}); });
console.log(balance, error) const { data: playerData } = useReadContract({
const { data: playerData, refetch: refetchPlayerData } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'getPlayer', functionName: 'getPlayer',
@ -60,15 +60,27 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
} }
}); });
console.log(playerData)
useEffect(() => {
console.warn(error, playerData)
}, [error])
const register = useCallback(() => { const register = useCallback(() => {
console.log("START") writeContract({
const a = writeContract({
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'register', functionName: 'register',
value: parseEther("0.0005"), value: parseEther("0.0005"),
}) })
console.log(a) }, [writeContract])
const raid = useCallback(() => {
writeContract({
abi,
address: contractAddress,
functionName: 'raid',
})
}, [writeContract]) }, [writeContract])
return ( return (
@ -76,7 +88,8 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
isRegistered: isRegistered as boolean, isRegistered: isRegistered as boolean,
user: null, user: null,
balance: balance as bigint, balance: balance as bigint,
register register,
raid
}}> }}>
{children} {children}
</PlayerContext.Provider> </PlayerContext.Provider>

3
deploy_contract.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
cast rpc anvil_setBalance 0x3295CCA2d922c637d35b258fc6c9C7e471803b45 0xDE0B6B3A7640000 --rpc-url http://127.0.0.1:8545
forge script script/RaidGeld.s.sol:RaidGeldScript --rpc-url 127.0.0.1:8545 --broadcast --private-key $DEV_PRIVATE_KEY

View File

@ -4,6 +4,9 @@ pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/access/Ownable.sol";
// DEV
import "forge-std/console.sol";
struct Raider { struct Raider {
uint16 level; uint16 level;
} }
@ -25,7 +28,7 @@ contract RaidGeld is ERC20, Ownable {
uint8 constant DECIMALS = 4; uint8 constant DECIMALS = 4;
uint256 public constant BUY_IN_AMOUNT = 0.0005 ether; uint256 public constant BUY_IN_AMOUNT = 0.0005 ether;
uint256 public constant INITIAL_GELD = 50 * 10 ** DECIMALS; uint256 public constant INITIAL_GELD = 50 * 10 ** DECIMALS;
uint256 public constant RAID_WAIT = 15; uint256 public constant RAID_WAIT = 15 seconds;
uint256 public total_minted = 0; uint256 public total_minted = 0;
mapping(address => Player) private players; mapping(address => Player) private players;
@ -71,24 +74,22 @@ contract RaidGeld is ERC20, Ownable {
// Manual minting for itchy fingers // Manual minting for itchy fingers
function raid() external onlyPlayer { function raid() external onlyPlayer {
require(block.timestamp >= players[msg.sender].last_raided_at + RAID_WAIT, "Tried minting too soon"); require(block.timestamp >= players[msg.sender].last_raided_at + RAID_WAIT, "Tried minting too soon");
// TODO: Make real calculation based on army // TODO: Make real calculation based on army
uint256 new_geld = 50 * 10 ** decimals(); uint256 new_geld = 50 * 10 ** decimals();
_mint(msg.sender, new_geld); _mint(msg.sender, new_geld);
total_minted += new_geld; total_minted += new_geld;
console.log(players[msg.sender].last_raided_at);
players[msg.sender].last_raided_at = block.timestamp; players[msg.sender].last_raided_at = block.timestamp;
console.log(players[msg.sender].last_raided_at);
} }
// Function to get Player struct // Function to get Player struct
function getPlayer(address addr) public view onlyPlayer returns (Player memory) { function getPlayer(address addr) public view returns (Player memory) {
return players[addr]; return players[addr];
} }
// Function to get Army struct // Function to get Army struct
function getArmy(address addr) public view onlyPlayer returns (Army memory) { function getArmy(address addr) public view returns (Army memory) {
return armies[addr]; return armies[addr];
} }

View File

@ -106,6 +106,7 @@ contract raid_geldTest is Test {
vm.startPrank(player1); vm.startPrank(player1);
registerPlayer(); registerPlayer();
uint256 balance = raid_geld.balanceOf(player1); uint256 balance = raid_geld.balanceOf(player1);
uint256 total_minted = raid_geld.total_minted(); uint256 total_minted = raid_geld.total_minted();
@ -115,6 +116,9 @@ contract raid_geldTest is Test {
// New balance should be larger // New balance should be larger
uint256 newBalance = raid_geld.balanceOf(player1); uint256 newBalance = raid_geld.balanceOf(player1);
uint256 newTotalMinted = raid_geld.total_minted(); uint256 newTotalMinted = raid_geld.total_minted();
Player memory player = raid_geld.getPlayer(player1);
uint256 last_raided_at = player.last_raided_at;
assertLt(balance, newBalance); assertLt(balance, newBalance);
assertLt(total_minted, newTotalMinted); assertLt(total_minted, newTotalMinted);
@ -129,8 +133,11 @@ contract raid_geldTest is Test {
// Balance should reflect that // Balance should reflect that
uint256 newestBalance = raid_geld.balanceOf(player1); uint256 newestBalance = raid_geld.balanceOf(player1);
uint256 newestTotalMinted = raid_geld.total_minted(); uint256 newestTotalMinted = raid_geld.total_minted();
player = raid_geld.getPlayer(player1);
uint256 last_raided_at_2 = player.last_raided_at;
assertLt(newTotalMinted, newestTotalMinted); assertLt(newTotalMinted, newestTotalMinted);
assertLt(newBalance, newestBalance); assertLt(newBalance, newestBalance);
assertLt(last_raided_at, last_raided_at_2);
} }
function test_06_is_registered() public { function test_06_is_registered() public {