Solidity 错误搜寻
Solidity bug hunting
下面有一段代码试图实现 Tic-Tac-Toe(也称为 Noughts and Crosses)的两人游戏(在线下注)。
据说这个实现至少包含9个危害游戏安全的bug,但我只找到一个,在第61行,我认为selfdestruct()不是送锅的方式。你们能找到更多的错误并提出一些相应的修复吗?欢迎任何帮助。
contract TicTacToe {
// game configuration
address [2] _playerAddress ; // address of both players
uint32 _turnLength ; // max time for each turn
// nonce material used to pick the first player
bytes32 _p1Commitment ;
uint8 _p2Nonce ;
// game state
uint8 [9] _board ; // serialized 3 x3 array
uint8 _currentPlayer ; // 0 or 1, indicating whose turn it is
uint256 _turnDeadline ; // deadline for submitting next move
// Create a new game , challenging a named opponent .
// The value passed in is the stake which the opponent must match .
// The challenger commits to its nonce used to determine first mover .
constructor ( address opponent , uint32 turnLength ,
bytes32 p1Commitment ) public {
_playerAddress [0] = msg . sender ;
_playerAddress [1] = opponent ;
_turnLength = turnLength ;
_p1Commitment = p1Commitment ;
}
// Join a game as the second player .
function joinGame ( uint8 p2Nonce ) public payable {
// only the specified opponent may join
if ( msg . sender != _playerAddress [1])
revert () ;
// must match player 1’s stake .
require ( msg . value >= this . balance ) ;
_p2Nonce = p2Nonce ;
}
// Revealing player 1’s nonce to choose who goes first .
function startGame ( uint8 p1Nonce ) public {
// must open the original commitment
require ( sha3 ( p1Nonce ) == _p1Commitment );
// XOR both nonces and take the last bit to pick the first player
_currentPlayer = ( p1Nonce ^ _p2Nonce ) & 0 x01 ;
// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}
// Submit a move
function playMove ( uint8 squareToPlay ) public {
// make sure correct player is submitting a move
require ( msg . sender != _playerAddress [ _currentPlayer ]) ;
// claim this square for the current player .
_board [ squareToPlay ] = _currentPlayer ;
// If the game is won , send the pot to the winner
if ( checkGameOver () )
selfdestruct ( msg . sender );
// Flip the current player
_currentPlayer ^= 0 x1 ;
// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}
// Default the game if a player takes too long to submit a move
function defaultGame () public {
if ( block . number > _turnDeadline )
selfdestruct ( msg . sender );
}
}
好的,我会回答我自己的问题。
- 第 42 行
- 第 54 行
- 又是第 54 行
- 第 61 行
- 第 72 行
下面有一段代码试图实现 Tic-Tac-Toe(也称为 Noughts and Crosses)的两人游戏(在线下注)。 据说这个实现至少包含9个危害游戏安全的bug,但我只找到一个,在第61行,我认为selfdestruct()不是送锅的方式。你们能找到更多的错误并提出一些相应的修复吗?欢迎任何帮助。
contract TicTacToe {
// game configuration
address [2] _playerAddress ; // address of both players
uint32 _turnLength ; // max time for each turn
// nonce material used to pick the first player
bytes32 _p1Commitment ;
uint8 _p2Nonce ;
// game state
uint8 [9] _board ; // serialized 3 x3 array
uint8 _currentPlayer ; // 0 or 1, indicating whose turn it is
uint256 _turnDeadline ; // deadline for submitting next move
// Create a new game , challenging a named opponent .
// The value passed in is the stake which the opponent must match .
// The challenger commits to its nonce used to determine first mover .
constructor ( address opponent , uint32 turnLength ,
bytes32 p1Commitment ) public {
_playerAddress [0] = msg . sender ;
_playerAddress [1] = opponent ;
_turnLength = turnLength ;
_p1Commitment = p1Commitment ;
}
// Join a game as the second player .
function joinGame ( uint8 p2Nonce ) public payable {
// only the specified opponent may join
if ( msg . sender != _playerAddress [1])
revert () ;
// must match player 1’s stake .
require ( msg . value >= this . balance ) ;
_p2Nonce = p2Nonce ;
}
// Revealing player 1’s nonce to choose who goes first .
function startGame ( uint8 p1Nonce ) public {
// must open the original commitment
require ( sha3 ( p1Nonce ) == _p1Commitment );
// XOR both nonces and take the last bit to pick the first player
_currentPlayer = ( p1Nonce ^ _p2Nonce ) & 0 x01 ;
// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}
// Submit a move
function playMove ( uint8 squareToPlay ) public {
// make sure correct player is submitting a move
require ( msg . sender != _playerAddress [ _currentPlayer ]) ;
// claim this square for the current player .
_board [ squareToPlay ] = _currentPlayer ;
// If the game is won , send the pot to the winner
if ( checkGameOver () )
selfdestruct ( msg . sender );
// Flip the current player
_currentPlayer ^= 0 x1 ;
// start the clock for the next move
_turnDeadline = block . number + _turnLength ;
}
// Default the game if a player takes too long to submit a move
function defaultGame () public {
if ( block . number > _turnDeadline )
selfdestruct ( msg . sender );
}
}
好的,我会回答我自己的问题。
- 第 42 行
- 第 54 行
- 又是第 54 行
- 第 61 行
- 第 72 行