Skip to content

Instantly share code, notes, and snippets.

@yoshirahh
Created April 10, 2019 22:03
Show Gist options
  • Save yoshirahh/dcf6882cd127c1d8e33a3b95ce022885 to your computer and use it in GitHub Desktop.
Save yoshirahh/dcf6882cd127c1d8e33a3b95ce022885 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.6+commit.b259423e.js&optimize=false&gist=
pragma solidity 0.5.6;
contract RPSs {
address payable private _player1;
address payable private _player2;
uint _stake;
bytes32 _p1Move;
string _p2Move;
uint _p1Timer;
uint _p2Timer;
function RPS() public payable {
// 1 (a) Constructor that sets creator as player 1.
_player1 = msg.sender;
}
function p1_commit(bytes32 _commitment) public payable {
// (b) only callable by player 1
require(msg.sender == _player1);
// (d) amount must be strictly greater than 0.
require(msg.value > 0 ether);
_p1Move = _commitment;
_p1Timer = block.timestamp;
// (c) the amount of ethereum sent by player 1 defines the stake of the game
_stake = msg.value;
}
function p2_join(string calldata _play) external payable {
// (a) should do nothing if there are already two players
if(_player2 == address(0) && _player1 != msg.sender) {
// (b) play is either “Rock”, “Paper”, or “Scissors”
require(valid_play(_play));
// (c) must be at least enough ethereum as the stake of the game.
require(msg.value >= _stake);
// (d) whoever sends the message is player 2, assuming all the above hold
_player2 = msg.sender;
_p2Move = _play;
_p2Timer = block.timestamp;
}
}
function p1_reveal(string calldata _play, string calldata _salt) external {
// (c) called by player 1 only
require(msg.sender == _player1);
// (a) play must be either “Rock”, “Paper”, or “Scissors”
require(valid_play(_play));
// (b) keccak256( play, salt) should be equal to the commitment provided when the contract was created
require(salt_string(_play, _salt) == _p1Move);
// (d) if no other player has joined, cancel the contract, refunding the stored ether to player 1.
if(_player2 == address(0)) {
selfdestruct(_player1);
} else {
uint8 winner = check_moves(_play, _p2Move);
// (e) if the game is a tie, erase both players’ moves (but not player identities!)
if(winner == 0) {
_p1Move = "";
_p2Move = "";
} else {
// (f) If not a tie, kill the contract and give the balance to player that won.
if(winner == 1) selfdestruct(_player1);
else selfdestruct(_player2);
}
}
// (g) if player 2 has not made a move in 30 seconds, cancel the contract, giving all stored ether to player 1.
if((block.timestamp - _p2Timer) > 30) selfdestruct(_player2);
}
function p2_payout() external {
// (a) if it’s been at least 30 seconds since player 1 has made a move, kill the contract and send the balance to player 2
if((block.timestamp - _p1Timer) > 30) selfdestruct(_player2);
}
function p1_replay(bytes32 _commitment) external {
// (a) player 1 only
require(msg.sender == _player1);
// (b) only if player 1 has no valid play stored (because a tie was declared)
require(_p1Move == "");
// (c) sets player 1’s commitment to commitment
_p1Move = _commitment;
_p1Timer = block.timestamp;
}
function p2_replay(string calldata _play) external {
// (a) player 2 only
require(msg.sender == _player2);
// (b) only if player 2 has no valid play stored (because a tie was declared)
require(str_eq(_p2Move, ""));
// (c) stores play as player 2’s play (should be “Rock”, “Paper”, or “Scissors”)
require(valid_play(_play));
_p2Move = _play;
_p2Timer = block.timestamp;
}
function salt_string(string memory _str, string memory _salt) public pure returns (bytes32){
return keccak256(abi.encodePacked(_str, _salt));
}
function str_eq (string memory a, string memory b) private pure returns(bool) {
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
}
function valid_play(string memory _play) private pure returns (bool) {
return str_eq(_play, "Rock") || str_eq(_play, "Paper") || str_eq(_play, "Scissors");
}
function check_moves(string memory _p1, string memory _p2) private pure returns (uint8) {
if(str_eq(_p1, _p2)) {
return 0;
} else if(str_eq(_p1, "Rock")) {
if (str_eq(_p2, "Scissors")) return 1;
else return 2;
} else if(str_eq(_p1, "Paper")) {
if (str_eq(_p2, "Rock")) return 1;
else return 2;
} else if(str_eq(_p1, "Scissors")) {
if (str_eq(_p2, "Paper")) return 1;
else return 2;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment