coinflip.gno
2.25 Kb ยท 112 lines
1package coinflip
2
3import (
4 "chain"
5 "chain/banker"
6 "chain/runtime"
7 "math/rand"
8
9 "gno.land/p/demo/entropy"
10 "gno.land/p/moul/fifo"
11 "gno.land/r/sacha/config"
12)
13
14const denom = "ugnot"
15const minBetAmount = 1
16
17var (
18 bets = []Bet{}
19 latestBets = fifo.New(8)
20)
21
22func Heads(cur realm) {
23 runtime.AssertOriginCall()
24
25 flipResult := flip(1)
26 betLogic(flipResult)
27}
28
29func Tails(cur realm) {
30 runtime.AssertOriginCall()
31
32 flipResult := flip(0)
33 betLogic(flipResult)
34}
35
36func GetResults(cur realm) []Bet {
37 return bets
38}
39
40func GetRealmBalance(cur realm) int64 {
41 banker_ := banker.NewBanker(banker.BankerTypeReadonly)
42 coins := banker_.GetCoins(runtime.CurrentRealm().Address())
43 balance := coins.AmountOf(denom)
44
45 return balance
46}
47
48func Withdrawal(cur realm, amount int64) {
49 if !config.IsAuthorized(runtime.PreviousRealm().Address()) {
50 panic(config.ErrUnauthorized)
51 }
52
53 runtime.AssertOriginCall()
54
55 banker_ := banker.NewBanker(banker.BankerTypeRealmSend)
56
57 if GetRealmBalance(cur) < amount {
58 panic("insufficient balance")
59 }
60
61 banker_.SendCoins(runtime.CurrentRealm().Address(), runtime.OriginCaller(), chain.NewCoins(chain.NewCoin(denom, amount)))
62}
63
64func flip(choice int) bool {
65 seed1 := uint64(entropy.New().Seed())
66 seed2 := uint64(entropy.New().Seed())
67
68 r := rand.New(rand.NewPCG(seed1, seed2))
69 result := r.IntN(2)
70
71 return result == choice
72}
73
74func getBet() chain.Coin {
75 bet := banker.OriginSend()
76 if len(bet) != 1 || bet[0].Denom != denom {
77 panic("bet is invalid")
78 }
79
80 amount := bet[0].Amount
81
82 if amount < minBetAmount {
83 panic("Bet too low")
84 }
85 if amount*2 > GetRealmBalance(cross) {
86 panic("Bet too high")
87 }
88
89 return bet[0]
90}
91
92func sendPrize(cur realm, caller address, amount int64) {
93 banker_ := banker.NewBanker(banker.BankerTypeRealmSend)
94 wonCoins := chain.NewCoins(chain.NewCoin(denom, amount))
95
96 banker_.SendCoins(runtime.CurrentRealm().Address(), caller, wonCoins)
97}
98
99func betLogic(flipResult bool) {
100 caller := runtime.OriginCaller()
101 bet := getBet()
102
103 if flipResult == true {
104 sendPrize(cross, caller, bet.Amount*2)
105 chain.Emit("BetResult", "Result", "win")
106 } else {
107 chain.Emit("BetResult", "Result", "lose")
108 }
109
110 bets = append(bets, Bet{Address: caller, Result: flipResult, Amount: bet})
111 latestBets.Append(Bet{Address: caller, Result: flipResult, Amount: bet})
112}