-
Notifications
You must be signed in to change notification settings - Fork 16
/
satoshi_dice.rb
79 lines (59 loc) · 2.15 KB
/
satoshi_dice.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# encoding: utf-8
##
# satoshi dice gambling - up to 65 000x returns on your bet!
#
# to run type:
# $ ruby ./run_satoshi_dice.rb
class SatoshiDice < Contract
## type struct - address user; uint block; uint cap; uint amount;
Bet = Struct.new( :user, :block, :cap, :amount )
## Fee (Casino House Edge) is 1.9%, that is, 19 / 1000
FEE_NUMERATOR = 19
FEE_DENOMINATOR = 1000
MAXIMUM_CAP = 2**16 # 65_536 = 2^16 = 2 byte/16 bit
MAXIMUM_BET = 100_000_000
MINIMUM_BET = 100
BetPlaced = Event.new( :id, :user, :cap, :amount ) ## type uint id, address user, uint cap, uint amount
Roll = Event.new( :id, :rolled ) ## type uint id, uint rolled
def initialize
@owner = msg.sender
@counter = 0
@bets = Mapping.of( Integer => Bet ) ## type mapping( uint => Bet )
end
def bet( cap )
assert( cap >= 1 && cap <= MAXIMUM_CAP )
assert( msg.value >= MINIMUM_BET && msg.value <= MAXIMUM_BET )
@counter += 1
@bets[@counter] = Bet.new( msg.sender, block.number+3, cap, msg.value )
log BetPlaced.new( @counter, msg.sender, cap, msg.value )
end
def roll( id )
bet = @bets[id]
assert( msg.sender == bet.user )
assert( block.number >= bet.block )
assert( block.number <= bet.block + 255 )
## "provable" fair - random number depends on
## - blockhash (of block in the future - t+3)
## - nonce (that is, bet counter id)
hex = sha256( "#{blockhash( bet.block )} #{id}" )
## get first 2 bytes (4 chars in hex string) and convert to integer number
## results in a number between 0 and 65_535
rolled = hex[0,4].to_i(16)
puts "rolled: #{rolled} - hex: #{hex[0,4]}"
if rolled < bet.cap
payout = bet.amount * MAXIMUM_CAP / bet.cap
fee = payout * FEE_NUMERATOR / FEE_DENOMINATOR
payout -= fee
puts "bingo! payout: #{payout}, fee: #{fee}"
msg.sender.transfer( payout )
end
log Roll.new( id, rolled )
@bets.delete( id )
end
def fund
end
def kill
assert( msg.sender == @owner )
selfdestruct( @owner )
end
end