function testPredictNoSalt() public {
RockPaperScissors.Move moveA;
RockPaperScissors.Move moveB;
bytes32 saltA;
bytes32 saltB;
uint256 _gameId = createAndJoinGame();
(,,,,,,,,,,,,,, uint8 scoreBBefore,) = game.games(gameId);
(moveA, saltA) = playerACommitNoSalt(_gameId, RockPaperScissors.Move.Rock);
bytes32 commitA = keccak256(abi.encodePacked(uint8(moveA), bytes32(0)));
bytes memory playerAcalldata = abi.encodeWithSignature("commitMove(uint256,bytes32)", commitA);
bytes32 A_Rock = keccak256(abi.encodePacked(RockPaperScissors.Move.Rock, bytes32(0)));
bytes32 A_Paper = keccak256(abi.encodePacked(RockPaperScissors.Move.Paper, bytes32(0)));
bytes32 A_Scissors = keccak256(abi.encodePacked(RockPaperScissors.Move.Scissors, bytes32(0)));
bytes32 Acommit = hex"f39a869f62e75cf5f0bf914688a6b289caf2049435d8e68c5c5e6d05e44913f3";
uint8 Amove = Acommit == A_Rock ? (uint8(RockPaperScissors.Move.Rock)) : (Acommit == A_Paper ? (uint8(RockPaperScissors.Move.Paper)) : (uint8(RockPaperScissors.Move.Scissors)));
(moveB, saltB) = playerBCommit(_gameId, RockPaperScissors.Move.Paper);
playerAReveal(_gameId, RockPaperScissors.Move.Rock, saltA);
playerBReveal(_gameId, RockPaperScissors.Move.Paper, saltB);
(,,,,,,,,,,,,,, uint8 scoreBAfter,) = game.games(gameId);
assertGt(scoreBAfter, scoreBBefore);
}
function playerACommit(uint256 _gameId, RockPaperScissors.Move move) public returns(RockPaperScissors.Move, bytes32) {
vm.prank(playerA);
bytes32 saltA = keccak256(abi.encodePacked("salt for player A"));
bytes32 commitA = keccak256(abi.encodePacked(uint8(move), saltA));
game.commitMove(_gameId, commitA);
return(move, saltA);
}
function playerBCommit(uint256 _gameId, RockPaperScissors.Move move) public returns(RockPaperScissors.Move, bytes32) {
vm.prank(playerB);
bytes32 saltB = keccak256(abi.encodePacked("salt for player B"));
bytes32 commitB = keccak256(abi.encodePacked(uint8(move), saltB));
game.commitMove(_gameId, commitB);
return(move, saltB);
}
function playerAReveal(uint256 _gameId, RockPaperScissors.Move move, bytes32 saltA) public {
vm.prank(playerA);
game.revealMove(_gameId, uint8(move), saltA);
}
function playerBReveal(uint256 _gameId, RockPaperScissors.Move move, bytes32 saltB) public {
vm.prank(playerB);
game.revealMove(_gameId, uint8(move), saltB);
}
function commitMove(uint256 _gameId, bytes32 _commitHash) external {
Game storage game = games[_gameId];
+ bytes32 NoSaltRock = keccak256(abi.encodePacked(RockPaperScissors.Move.Rock, bytes32(0)));
+ bytes32 NoSaltPaper = keccak256(abi.encodePacked(RockPaperScissors.Move.Paper, bytes32(0)));
+ bytes32 NoSaltScissors = keccak256(abi.encodePacked(RockPaperScissors.Move.Scissors, bytes32(0)));
+ require(_commitHash != NoSaltRock && _commitHash != NoSaltPaper && _commitHash != NoSaltScissors, "must use salt for commit hash");
require(msg.sender == game.playerA || msg.sender == game.playerB, "Not a player in this game");
require(game.state == GameState.Created || game.state == GameState.Committed, "Game not in commit phase");
if (game.currentTurn == 1 && game.commitA == bytes32(0) && game.commitB == bytes32(0)) {
// First turn, first commits
require(game.playerB != address(0), "Waiting for player B to join");
game.state = GameState.Committed;
} else {
// Later turns or second player committing
require(game.state == GameState.Committed, "Not in commit phase");
require(game.moveA == Move.None && game.moveB == Move.None, "Moves already committed for this turn");
}
if (msg.sender == game.playerA) {
require(game.commitA == bytes32(0), "Already committed");
game.commitA = _commitHash;
} else {
require(game.commitB == bytes32(0), "Already committed");
game.commitB = _commitHash;
}
emit MoveCommitted(_gameId, msg.sender, game.currentTurn);
// If both players have committed, set the reveal deadline
if (game.commitA != bytes32(0) && game.commitB != bytes32(0)) {
game.revealDeadline = block.timestamp + game.timeoutInterval;
}
}