这份合同似乎是一个在合同余额中提供1/16赔率的游戏。但是,在调试器中运行代码时,似乎“secretNumber”变量在使用前被覆盖。
pragma solidity ^0.4.19;
contract CryptoRoulette {
uint256 private secretNumber;
uint256 public lastPlayed;
uint256 public betPrice = 0.1 ether;
address public ownerAddr;
struct Game {
address player;
uint256 number;
}
Game[] public gamesPlayed;
function CryptoRoulette() public {
ownerAddr = msg.sender;
shuffle();
}
function shuffle() internal {
secretNumber = uint8(sha3(now, block.blockhash(block.number-1))) % 16;
}
function play(uint256 number) payable public {
require(msg.value >= betPrice && number < 16);
Game game;
game.player = msg.sender;
game.number = number;
gamesPlayed.push(game);
if (number == secretNumber) {
msg.sender.transfer(this.balance);
}
shuffle();
lastPlayed = now;
}
function kill() public {
if (msg.sender == ownerAddr && now > lastPlayed + 1 days) {
suicide(msg.sender);
}
}
function() public payable { }
}
secretNumber的更新方式应始终小于16
secretNumber = uint8(sha3(now, block.blockhash(block.number-1))) % 16;
此调试器输出显示在执行
if (number == secretNumber) {
奇怪的是,secretNumber的值已经更新为呼叫者地址(msg.sender)。
`
(243) PUSH1 0x00
000000000000000000000000000000000000000000000000000000006898f82b
0000000000000000000000000000000000000000000000000000000000000143
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000000 (top)
40: if (number == secretNumber) {
^^^^^^^^^^^^
debug(develop:0x98cacf83...)> i
CryptoRoulette.sol | 0xbd2c938b9f6bfc1a66368d08cb44dc3eb2ae27be:
40: if (number == secretNumber) {
^^^^^^
debug(develop:0x98cacf83...)> p
CryptoRoulette.sol | 0xbd2c938b9f6bfc1a66368d08cb44dc3eb2ae27be:
(245) DUP3
000000000000000000000000000000000000000000000000000000006898f82b
0000000000000000000000000000000000000000000000000000000000000143
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000627306090abab3a6e1400e9345bc60c78a8bef57 (top)
40: if (number == secretNumber) {
^^^^^^
我的猜测是,这种情况之前的存储访问导致堆栈以某种方式损坏。
这是已知的漏洞吗?有人能解释一下发生了什么事吗?