View difference between Paste ID: ynspvc5R and RVvqLdhJ
SHOW: | | - or go back to the newest paste.
1
Are you good at computing sha3 hashes? Compete with other players with the objective of getting the lowest hash value and win some Ether! Note that if you are the sole player, this is essentially a faucet when the bonus fund has sufficient ether. 
2
3
The game has three states:
4
	0 - Waiting for first player to join
5
	1 - Waiting for more players, countdown to competition started!
6
	2 - Competition! Submit your solutions at this stage
7
	
8
	Disclaimer: I, the author have hard-coded 1% of the winnings to go to my address. I believe this is fair, since I spent time writing this contract, and also am periodically refilling the (optional) bonus fund that gives additional payouts. Please consider this when playing the game. 
9
10
LOAD CONTRACT:
11
12
	Copy the following commands into your geth console:
13
	
14
        var mygameContract = eth.contract( [{"constant":false,"inputs":[{"name":"sol","type":"uint256"}],"name":"submitSolution","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"bidIndex","type":"uint256"}],"name":"getBidderAt","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"status","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"getCompetitionEnd","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"bidIndex","type":"uint256"}],"name":"getHashAt","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"bidIndex","type":"uint256"}],"name":"getSolnAt","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"blockToHash","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"bidIndex","type":"uint256"}],"name":"getBidAt","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"interval","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"bonusFund","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"setStatus","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"getNumBids","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"suggestedInterval","type":"uint256"}],"name":"newBid","outputs":[],"type":"function"},{"inputs":[],"type":"constructor"}]);
15
       
16-
        var l = mygameContract.at("PUT ADDRESS HERE")
16+
        var l = mygameContract.at("0x35e57f2b08596f1946ecd9d31975ec3c2d7e1c1d")
17
18
USAGE:
19
20
	When game is in state 0:
21
	
22
		Submit first bet, you have the option of choosing the interval value, which is the length of state 1 and state 2 (in terms of number of blocks). The first number (20 in this example) is the interval length you are free to choose. Pick any value between 20 and 200 inclusive. The amount you send is equal to your wager.  
23
		
24
		l.newBid(20, {from:eth.accounts[0], to:l.address, value:web3.toWei(1, "ether"),gas:3000000})
25
26
	When game is in state 1:
27
	
28
		Submit your wager, now the first number in the line below does not matter. Leave it at 0. The amount you send is equal to your wager.
29
	
30
		l.newBid(0, {from:eth.accounts[0], to:l.address, value:web3.toWei(1, "ether"),gas:3000000})  
31
32
	When game is in state 2:
33
	
34
		Submit solutions, by typing the follwing line, where you substitute 0 with your solution. The objective is to find a solution so that the value of sha3(block.blockhash(blockToHash),solution) is lower than that of other players. 
35
		
36
		l.submitSolution(0, {from:eth.accounts[0], to:l.address,gas:3000000})
37
		
38
		When the time interval has passed, you can trigger the payout by typing
39
40
		l.setStatus({from:eth.accounts[0], to:l.address,gas:3000000}), or it is triggered automatically with a call to newBid or submitSolution. 
41
		
42
43
MONITORING:
44
	 You can monitor the current state of the game by typing the following command.
45
	 
46
	 text="";
47
	 text="Contract balance\n"+web3.fromWei(eth.getBalance(l.address), "ether")+" Ether"+"\nstatus:\n"+l.status()+"\nblockToHash (competition start):\n"+l.blockToHash()+"\nCompetition end\n:"+l.getCompetitionEnd()+"\nbonusFund:\n"+web3.fromWei(l.bonusFund(), "ether")+" Ether"+"\ngetNumBids()\n:"+l.getNumBids() +"\n";
48
	 for (i = 0; i < l.getNumBids(); i++) {
49
	 	text+= "i= "+i+"\ngetBidderAt(i)\n:"+l.getBidderAt(i) +"\ngetHashAt(i)\n:"+ l.getHashAt(i)+"\ngetBidAt(i)\n:"+ web3.fromWei(l.getBidAt(i), "ether")+" Ether"+"\ngetSolnAt(i)\n:"+ l.getSolnAt(i)+"\n";
50
	 	}
51
	 text
52
		
53
54
VERIFICATION:
55
56
	This is the source code, compiled with optimization flag set to true. 
57
58
contract SHA3compete {
59
60
    address developer;
61
    uint public interval; // Between 20 and 200
62
    uint public status;
63
    uint public blockToHash;
64
    uint public bonusFund;
65
    Bid[] bids;
66
67
    struct Bid{
68
        address bidder;
69
        uint value;
70
        uint bestHash;
71
        uint sol;
72
    }
73
74
    function SHA3compete(){
75
        developer = msg.sender;
76
        bonusFund = msg.value;
77
        status = 0; // 0 waiting for first bid, 1 has first bid, 2 in competition
78
        bids.length=0;
79
    }
80
81
    function getNumBids() constant returns(uint){
82
      return bids.length;
83
    }
84
85
    function getCompetitionEnd() constant returns(uint){
86
      if (status>0){
87
        return blockToHash+interval;
88
      }
89
      else{
90
        return 0;
91
      }
92
    }
93
94
    function getBidderAt(uint bidIndex) constant returns(address){
95
      return bids[bidIndex].bidder;
96
    }
97
98
    function getHashAt(uint bidIndex) constant returns(uint){
99
      return bids[bidIndex].bestHash;
100
    }
101
102
    function getBidAt(uint bidIndex) constant returns(uint){
103
      return bids[bidIndex].value;
104
    }
105
106
    function getSolnAt(uint bidIndex) constant returns(uint){
107
      return bids[bidIndex].sol;
108
    }
109
110
    function (){
111
      bonusFund+=msg.value;
112
    }
113
114
    function newBid(uint suggestedInterval){ //This is the bid submission
115
        setStatus();
116
        if (msg.value>0 && status!=2 && !(status==0 && (suggestedInterval<20 || suggestedInterval>200) )){
117
          // If in competition, do not accept bids
118
            if (status==0 ){ // Add the first competitor
119
                interval =  suggestedInterval;
120
                blockToHash = block.number+interval;
121
                status = 1;
122
            }
123
            bids.length+=1;
124
            bids[bids.length-1]=Bid(msg.sender, msg.value,2**256-1,0);
125
        }
126
        else{ // Catch erroneous sends
127
          bonusFund+=msg.value;
128
        }
129
    }
130
131
132
    function submitSolution(uint sol){
133
        setStatus();
134
        if (status == 2){
135
          bool foundIdentical = false;
136
              for (uint i=0;i<bids.length;i++){
137
                  if (bids[i].sol == sol){
138
                    foundIdentical = true;
139
                  }
140
              }
141
              if (foundIdentical==false){
142
            for (i=0;i<bids.length;i++){
143
                if (bids[i].bidder == msg.sender){
144
                    bids[i].bestHash=uint(sha3(block.blockhash(blockToHash),sol));
145
                    bids[i].sol=sol;
146
                }
147
            }
148
          }
149
        }
150
        // Catch erroneous sends
151
        bonusFund+=msg.value;
152
    }
153
154
    function setStatus(){
155
        if(status== 1 && blockToHash<=block.number){ //Condition that starts competition
156
            status = 2;
157
        }
158
        if(status==2 && blockToHash+interval<=block.number){ // Condition that ends competition
159
            status=0;
160
            payout();
161
            blockToHash=0;
162
            delete bids;
163
        }
164
    }
165
166
    function payout() private{
167
        bool foundNonZero=true;
168
        while (foundNonZero==true){
169
            foundNonZero=false;
170
            uint currentBest=2**256-1;
171
            uint bestI = 0;
172
            for (uint i=0;i<bids.length;i++){
173
                if (bids[i].bestHash <currentBest && bids[i].value>0){
174
                    currentBest = bids[i].bestHash;
175
                    foundNonZero=true;
176
                    bestI = i;
177
                }
178
            }
179
180
            // Collect money for bestI
181
            uint betOfI = bids[bestI].value;
182
            uint toSend = 0;
183
            for (uint j = 0;j<bids.length;j++){
184
                if (bids[j].value>=betOfI){
185
                    toSend+=betOfI;
186
                    bids[j].value-=betOfI;
187
                }
188
                else{
189
                    toSend+=bids[j].value;
190
                    bids[j].value=0;
191
                }
192
            }
193
            if (foundNonZero==true){
194
              bids[bestI].bidder.send(toSend/100*99+bonusFund/100);
195
              bonusFund-=bonusFund/100;
196
              developer.send(toSend-toSend/100*99);
197
            }
198
        }
199
    }
200
}