pragma solidity ^0.4.3;
contract Game{
//创建者
address founder;
uint betPhase=6;
uint commitPhase=6;
uint openPhase=6;
uint minValue=0.1 ether;
uint refund=90;
bool finished=true;
uint startBlock;
uint id=0;
struct Participant{
bytes32 hash;
bytes32 origin;
uint value;
bool committed;
bool returned;
}
struct Bet{
uint betPhase;
uint commitPhase;
uint openPhase;
uint minValue;
mapping(address=>Participant) participants;
address[] keys;
uint totalValue;
uint valiadValue;
uint validUsers;
bytes32 luckNumber;
address lucky;
bool prized;
uint refund;
}
mapping(uint=>Bet) games;
modifier checkGameFinish(){
if(finished){
throw;
}
_;
}
modifier checkFounder(){
if(msg.sender!=founder){
throw;
}
_;
}
modifier checkPrized(uint id){
if(games[id].prized){
throw;
}
_;
}
modifier checkFihished(){
if(!finished){
throw;
}
_;
}
modifier checkId(uint i){
if(id!=i){
throw;
}
_;
}
modifier checkValue(uint value){
if(value<minValue){
throw;
}
_;
}
modifier checkBetPhase(){
if(block.number>startBlock+betPhase){
throw;
}
_;
}
modifier checkCommitPhase(){
if(block.number>startBlock+betPhase+commitPhase){
throw;
}
_;
}
modifier checkOpen(){
if(block.number<startBlock+betPhase+commitPhase){
throw;
}
_;
}
modifier checkUser(address user,uint id){
if(games[id].participants[user].hash==""){
throw;
}
_;
}
modifier checkRegister(uint id,address user){
if(games[id].participants[user].hash!=""){
throw;
}
_;
}
function Game() public{
founder=msg.sender;
}
event StartGame(uint indexed id,uint betPhase,uint commitPhase,uint openPhase,uint betValue,uint refund,uint startBlock);
function startGame(uint iBetPhase,uint iCommitPhase,uint iOpenPhase,uint betvalue,uint iRefund)
checkFounder
checkFihished
{
id+=1;
betPhase=iBetPhase;
commitPhase=iCommitPhase;
openPhase=iOpenPhase;
minValue=(betvalue*1 ether)/100;
finished=false;
startBlock=block.number;
refund=iRefund;
StartGame(id,betPhase,commitPhase,openPhase,minValue,refund,startBlock);
}
// current total value,hash,id,sid
event Play(uint indexed value,bytes32 hash,uint id,bytes32 sid,address player);
function play(uint id,bytes32 hash,bytes32 sid) public payable
checkValue(msg.value)
checkBetPhase
checkId(id)
checkRegister(id,msg.sender)
{
address user=msg.sender;
Bet memory tmp=games[id];
Participant memory participant=Participant({hash:hash,origin:"",value:msg.value,committed:false,returned:false});
uint value;
if(tmp.keys.length==0){
Bet storage bet=games[id];
bet.betPhase=betPhase;
bet.commitPhase=commitPhase;
bet.openPhase=openPhase;
bet.minValue=minValue;
bet.keys.push(user);
bet.participants[user]=participant;
bet.refund=refund;
bet.totalValue=msg.value;
value=msg.value;
}else{
games[id].keys.push(user);
games[id].participants[user]=participant;
games[id].totalValue+=msg.value;
value=msg.value;
}
var num=games[id].keys.length;
Play(value,hash,id,sid,msg.sender);
}
// origin,valid users
event CommitOrigin(address indexed user,bytes32 origin,uint num,bytes32 sid,uint id);
function commitOrigin(uint id,bytes32 origin,bytes32 sid)
checkCommitPhase
checkId(id)
checkUser(msg.sender,id)
{
bytes32 hash=games[id].participants[msg.sender].hash;
if(sha3(origin)==hash){
if(games[id].participants[msg.sender].committed!=true){
games[id].participants[msg.sender].committed=true;
games[id].participants[msg.sender].origin=origin;
games[id].valiadValue+=games[id].participants[msg.sender].value;
games[id].validUsers++;
CommitOrigin(msg.sender,origin,games[id].validUsers,sid,id);
}
}else{
throw;
}
}
function getLuckNumber(Bet storage bet) internal
returns(bytes32)
{
address[] memory users=bet.keys;
bytes32 random;
for(uint i=0;i<users.length;i++){
address key=users[i];
Participant memory p=bet.participants[key];
if(p.committed==true){
random ^=p.origin;
}
}
return sha3(random);
}
// lucky user,lucky number,random number,prize
event Open(address indexed user,bytes32 random,uint prize,uint id);
function open(uint id)
checkPrized(id)
checkFounder
checkOpen
checkGameFinish
{
bytes32 max=0;
Bet storage bet=games[id];
bytes32 random=getLuckNumber(bet);
address tmp;
address[] memory users=bet.keys;
for(uint i=0;i<users.length;i++){
address key=users[i];
Participant storage p=bet.participants[key];
if(p.committed==true){
bytes32 distance=random^p.origin;
if(distance>max){
max=distance;
tmp=key;
}
}else{
if(p.returned==false){
if(key.send(p.value*8/10)){
p.returned=true;
}
}
}
}
bet.lucky=tmp;
bet.luckNumber=random;
uint prize=bet.valiadValue*refund/100;
founder.send((bet.valiadValue-prize));
if(tmp.send(prize)){
bet.prized=true;
Open(tmp,random,prize,id);
}
finished=true;
}
function getContractBalance() constant returns(uint){
return this.balance;
}
function withdraw(address user,uint value)
checkFounder
{
user.send(value);
}
function getPlayerCommitted(uint period,address player) constant returns(bool){
Participant memory p=games[period].participants[player];
return p.committed;
}
function getPlayerReturned(uint period,address player) constant returns(bool){
Participant memory p=games[period].participants[player];
return p.returned;
}
function getPlayerNum(uint period) constant
returns(uint){
Bet bet=games[period];
return bet.keys.length;
}
function getPlayerAddress(uint period,uint offset) constant
returns(address){
Bet bet=games[period];
return bet.keys[offset];
}
function getPlayerOrigin(uint period,uint offset) constant
returns(bytes32){
Bet bet=games[period];
address user=bet.keys[offset];
return bet.participants[user].origin;
}
function getPlayerHash(uint period,uint offset) constant
returns(bytes32){
Bet bet=games[period];
address user=bet.keys[offset];
return bet.participants[user].hash;
}
function getPlayerValue(uint period,uint offset) constant
returns(uint){
Bet bet=games[period];
address user=bet.keys[offset];
return bet.participants[user].value;
}
// public getRandom(uint id) constant{
// }
function getId() constant returns(uint){
return id;
}
function getRandom(uint id) constant
checkId(id)
returns(bytes32){
return games[id].luckNumber;
}
function getLuckUser(uint id) constant
checkId(id)
returns(address){
return games[id].lucky;
}
function getPrizeAmount(uint id) constant
checkId(id)
returns(uint){
return games[id].totalValue;
}
function getMinAmount(uint id) constant
checkId(id)
returns(uint)
{
return minValue;
}
function getsha3(bytes32 x) constant
returns(bytes32){
return sha3(x);
}
function getGamePeriod() constant
returns(uint){
return id;
}
function getStartBlock() constant
returns(uint){
return startBlock;
}
function getBetPhase() constant
returns(uint){
return betPhase;
}
function getCommitPhase() constant
returns(uint){
return commitPhase;
}
function getFinished() constant
returns(bool){
return finished;
}
}
{
"compilationTarget": {
"Game.sol": "Game"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"player","type":"address"}],"name":"getPlayerCommitted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"offset","type":"uint256"}],"name":"getPlayerOrigin","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"offset","type":"uint256"}],"name":"getPlayerAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"origin","type":"bytes32"},{"name":"sid","type":"bytes32"}],"name":"commitOrigin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getMinAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getGamePeriod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"offset","type":"uint256"}],"name":"getPlayerHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"open","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"hash","type":"bytes32"},{"name":"sid","type":"bytes32"}],"name":"play","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getContractBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"offset","type":"uint256"}],"name":"getPlayerValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCommitPhase","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getLuckUser","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getPrizeAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStartBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBetPhase","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"iBetPhase","type":"uint256"},{"name":"iCommitPhase","type":"uint256"},{"name":"iOpenPhase","type":"uint256"},{"name":"betvalue","type":"uint256"},{"name":"iRefund","type":"uint256"}],"name":"startGame","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"}],"name":"getRandom","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"bytes32"}],"name":"getsha3","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"}],"name":"getPlayerNum","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"period","type":"uint256"},{"name":"player","type":"address"}],"name":"getPlayerReturned","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"user","type":"address"},{"name":"value","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"betPhase","type":"uint256"},{"indexed":false,"name":"commitPhase","type":"uint256"},{"indexed":false,"name":"openPhase","type":"uint256"},{"indexed":false,"name":"betValue","type":"uint256"},{"indexed":false,"name":"refund","type":"uint256"},{"indexed":false,"name":"startBlock","type":"uint256"}],"name":"StartGame","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"value","type":"uint256"},{"indexed":false,"name":"hash","type":"bytes32"},{"indexed":false,"name":"id","type":"uint256"},{"indexed":false,"name":"sid","type":"bytes32"},{"indexed":false,"name":"player","type":"address"}],"name":"Play","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"origin","type":"bytes32"},{"indexed":false,"name":"num","type":"uint256"},{"indexed":false,"name":"sid","type":"bytes32"},{"indexed":false,"name":"id","type":"uint256"}],"name":"CommitOrigin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"random","type":"bytes32"},{"indexed":false,"name":"prize","type":"uint256"},{"indexed":false,"name":"id","type":"uint256"}],"name":"Open","type":"event"}]