Mining or raiding mechanic works now
Some checks are pending
CI / Foundry project (push) Waiting to run
Some checks are pending
CI / Foundry project (push) Waiting to run
This commit is contained in:
parent
bbf2a1874f
commit
ec10cb11cc
67
README.md
67
README.md
@ -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
|
|
||||||
```
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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
3
deploy_contract.sh
Executable 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
|
||||||
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user