Last active
February 7, 2022 07:39
-
-
Save danielkhoo/36463ad69a52a1eee5b9ed3eff4d042a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.8.0 <0.9.0; | |
//SPDX-License-Identifier: MIT | |
contract RockPaperScissors { | |
// 4 Game Phases: Join, Commit, Reveal, Result | |
enum GameState { | |
JoinPhase, | |
CommitPhase, | |
RevealPhase, | |
ResultPhase | |
} | |
// 3 Game Results: P1 win, P2 win, draw | |
enum GameResult { | |
P1Win, | |
P2Win, | |
Draw | |
} | |
// Holds the game data for a single match | |
struct GameStruct { | |
bool initialized; | |
address player1; | |
address player2; | |
GameState gameState; | |
bytes32 commit1; | |
bytes32 commit2; | |
bytes32 reveal1; | |
bytes32 reveal2; | |
uint256 revealDeadline; | |
GameResult gameResult; | |
} | |
// Maps Game address => Game data | |
mapping(address => GameStruct) public games; | |
// Maps Player address to their current 'active' game | |
mapping(address => address) public activeGame; | |
/** | |
* @notice Modifier that checks game is initialized, the sender is player 1/2 | |
* and that the game state to be in the expected phase | |
* @param gameHash - the game code | |
* @param gameState - the three possible game phases | |
*/ | |
modifier validGameState(address gameHash, GameState gameState) { | |
// Check that the game exists | |
require( | |
games[gameHash].initialized == true, | |
"Game code does not exist" | |
); | |
// Check player is either player 1 or player 2 | |
require( | |
games[gameHash].player1 == msg.sender || | |
games[gameHash].player2 == msg.sender, | |
"Player not in this game" | |
); | |
// Check that game is in expected state | |
require( | |
games[gameHash].gameState == gameState, | |
"Game not in correct phase" | |
); | |
_; | |
} | |
/** | |
* @notice Creates a new game, generating a game hash and setting player 1 as sender | |
* and player 2 as the address provided | |
* @param otherPlayer - address for player 2 | |
*/ | |
function createGame(address otherPlayer) public returns (address) { | |
// | |
address gameHash = generateGameHash(); | |
require( | |
!games[gameHash].initialized, | |
"Game code already exists, please try again" | |
); | |
// Check other player isn't host | |
require( | |
msg.sender != otherPlayer, | |
"Invited player must have a different address" | |
); | |
games[gameHash].initialized = true; | |
games[gameHash].player1 = msg.sender; | |
games[gameHash].player2 = otherPlayer; | |
// Set game phase to initial join phase | |
games[gameHash].gameState = GameState.JoinPhase; | |
// Set P1 active game to game hash | |
activeGame[msg.sender] = gameHash; | |
// Return the game hash so it can be shared | |
return gameHash; | |
} | |
/** | |
* @notice Function for player 2 to join a game with the game address | |
* @param gameHash - game address shared by player 1 | |
*/ | |
function joinGame(address gameHash) | |
public | |
validGameState(gameHash, GameState.JoinPhase) | |
{ | |
// Set game phase to commit phase | |
games[gameHash].gameState = GameState.CommitPhase; | |
// Set P2 active game to game hash | |
activeGame[msg.sender] = gameHash; | |
} | |
/// @notice Util Functions for generating hashes, computing winners and fetching data | |
function generateGameHash() public view returns (address) { | |
bytes32 prevHash = blockhash(block.number - 1); | |
// Game hash is a pseudo-randomly generated address from last blockhash + p1 | |
return | |
address(bytes20(keccak256(abi.encodePacked(prevHash, msg.sender)))); | |
} | |
/** | |
* @notice Fetches the game data of the player's active game | |
* @param player - address of player | |
*/ | |
function getActiveGameData(address player) | |
public | |
view | |
returns (GameStruct memory) | |
{ | |
// Get the game hash from active game mapping | |
address gameHash = activeGame[player]; | |
return games[gameHash]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment