A decentralized spinning board game deployed on Base Chain Mainnet where players spin to win!
- Board Range: Numbers 1-10
- Players: Minimum 2, Maximum 10 per game
- Entry Fee: 0.00002 ETH per player
- Winner: Player with the highest spin number wins
- Prize Distribution:
- 50% goes to the winner
- 50% goes to the game creator (contract owner)
npm installCopy the example environment file and fill in your values:
cp .env.example .envEdit .env with your configuration:
DEPLOYER_PRIVATE_KEY: Your deployer wallet private keyBASE_RPC_URL: Base Mainnet RPC URLBASESCAN_API_KEY: For contract verification
Generate 10 wallets for testing:
npx hardhat run scripts/generateWallets.jsCopy the generated private keys to your .env file.
Each wallet needs at least:
- 0.00002 ETH (entry fee)
- ~0.00008 ETH (gas fees)
- Recommended: 0.0001 ETH per wallet
npm run deploy:basenpm run deploy:baseSepoliaAfter deployment, copy the contract address to your .env file:
SPINDBOARD_CONTRACT_ADDRESS=0x...
Run the test suite:
npm testThe interaction script allows you to play the game with multiple wallets.
npx hardhat run scripts/interact.js --network base -- --action=status# Join with 3 players (default)
npx hardhat run scripts/interact.js --network base -- --action=join --players=3
# Join with 5 players
npx hardhat run scripts/interact.js --network base -- --action=join --players=5npx hardhat run scripts/interact.js --network base -- --action=spin# Run demo with 3 players
npx hardhat run scripts/interact.js --network base -- --action=demo --players=3npx hardhat run scripts/interact.js --network base -- --action=results --gameId=1| Function | Description |
|---|---|
joinGame() |
Join the current game (requires 0.00002 ETH) |
spin() |
Spin the board to get your number |
| Function | Description |
|---|---|
getCurrentGame() |
Get current game details |
getGame(gameId) |
Get specific game details |
getGamePlayers(gameId) |
Get all players in a game |
getPlayerInfo(address) |
Get player status in current game |
canStartSpinning() |
Check if game can start |
playersNeededToStart() |
Number of players needed |
availableSlots() |
Open slots in current game |
getStats() |
Get contract statistics |
| Function | Description |
|---|---|
forceCompleteGame() |
Force complete a stuck game |
emergencyWithdraw() |
Emergency withdrawal |
| Event | Description |
|---|---|
GameCreated |
New game created |
PlayerJoined |
Player joined a game |
PlayerSpun |
Player completed their spin |
GameCompleted |
Game finished with winner |
WinnerPaid |
Winner received prize |
CreatorFeePaid |
Creator received fee |
- Randomness: The contract uses
block.prevrandaofor randomness. For higher stakes, consider using Chainlink VRF. - Reentrancy: Protected with OpenZeppelin's
ReentrancyGuard. - Access Control: Admin functions protected with
Ownable.
| Network | Chain ID | RPC URL |
|---|---|---|
| Base Mainnet | 8453 | https://mainnet.base.org |
| Base Sepolia | 84532 | https://sepolia.base.org |
MIT