Connected wagmi to contract, changed Geld -> RaidGeld and minor contract changes
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
bcc79beed1
commit
bbf2a1874f
7
.gas-snapshot
Normal file
7
.gas-snapshot
Normal file
@ -0,0 +1,7 @@
|
||||
GeldTest:test_00_no_fallback() (gas: 16801)
|
||||
GeldTest:test_01_no_receive() (gas: 17274)
|
||||
GeldTest:test_02_registration() (gas: 160943)
|
||||
GeldTest:test_03_fundsCanBeWithdrawn() (gas: 161313)
|
||||
GeldTest:test_04_onlyOwnerCanWithdraw() (gas: 147226)
|
||||
GeldTest:test_05_raid() (gas: 184786)
|
||||
GeldTest:test_06_is_registered() (gas: 148625)
|
||||
2
app/package-lock.json
generated
2
app/package-lock.json
generated
@ -14,7 +14,7 @@
|
||||
"next": "^14.2.10",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"viem": "2.17.0",
|
||||
"viem": "^2.17.0",
|
||||
"wagmi": "^2.12.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"next": "^14.2.10",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"viem": "2.17.0",
|
||||
"viem": "^2.17.0",
|
||||
"wagmi": "^2.12.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import React from "react"
|
||||
import styles from '../styles/Background.module.css';
|
||||
import Tower from "./Tower";
|
||||
|
||||
const Background = () => {
|
||||
return <div className={styles.frame}>
|
||||
<div className={`${styles.air} ${styles.background_asset}`} />
|
||||
<div className={`${styles.clouds_small} ${styles.background_asset}`} />
|
||||
<div className={`${styles.clouds_large} ${styles.background_asset}`} />
|
||||
<div className={`${styles.tower} ${styles.background_asset}`} />
|
||||
<Tower />
|
||||
<div className={`${styles.mountains} ${styles.background_asset}`} />
|
||||
<div className={`${styles.village} ${styles.background_asset}`} />
|
||||
<div className={`${styles.tavern_keeper} ${styles.person} ${styles.static_keeper}`} />
|
||||
|
||||
@ -1,12 +1,57 @@
|
||||
import React from "react"
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import styles from "../styles/Header.module.css"
|
||||
import { usePlayer } from "../providers/PlayerProvider";
|
||||
import { useAccount } from 'wagmi';
|
||||
import dynamic from "next/dynamic";
|
||||
import { formatUnits } from "viem";
|
||||
|
||||
const Header = () => {
|
||||
return <header className={styles.header}>
|
||||
<h1 className={styles.title}>mico's Slayery</h1>
|
||||
<p className={styles.counter}>1213123 million GELD</p>
|
||||
<p className={styles.counter_per_seconds}>per second: 55.000 thousand</p>
|
||||
const { isConnected } = useAccount();
|
||||
const { isRegistered, register, balance } = usePlayer();
|
||||
const [count, setCount] = useState("0")
|
||||
const [perSecond, setPerSecond] = useState("0")
|
||||
|
||||
useEffect(() => {
|
||||
if (balance != null) {
|
||||
setCount(formatUnits(balance, 4))
|
||||
}
|
||||
}, [balance])
|
||||
|
||||
const title = useMemo(() => {
|
||||
return isRegistered ? `SLAY THE MOLOCH` :
|
||||
!isConnected ? "Connect your wallet traveler ☝️ and then ..." :
|
||||
"Click here to start 😈"
|
||||
}, [isConnected, isRegistered])
|
||||
|
||||
const subtitle = useMemo(() => {
|
||||
if (isRegistered) {
|
||||
return <p className={styles.counter}>{count} GELD</p>
|
||||
} else {
|
||||
return <p className={styles.counter}>SLAY THE MOLOCH</p>
|
||||
}
|
||||
}, [isRegistered, count])
|
||||
|
||||
const perSecondParagraph = useMemo(() => {
|
||||
return (isRegistered) ?
|
||||
<p className={styles.counter_per_seconds}>per second: {perSecond}</p>
|
||||
: null
|
||||
}, [isRegistered, perSecond])
|
||||
|
||||
const onRegister = useCallback(() => {
|
||||
if (isRegistered) return
|
||||
register();
|
||||
}, [isRegistered, register])
|
||||
|
||||
return <header onClick={onRegister} className={styles.header}>
|
||||
{count.current} {balance}
|
||||
<h1 className={styles.title}>{title}</h1>
|
||||
{subtitle}
|
||||
{perSecondParagraph}
|
||||
</header>
|
||||
}
|
||||
|
||||
export default Header
|
||||
// export default Header
|
||||
|
||||
export default dynamic(() => Promise.resolve(Header), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
7
app/src/components/Tower.tsx
Normal file
7
app/src/components/Tower.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import styles from '../styles/Background.module.css';
|
||||
|
||||
const Tower = () => {
|
||||
return <div className={`${styles.tower} ${styles.background_asset}`} />
|
||||
}
|
||||
|
||||
export default Tower
|
||||
@ -6,6 +6,7 @@ import { WagmiProvider } from 'wagmi';
|
||||
import { RainbowKitProvider, midnightTheme } from '@rainbow-me/rainbowkit';
|
||||
import { config } from '../wagmi';
|
||||
import { Texturina } from 'next/font/google'
|
||||
import PlayerProvider from '../providers/PlayerProvider';
|
||||
|
||||
const client = new QueryClient();
|
||||
const font = Texturina({ weight: ['400'], subsets: ["latin"] })
|
||||
@ -23,7 +24,9 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||
font-family: ${font.style.fontFamily};
|
||||
}
|
||||
`}</style>
|
||||
<PlayerProvider>
|
||||
<Component {...pageProps} />
|
||||
</PlayerProvider>
|
||||
</RainbowKitProvider>
|
||||
</QueryClientProvider>
|
||||
</WagmiProvider>
|
||||
|
||||
91
app/src/providers/PlayerProvider.tsx
Normal file
91
app/src/providers/PlayerProvider.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import React, { createContext, ReactNode, useCallback, useContext } from 'react'
|
||||
import { useAccount, useReadContract, useWriteContract } from 'wagmi'
|
||||
import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json"
|
||||
import { parseEther } from 'viem'
|
||||
|
||||
const contractAddress = "0xbd06B0878888bf4c6895704fa603a5ADf7e65c66"
|
||||
const abi = contractAbi.abi
|
||||
|
||||
export interface PlayerContextType {
|
||||
isRegistered: boolean,
|
||||
user: null | string,
|
||||
balance: bigint,
|
||||
register: () => void;
|
||||
}
|
||||
|
||||
const PlayerContext = createContext<PlayerContextType>({
|
||||
isRegistered: false,
|
||||
user: null,
|
||||
balance: BigInt(0),
|
||||
register: () => { },
|
||||
});
|
||||
|
||||
const PlayerProvider = ({ children }: { children: ReactNode }) => {
|
||||
const { address, isConnected } = useAccount();
|
||||
const { writeContract } = useWriteContract();
|
||||
const { data: isRegistered } = useReadContract({
|
||||
address: contractAddress,
|
||||
abi,
|
||||
functionName: 'isRegistered',
|
||||
args: [address],
|
||||
query: {
|
||||
enabled: isConnected,
|
||||
refetchInterval: 5,
|
||||
}
|
||||
});
|
||||
|
||||
console.log("IS REGISTERED", isRegistered, address)
|
||||
|
||||
const { data: balance, error, refetch: refetchBalance } = useReadContract({
|
||||
address: contractAddress,
|
||||
abi,
|
||||
functionName: 'balanceOf',
|
||||
args: [address],
|
||||
query: {
|
||||
refetchInterval: 5,
|
||||
enabled: isConnected
|
||||
}
|
||||
});
|
||||
|
||||
console.log(balance, error)
|
||||
|
||||
const { data: playerData, refetch: refetchPlayerData } = useReadContract({
|
||||
address: contractAddress,
|
||||
abi,
|
||||
functionName: 'getPlayer',
|
||||
args: [address],
|
||||
query: {
|
||||
enabled: isConnected,
|
||||
refetchInterval: 15
|
||||
}
|
||||
});
|
||||
|
||||
const register = useCallback(() => {
|
||||
console.log("START")
|
||||
const a = writeContract({
|
||||
abi,
|
||||
address: contractAddress,
|
||||
functionName: 'register',
|
||||
value: parseEther("0.0005"),
|
||||
})
|
||||
console.log(a)
|
||||
}, [writeContract])
|
||||
|
||||
return (
|
||||
<PlayerContext.Provider value={{
|
||||
isRegistered: isRegistered as boolean,
|
||||
user: null,
|
||||
balance: balance as bigint,
|
||||
register
|
||||
}}>
|
||||
{children}
|
||||
</PlayerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const usePlayer = () => {
|
||||
return useContext(PlayerContext);
|
||||
}
|
||||
|
||||
export default PlayerProvider
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
height: 240px;
|
||||
top: 200px;
|
||||
animation: thunder_hue_hard 12s linear infinite;
|
||||
transition: all ease-in-out 0.2s;
|
||||
transition: all ease-in-out 0.05s;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
transform: scale(1.05, 1.1);
|
||||
|
||||
@ -2,16 +2,16 @@
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {Geld} from "../src/Geld.sol";
|
||||
import {RaidGeld} from "../src/RaidGeld.sol";
|
||||
|
||||
contract GeldScript is Script {
|
||||
Geld public geld;
|
||||
contract RaidGeldScript is Script {
|
||||
RaidGeld public raidgeld;
|
||||
|
||||
function setUp() public {}
|
||||
|
||||
function run() public {
|
||||
vm.startBroadcast();
|
||||
geld = new Geld();
|
||||
raidgeld = new RaidGeld();
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@ struct Player {
|
||||
uint256 last_raided_at;
|
||||
}
|
||||
|
||||
contract Geld is ERC20, Ownable {
|
||||
contract RaidGeld is ERC20, Ownable {
|
||||
uint8 constant DECIMALS = 4;
|
||||
uint256 public constant BUY_IN_AMOUNT = 0.0005 ether;
|
||||
uint256 public constant INITIAL_GELD = 50 * 10 ** DECIMALS;
|
||||
@ -37,7 +37,7 @@ contract Geld is ERC20, Ownable {
|
||||
_;
|
||||
}
|
||||
|
||||
constructor() ERC20("Geld", "GELD") Ownable(msg.sender) {}
|
||||
constructor() ERC20("Raid Geld", "GELD") Ownable(msg.sender) {}
|
||||
|
||||
// This effectively registers the user
|
||||
function register() external payable {
|
||||
@ -83,13 +83,18 @@ contract Geld is ERC20, Ownable {
|
||||
}
|
||||
|
||||
// Function to get Player struct
|
||||
function getPlayer() public view onlyPlayer returns (Player memory) {
|
||||
return players[msg.sender];
|
||||
function getPlayer(address addr) public view onlyPlayer returns (Player memory) {
|
||||
return players[addr];
|
||||
}
|
||||
|
||||
// Function to get Army struct
|
||||
function getArmy() public view onlyPlayer returns (Army memory) {
|
||||
return armies[msg.sender];
|
||||
function getArmy(address addr) public view onlyPlayer returns (Army memory) {
|
||||
return armies[addr];
|
||||
}
|
||||
|
||||
// Quick fn to check if user is registered
|
||||
function isRegistered(address addr) public view returns (bool) {
|
||||
return players[addr].created_at != 0;
|
||||
}
|
||||
|
||||
receive() external payable {
|
||||
@ -2,10 +2,10 @@
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Test, console} from "forge-std/Test.sol";
|
||||
import {Geld, Army, Player} from "../src/Geld.sol";
|
||||
import {RaidGeld, Army, Player} from "../src/RaidGeld.sol";
|
||||
|
||||
contract GeldTest is Test {
|
||||
Geld public geld;
|
||||
contract raid_geldTest is Test {
|
||||
RaidGeld public raid_geld;
|
||||
address public player1;
|
||||
address public player2;
|
||||
address public owner;
|
||||
@ -18,47 +18,47 @@ contract GeldTest is Test {
|
||||
vm.deal(player1, 10 ether);
|
||||
vm.deal(player2, 10 ether);
|
||||
vm.prank(owner);
|
||||
geld = new Geld();
|
||||
raid_geld = new RaidGeld();
|
||||
}
|
||||
|
||||
function registerPlayer() private {
|
||||
geld.register{value: geld.BUY_IN_AMOUNT()}();
|
||||
raid_geld.register{value: raid_geld.BUY_IN_AMOUNT()}();
|
||||
}
|
||||
|
||||
function test_00_no_fallback() public {
|
||||
vm.expectRevert();
|
||||
// Send Ether with some data to trigger fallback
|
||||
address(geld).call{value: 0.1 ether}("0x1234");
|
||||
address(raid_geld).call{value: 0.1 ether}("0x1234");
|
||||
}
|
||||
|
||||
function test_01_no_receive() public {
|
||||
vm.startPrank(player1);
|
||||
vm.expectRevert();
|
||||
payable(address(geld)).transfer(0.1 ether);
|
||||
payable(address(raid_geld)).transfer(0.1 ether);
|
||||
}
|
||||
|
||||
function test_02_registration() public {
|
||||
vm.startPrank(player1);
|
||||
|
||||
uint256 initialBalance = address(geld).balance;
|
||||
uint256 initialTotalMinted = geld.total_minted();
|
||||
uint256 initialBalance = address(raid_geld).balance;
|
||||
uint256 initialTotalMinted = raid_geld.total_minted();
|
||||
|
||||
// Send registration fee ETH to the contract
|
||||
registerPlayer();
|
||||
|
||||
// Check that initial GELD is received by the player
|
||||
assertEq(geld.balanceOf(player1), geld.INITIAL_GELD());
|
||||
// Check that initialraid_geld.is received by the player
|
||||
assertEq(raid_geld.balanceOf(player1), raid_geld.INITIAL_GELD());
|
||||
|
||||
// Verify the contract balance is updated
|
||||
assertEq(address(geld).balance, initialBalance + geld.BUY_IN_AMOUNT());
|
||||
assertEq(address(raid_geld).balance, initialBalance + raid_geld.BUY_IN_AMOUNT());
|
||||
|
||||
// Verify player is set initially
|
||||
Player memory player = geld.getPlayer();
|
||||
assertEq(player.total_minted, geld.INITIAL_GELD());
|
||||
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, 0);
|
||||
|
||||
Army memory army = geld.getArmy();
|
||||
Army memory army = raid_geld.getArmy(player1);
|
||||
|
||||
assertEq(army.moloch_denier.level, 0);
|
||||
assertEq(army.apprentice.level, 0);
|
||||
@ -66,7 +66,7 @@ contract GeldTest is Test {
|
||||
assertEq(army.champion.level, 0);
|
||||
|
||||
// Verify that total_minted is updated
|
||||
assertEq(geld.total_minted(), initialTotalMinted + geld.INITIAL_GELD());
|
||||
assertEq(raid_geld.total_minted(), initialTotalMinted + raid_geld.INITIAL_GELD());
|
||||
}
|
||||
|
||||
function test_03_fundsCanBeWithdrawn() public {
|
||||
@ -78,14 +78,14 @@ contract GeldTest is Test {
|
||||
|
||||
// Switch back to owner and withdraw funds
|
||||
vm.startPrank(owner);
|
||||
geld.withdraw();
|
||||
raid_geld.withdraw();
|
||||
uint256 newBalance = owner.balance;
|
||||
uint256 newContractBalance = address(geld).balance;
|
||||
uint256 newContractBalance = address(raid_geld).balance;
|
||||
|
||||
// contract balance should be empty
|
||||
assertEq(newContractBalance, 0);
|
||||
// owner should have the extra funds
|
||||
assertEq(newBalance, initialBalance + geld.BUY_IN_AMOUNT());
|
||||
assertEq(newBalance, initialBalance + raid_geld.BUY_IN_AMOUNT());
|
||||
}
|
||||
|
||||
function test_04_onlyOwnerCanWithdraw() public {
|
||||
@ -95,7 +95,7 @@ contract GeldTest is Test {
|
||||
|
||||
// attempt to withdraw with player 1, it should fail
|
||||
vm.expectRevert();
|
||||
geld.withdraw();
|
||||
raid_geld.withdraw();
|
||||
}
|
||||
|
||||
function test_05_raid() public {
|
||||
@ -106,30 +106,39 @@ contract GeldTest is Test {
|
||||
vm.startPrank(player1);
|
||||
registerPlayer();
|
||||
|
||||
uint256 balance = geld.balanceOf(player1);
|
||||
uint256 total_minted = geld.total_minted();
|
||||
uint256 balance = raid_geld.balanceOf(player1);
|
||||
uint256 total_minted = raid_geld.total_minted();
|
||||
|
||||
// Trigger raid funds minting
|
||||
geld.raid();
|
||||
raid_geld.raid();
|
||||
|
||||
// New balance should be larger
|
||||
uint256 newBalance = geld.balanceOf(player1);
|
||||
uint256 newTotalMinted = geld.total_minted();
|
||||
uint256 newBalance = raid_geld.balanceOf(player1);
|
||||
uint256 newTotalMinted = raid_geld.total_minted();
|
||||
assertLt(balance, newBalance);
|
||||
assertLt(total_minted, newTotalMinted);
|
||||
|
||||
// Expect fail if we raid again, we need to wait a bit
|
||||
vm.expectRevert();
|
||||
geld.raid();
|
||||
raid_geld.raid();
|
||||
|
||||
// After wait time passes raid should work again
|
||||
vm.warp(block.timestamp + geld.RAID_WAIT());
|
||||
geld.raid();
|
||||
vm.warp(block.timestamp + raid_geld.RAID_WAIT());
|
||||
raid_geld.raid();
|
||||
|
||||
// Balance should reflect that
|
||||
uint256 newestBalance = geld.balanceOf(player1);
|
||||
uint256 newestTotalMinted = geld.total_minted();
|
||||
uint256 newestBalance = raid_geld.balanceOf(player1);
|
||||
uint256 newestTotalMinted = raid_geld.total_minted();
|
||||
assertLt(newTotalMinted, newestTotalMinted);
|
||||
assertLt(newBalance, newestBalance);
|
||||
}
|
||||
|
||||
function test_06_is_registered() public {
|
||||
bool is_registered = raid_geld.isRegistered(player1);
|
||||
assertEq(is_registered, false);
|
||||
vm.startPrank(player1);
|
||||
registerPlayer();
|
||||
is_registered = raid_geld.isRegistered(player1);
|
||||
assertEq(is_registered, true);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user