-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathInstantLotteryGame.py
853 lines (697 loc) · 34.5 KB
/
InstantLotteryGame.py
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
Cversion = '1.0.0'
from hashgard.interop.System.Storage import Get, Put, PutArray, GetArray
from hashgard.interop.System.Runtime import GetTxSender, GetTime, GetRand, TimeFormat, Assert
from hashgard.vmop.Builtins import concat, substr
from hashgard.libop.String import join, split, int, str
from hashgard.interop.System.Account import IsValid
from hashgard.interop.System.Bank import ContractAccAddressGet, ContractBalanceSend, ContractBalanceInject, BalanceOf
GARD_DENOM = 'agard'
GARD_FACTOR = 1000000000000000000
OWNER = 'gard1xvn48vn3ljwk2d3vynv8ugkl373d93tfp9zae3'
KEY_OWNER = OWNER
KEY_SYSTEM_POOL = "system_prize_pool" # 系统奖池
KEY_USER_POOL = "user_prize_pool" # 用户奖池
KEY_EVENT_POOL = "event_prize_pool" # 活动奖池
KEY_MY_ALL_STAKE = "my_sake" # 我的投注记录
KEY_MY_STAKE_COUNT = "my_stake_count" # 我的投注统计
KEY_BETTING_AMOUNT = "betting_amount" # 投注金额
KEY_BETTING_NUMBER = "betting_number" # 投注号码
KEY_SHARED_REWARD = "shared_reward" # 推广奖励计数
KEY_INVITED_RECORD = "invited_record" # 被邀请记录
KEY_INVITATION_RECORD = "invitation_record" # 邀请记录
KEY_INVITATION_CODE = "invitation_code" # 邀请码
KEY_AMOUNT_EACH_AWARD = "amount_of_each_award" # 每期中奖额度信息
KEY_PRIZE_NUMBER = "prize_number" # 中奖号码
KEY_LOTTERY_USER = "lottery_user_info" # 开奖时的信息
KEY_REDEMPTION_USER = "redemption" # 兑奖时的信息
KEY_NUMBER_DRAWS = "now_number_draws" # 投注期数
KEY_WITZHDRAWS_STATUS = "withdraw_status" # 用户的兑奖状态
KEY_LAST_NUMBER_DRAWS = "last_number_draws" # 最后一期的期数
KEY_CALUCLATION_NOTE = "calculation_note" # 用以计算投注数
KEY_NUMBER_BETS_PEER_ISSUE = "Number_of_bets_per_issue" # 每一期每一柱的投注详情
KEY_USER_BETS = "user_bets" # 允许用户的最大投注次数
KEY_ISSUE_ACCOUNT = "issue_account" # 累计中奖额度信息
KEY_PERIODS_LIST = "periods_list" # 存放期号列表
KEY_PERIODS_TIME = "periods_time" # 期号对应的时间
KEY_DRAWS_PID = "pid"
KEY_GAME_START_TIME = 1567267200
KEY_GAME_TIME_FOR_A_ROUND = 3600 # 3600 一个小时
def main(operation, args):
if operation == 'init':
return init()
if operation == 'system_prize_pool_inject':
if len(args) != 1:
return False
return system_prize_pool_inject(args[0])
if operation == 'syspool':
return syspool()
if operation == 'withdraw_system_pool':
if len(args) != 1:
return False
return withdraw_system_pool(args[0])
if operation == "query_draws_pid":
return query_draws_pid()
if operation == "if_lottery":
return if_lottery()
if operation == "get_draw_calculation_note":
if len(args) != 1:
return False
return get_draw_calculation_note(args[0])
if operation == "get_pid":
return get_pid()
if operation == "withdraw_system_pool":
if len(args) != 1:
return False
return withdraw_system_pool(args[0])
if operation == "stake":
if len(args) != 3:
return False
return stake(args[0], args[1], args[2])
if operation == "stakepool":
return stakepool()
if operation == "query_users_number":
if len(args) != 2:
return False
return query_users_number(args[0], args[1])
if operation == "query_users_number_amount":
if len(args) != 3:
return False
return query_users_number_amount(args[0], args[1], args[2])
if operation == "query_draws_lottery_user":
if len(args) != 1:
return False
return query_draws_lottery_user(args[0])
if operation == "draw":
return draw()
if operation == "query_amount_award":
if len(args) != 1:
return False
return query_amount_award(args[0])
if operation == "withdraw":
if len(args) != 1:
return False
return withdraw(args[0])
if operation == "set_event_pool":
if len(args) != 1:
return False
return set_event_pool(args[0])
if operation == "ppool":
return ppool()
if operation == "query_prize_number":
if len(args) != 1:
return False
return query_prize_number(args[0])
if operation == "query_user_invitation_code":
if len(args) != 1:
return False
return query_user_invitation_code(args[0])
if operation == "query_invitation_code_user":
if len(args) != 1:
return False
return query_invitation_code_user(args[0])
if operation == "get_redemption_information":
if len(args) != 2:
return False
return get_redemption_information(args[0], args[1])
if operation == "query_invitee":
if len(args) != 1:
return False
return query_invitee(args[0])
if operation == "query_my_inviter":
if len(args) != 1:
return False
return query_my_inviter(args[0])
if operation == "invitation_code_generation":
return invitation_code_generation()
if operation == "owner":
return owner()
if operation == "change_owner":
if len(args) != 1:
return False
return change_owner(args[0])
if operation == "issue":
return issue()
if operation == "lastissue":
return lastissue()
if operation == 'contractKeys':
return contract_keys()
if operation == "get_period_generation":
return get_period_generation()
if operation == "get_stake_account":
if len(args) != 1:
return False
return get_stake_account(args[0])
if operation == "contractAccount":
return contractAccount()
if operation == "query_bets_note":
if len(args) != 2:
return False
return query_bets_note(args[0], args[1])
if operation == "get_promotion_reward":
if len(args) != 1:
return False
return get_promotion_reward(args[0])
if operation == "get_stake_issue":
if len(args) != 1:
return False
return get_stake_issue(args[0])
if operation == "query_issue_stakepool":
if len(args) != 1:
return False
return query_issue_stakepool(args[0])
if operation == "query_issue_account":
return query_issue_account()
if operation == "query_periods_list":
return query_periods_list()
if operation == "query_withdraw_account":
if len(args) != 1:
return False
return query_withdraw_account(args[0])
if operation == "query_user_bet_num":
if len(args) != 2:
return False
return query_user_bet_num(args[0], args[1])
if operation == "query_user_withdraw_status":
if len(args) != 2:
return False
return query_user_withdraw_status(args[0], args[1])
return False
def init():
if Get(KEY_OWNER):
return False
now_time = GetTime()
Put(KEY_OWNER, OWNER) # 添加owner 地址
Put(KEY_NUMBER_DRAWS, get_period_generation()) # 当前期数 ,格式:20190925
draws_time_key = concat(Get(KEY_NUMBER_DRAWS), KEY_PERIODS_TIME)
Put(draws_time_key, now_time) # 当前期号对应的时间戳
note_key = concat(Get(KEY_NUMBER_DRAWS), KEY_CALUCLATION_NOTE)
Put(note_key, 0) # 投注数
key = concat(Get(KEY_NUMBER_DRAWS), KEY_DRAWS_PID)
Put(key, get_pid()) # 初始期数的pid
PutArray(KEY_PERIODS_LIST, [Get(KEY_NUMBER_DRAWS)]) # 存放一天内的期号列表
return True
def contractAccount(): # 合约的资金账户地址
return ContractAccAddressGet()
def owner(): # 获取 owner 地址
return Get(KEY_OWNER)
def change_owner(address): # 改变 owner 地址
if not IsValid(address):
raise Exception("地址格式错误")
if GetTxSender() != Get(KEY_OWNER):
raise Exception("请使用 owner 地址调用")
Put(KEY_OWNER, address)
return True
def issue(): # 返回当前期数
return Get(KEY_NUMBER_DRAWS)
def contract_keys():
return ["owner:string", "issue:string", "syspool:integer", "stakepool:integer", "ppool:integer",
"contractAccount:string"]
def query_draws_pid(): # 查询当前期数对应的pid
number_draws = Get(KEY_NUMBER_DRAWS) # 当前期数
key = concat(number_draws, KEY_DRAWS_PID)
return Get(key)
def lastissue(): # 最后一期期数
last_draw = GetArray(KEY_LAST_NUMBER_DRAWS)
return last_draw
def if_lottery(): # 判断是否可以开奖
rd = Get(KEY_NUMBER_DRAWS) # 当前期
note_key = concat(rd, KEY_CALUCLATION_NOTE) # 这一期的的投注次数
notes = Get(note_key)
pid = get_pid() # 当前的pid
if notes > 0 and pid > query_draws_pid(): # 判断当前期数的pid 是不是还未动,因为pid是个递增的 并且判断当前是否有人投注
return True
return False
def get_draw_calculation_note(number_draws): # 查询期数的总共投注次数
note_key = concat(number_draws, KEY_CALUCLATION_NOTE)
return Get(note_key)
def get_pid(): # 获取当前期数pid,主要用于判断是否已经过了一小时
time = GetTime()
pid = ((time - KEY_GAME_START_TIME) - (
time - KEY_GAME_START_TIME) % KEY_GAME_TIME_FOR_A_ROUND) / KEY_GAME_TIME_FOR_A_ROUND
return pid
# 返回是个int
def system_prize_pool_inject(amount): # 给系统奖池授予额度
sender = GetTxSender()
if BalanceOf(sender, [GARD_DENOM])[0] < amount: # 判断余额是否足够初始化
raise Exception("余额不足")
sys_pool = Get(KEY_SYSTEM_POOL)
if not sys_pool:
ContractBalanceInject(sender, GARD_DENOM, amount)
Put(KEY_SYSTEM_POOL, amount) # 记录系统奖池额度
return True
balance_amount = sys_pool + amount
ContractBalanceInject(sender, GARD_DENOM, balance_amount)
Put(KEY_SYSTEM_POOL, balance_amount) # 记录总的奖池额度
return True
def syspool(): # 查询系统奖池额度
return Get(KEY_SYSTEM_POOL)
def withdraw_system_pool(amount): # 取回系统奖池额度
if GetTxSender() != Get(KEY_OWNER):
raise Exception("请使用合约 owner 地址调用")
if amount < 0:
raise Exception("请输入正确的金额")
balance_amount = syspool() - amount
if balance_amount < 0:
raise Exception("系统奖池余额不足")
ContractBalanceSend(Get(KEY_OWNER), GARD_DENOM, amount)
key = concat(KEY_SYSTEM_POOL, ContractAccAddressGet())
Put(key, balance_amount)
return True
def stake(number, amount, invitation_code): # 用户投注
if len(number) != 3:
raise Exception("请输入正确的投注号码")
if amount < 10000 * GARD_FACTOR:
raise Exception("每次投注不能少于 10000gard")
if if_lottery():
raise Exception('当前期已经结束,处于开奖期,前往开奖')
sender_address = GetTxSender() # 当前调用地址
if BalanceOf(sender_address, [GARD_DENOM])[0] < 10000 * GARD_FACTOR:
raise Exception("账户余额不足投注")
now_time = GetTime() # 当前时间
rd = Get(KEY_NUMBER_DRAWS) # 当前期数
user_bets_key = concat(concat(KEY_USER_BETS, sender_address), rd) # 用户投注次数
user_bets = Get(user_bets_key)
if not user_bets:
Put(user_bets_key, 1)
else:
if user_bets >= 3:
raise Exception("当前用户投注次数超过三次")
else:
Put(user_bets_key, user_bets + 1)
now_user_pool = stakepool() # 当前用户池额度
if not now_user_pool:
Put(KEY_USER_POOL, amount)
else:
Put(KEY_USER_POOL, amount + now_user_pool) # 添加入总的用户池额度
now_issue_stakepool = query_issue_stakepool(rd)
issue_stakepool_key = concat(rd, KEY_USER_POOL) # 当期的用户池总额度
if now_issue_stakepool > 0:
Put(issue_stakepool_key, now_issue_stakepool + amount)
else:
Put(issue_stakepool_key, amount)
note_key = concat(rd, KEY_CALUCLATION_NOTE)
num_note = Get(note_key) # 获取投注数
now_note = num_note + 1 # 每个用户投注一次,次数增加一次
Put(note_key, now_note) # 记录每一期的总的投注数
# 投注数每次都增加,避免出现一个过大的列表
betting_record_key = concat(concat(KEY_NUMBER_BETS_PEER_ISSUE, rd), str(now_note)) # 每一期的投注记录 key
user_info = [str(now_time), sender_address, number, str(amount)] # 保存为一个数组
Assert(user_info[3] == str(amount), "erro") # 输出address
PutArray(betting_record_key, user_info) # 记录投注记录
number_key = concat(concat(rd, KEY_BETTING_NUMBER), sender_address) # 用户的投注号码
amount_key = concat(concat(concat(rd, KEY_BETTING_AMOUNT), number), sender_address) # 记录用户投注的金额
stake_all_key = concat(KEY_MY_ALL_STAKE, sender_address) # 我所有的投注记录,只记录三天以内的
stake_list = GetArray(stake_all_key)
if len(stake_list) == 0:
ls = []
ls.append(rd)
PutArray(stake_all_key, ls) # 记录我的投注记录期号
else:
periods_exceeds_list = get_periods_exceeds(sender_address, rd) # 返回去掉一天外的数组
PutArray(stake_all_key, periods_exceeds_list)
numbers = GetArray(number_key)
if len(numbers) == 0:
PutArray(number_key, [number]) # 记录用户的投注号码
Put(amount_key, amount) # 记录用户对这个号码的投注金额
else:
ls = []
existed = False
for i in range(len(numbers)):
ls.append(numbers[i])
if numbers[i] == number:
balance = query_users_number_amount(sender_address, rd, number)
balance_amount = balance + amount
Put(amount_key, balance_amount)
existed = True
if not existed:
ls.append(number)
PutArray(number_key, ls)
Put(amount_key, amount) # 记录用户对这个号码的投注金额
invited_key = concat(KEY_INVITED_RECORD, sender_address) # 被邀请记录
invited = Get(invited_key)
invitation_user = query_invitation_code_user(invitation_code) # 生成邀请码的地址
invitation_key = concat(KEY_INVITATION_RECORD, invitation_user) # 上级邀请记录
if len(invitation_code) == 4 and not invited and invitation_user and invitation_user != sender_address:
Put(invited_key, invitation_user) # 提交被邀请记录
invitation_list_value = GetArray(invitation_key)
invitation_list = []
for i in range(len(invitation_list_value)):
invitation_list.append(invitation_list_value[i])
invitation_list.append(sender_address)
PutArray(invitation_key, invitation_list) # 提交邀请人的邀请记录,由于可以邀请很多人,所有是个列表
stake_count_key = concat(KEY_MY_STAKE_COUNT, sender_address) # 我的投注统计,包括投注的总 token,和获取奖励的总 token
count_value = GetArray(stake_count_key)
if len(count_value) == 0:
PutArray(stake_count_key, [str(amount), str(0)])
if len(count_value) == 2:
betting_amount = int(count_value[0]) # 总共投注
reward_amount = int(count_value[1]) # 获得奖励
PutArray(stake_count_key, [str(betting_amount + amount), str(reward_amount)]) # 提交自己投注记录
ContractBalanceInject(sender_address, GARD_DENOM, amount)
return True
def stakepool(): # 查询用户奖池额度
return Get(KEY_USER_POOL)
def query_issue_stakepool(rd): # 查询该期数的所有用户投注金额
key = concat(rd, KEY_USER_POOL)
return Get(key) # 返回int
def query_users_number(sender_address, rd): # 查询该地址对应期数,查询用户的所有投注号码
if not IsValid(sender_address):
raise Exception("Incorrect address format.")
number_key = concat(concat(rd, KEY_BETTING_NUMBER), sender_address)
return GetArray(number_key) # 返回一个列表
def query_users_number_amount(sender_address, rd, number): # 根据该地址对应期数的用户投注号码,查询该号码的投注金额
if not IsValid(sender_address):
raise Exception("Incorrect address format.")
amount_key = concat(concat(concat(rd, KEY_BETTING_AMOUNT), number), sender_address)
return Get(amount_key)
def query_draws_lottery_user(draws): # 根据期数,查询开奖人的记录
draws_lettry_key = concat(KEY_LOTTERY_USER, draws)
return GetArray(draws_lettry_key)
def draw(): # 开奖
if not if_lottery():
raise Exception("当前期数还在进行时")
draws = Get(KEY_NUMBER_DRAWS) # 当前期数
sender = GetTxSender()
if BalanceOf(sender, [GARD_DENOM])[0] <= 0:
raise Exception("当前账户没有持有 GARD,无法开奖")
sys_pool = syspool() # 当前的系统奖池额度
now_users_pool = stakepool() # 当前用户池额度
now_time = GetTime() # 获取当前时间
prize_number = GetRand(3) # 生成中奖号码
prize_key = concat(KEY_PRIZE_NUMBER, draws)
Put(prize_key, prize_number) # 记录每一期的中奖号码
rand_amount = int(GetRand(4)) # 生成随机开奖奖励 amount
lettry_amount = rand_amount * GARD_FACTOR
draws_lettry_key = concat(KEY_LOTTERY_USER, draws)
PutArray(draws_lettry_key, [sender, str(now_time), str(lettry_amount)]) # 增加开奖人记录
now_users_pool = now_users_pool - lettry_amount
Put(KEY_USER_POOL, now_users_pool) # 先从用户奖池扣除这一部分开奖奖金
# 算出当前中奖人数有多少个
note_key = concat(draws, KEY_CALUCLATION_NOTE)
note_num = Get(note_key) # 当期有多少个投注数, 返回是个int
fist_amount = 0 # 第一名的总额度
second_amount = 0 # 二等奖中奖总token额度
thrid_amount = 0 # 三等奖中奖总token额度
for i in range(1, note_num + 1):
betting_info = query_bets_note(draws, str(i))
number = betting_info[2]
if first_prize_match(draws, number):
fist_amount = int(betting_info[3]) + fist_amount
continue
if second_prize_match(draws, number):
second_amount = int(betting_info[3]) + second_amount
continue
if thrid_prize_match(draws, number):
thrid_amount = int(betting_info[3]) + thrid_amount
continue
award_key = concat(draws, KEY_AMOUNT_EACH_AWARD) # 中奖额度信息
PutArray(award_key, [str(sys_pool), str(now_users_pool), str(fist_amount), str(second_amount),
str(thrid_amount)]) # 记录每一期的中奖额度信息
PutArray(KEY_LAST_NUMBER_DRAWS, [draws, str(now_time)]) # 最后一期期数和期数结束时间
draws = get_period_generation()
Put(KEY_NUMBER_DRAWS, draws) # 期数变更
key = concat(draws, KEY_DRAWS_PID)
now_pid = get_pid()
Put(key, now_pid) # 更改这期的pid
draws_time_key = concat(draws, KEY_PERIODS_TIME)
Put(draws_time_key, now_time) # 当前期号对应的时间戳
all_periods = query_periods_list()
list = []
for i in range(len(all_periods)):
list.append(all_periods[i])
new_list = []
if len(list) == 24:
for i in range(len(list)):
if i != len(list) - 1:
new_list.append(list[i + 1])
else:
break
new_list.append(draws)
PutArray(KEY_PERIODS_LIST, new_list)
else:
list.append(draws)
PutArray(KEY_PERIODS_LIST, list) # 记录之前的期数,最多24个
ContractBalanceSend(sender, GARD_DENOM, lettry_amount) # 给开奖人奖金
return True
def query_bets_note(draws, notes): # 返回对应期数和对应注数的信息
betting_record_key = concat(concat(KEY_NUMBER_BETS_PEER_ISSUE, draws), notes)
betting_info = GetArray(betting_record_key)
return betting_info
def query_amount_award(draws): # 查询每一期的中奖额度信息
award_key = concat(draws, KEY_AMOUNT_EACH_AWARD)
return GetArray(award_key)
def withdraw(draws): # 根据期数兑奖
sender = GetTxSender()
now_draws = Get(KEY_NUMBER_DRAWS) # 当前期数
time = GetTime() # 当前时间
last_number = GetArray(KEY_LAST_NUMBER_DRAWS)
if query_user_withdraw_status(draws, sender):
raise Exception("当期已经兑过奖")
if len(last_number) == 0:
raise Exception("当前期还无法兑奖")
last_draws_time = int(last_number[1]) # 最后一期时间
if int(draws) >= int(now_draws):
raise Exception("当前期无法兑奖")
if len(query_users_number(sender, draws)) == 0:
raise Exception("当前期数没有投注")
if time - last_draws_time >= 60 * 60 * 24 * 1: # 计算是否超过一天
raise Exception("当前已经超过一天未兑奖,无法兑现")
amount_award_list = query_amount_award(draws) # 查询每一期的中奖额度信息
lottery_sys_pool = int(amount_award_list[0]) # 开奖时的系统池额度
lottery_users_pool = int(amount_award_list[1]) # 开奖时的用户池额度
fist_pool_amount = int(amount_award_list[2]) # 开奖时候的一等奖额度
second_pool_amount = int(amount_award_list[3]) # 开奖时候的二等奖额度
thrid_pool_amount = int(amount_award_list[4]) # 开奖时候的三等奖额度
numbers = query_users_number(sender, draws) # 用户投注的所有号码
withdraws_all_amount = 0 # 应该获取到的所有奖金额度
user_pool_amount = 0 # 应该要减去的用户奖池额度
sys_pool_amount = 0 # 应该要减去的系统奖池额度
fist_withdraws_amount = 0 # 用户兑奖的一等奖额度
second_withdraws_amount = 0 # 用户兑奖的二等奖额度
thrid_withdraws_amount = 0 # 用户兑奖的三等奖额度
for num in numbers: # 遍历所有号码
if first_prize_match(draws, num):
fist_amount = query_users_number_amount(sender, draws, num)
withdraws_fist_amount = fist_amount * lottery_users_pool / 10 * 4 / fist_pool_amount + lottery_sys_pool / 1000
user_pool_amount = user_pool_amount + fist_amount * lottery_users_pool / 10 * 4 / fist_pool_amount
sys_pool_amount = sys_pool_amount + lottery_sys_pool / 1000
withdraws_all_amount = withdraws_all_amount + withdraws_fist_amount
fist_withdraws_amount = fist_withdraws_amount + withdraws_fist_amount
continue
if second_prize_match(draws, num):
second_amount = query_users_number_amount(sender, draws, num)
withdraw_second_amount = second_amount * lottery_users_pool / 10 * 2 / second_pool_amount
withdraws_all_amount = withdraws_all_amount + withdraw_second_amount
user_pool_amount = user_pool_amount + withdraw_second_amount
second_withdraws_amount = second_withdraws_amount + withdraw_second_amount
continue
if thrid_prize_match(draws, num):
thrid_amount = query_users_number_amount(sender, draws, num)
withdraws_thrid_amount = thrid_amount * lottery_users_pool / 10 * 1 / thrid_pool_amount
withdraws_all_amount = withdraws_all_amount + withdraws_thrid_amount
user_pool_amount = user_pool_amount + withdraws_thrid_amount
thrid_withdraws_amount = thrid_withdraws_amount + withdraws_thrid_amount
continue
if withdraws_all_amount > 0: # 如果中奖则给其转账,并判断邀请逻辑
inviter_address = query_my_inviter(sender) # 上级地址
event_pool = ppool() # 查询活动奖池额度
sys_pool = syspool() # 查询系统奖池额度
user_pool = stakepool() # 查询活动奖池
if inviter_address and event_pool > 0: # 如果存在邀请者,并或活动奖池大于0
# rd = int(GetRand(1)) # 随机字符串
# pted_event_amount = event_pool / 1000 + event_pool * rd / 1000 # 分配随机 0.1% 到 1% 不等
rd = int(GetRand(4))
pted_event_amount = rd * GARD_FACTOR
sr_key = concat(KEY_SHARED_REWARD, sender) # 被邀请的被推广奖励
sender_reward_list = GetArray(sr_key)
if len(sender_reward_list) == 0:
PutArray(sr_key, [str(0), str(pted_event_amount)])
else:
promotion_amount = sender_reward_list[0] # 推广奖励
promoted_amount = int(sender_reward_list[1]) # 被推广奖励
PutArray(sr_key, [promotion_amount, str(promoted_amount + pted_event_amount)]) # 提交自己的被推广奖励
# rd = int(GetRand(1)) # 随机字符串
# pro_event_amount = event_pool / 1000 + event_pool * rd / 1000 # 分配随机 0.1% 到 1% 不等
pro_event_amount = rd * GARD_FACTOR
sr_key = concat(KEY_SHARED_REWARD, inviter_address) # 推广者的推广奖励
invited_reward_list = GetArray(sr_key) # 邀请者
if len(invited_reward_list) == 0:
PutArray(sr_key, [str(pro_event_amount), str(0)])
else:
promotion_amount = int(invited_reward_list[0]) # 推广奖励
promoted_amount = invited_reward_list[1] # 被推广奖励
PutArray(sr_key, [str(promotion_amount + pro_event_amount), promoted_amount]) # 提交推广者的推广奖励
ContractBalanceSend(sender, GARD_DENOM, pted_event_amount) # 给投注人转入被邀请奖励
ContractBalanceSend(inviter_address, GARD_DENOM, pro_event_amount) # 给邀请人转推广奖励
now_event_pool = event_pool - pted_event_amount - pro_event_amount
Put(KEY_EVENT_POOL, now_event_pool) # 更新活动奖池额度
issue_account = query_issue_account() # 查询总的中奖额度信息
withdraw_account = query_withdraw_account(draws) # 查询该兑奖期的兑奖额度信息
withdraw_account_key = concat(KEY_ISSUE_ACCOUNT, draws)
if len(issue_account) != 0:
old_fist = int(issue_account[0])
old_second = int(issue_account[1])
old_thrid = int(issue_account[2])
PutArray(KEY_ISSUE_ACCOUNT,
[str(old_fist + fist_withdraws_amount), str(old_second + second_withdraws_amount),
str(old_thrid + thrid_withdraws_amount)]) # 提交总的中奖额度信息
else:
PutArray(KEY_ISSUE_ACCOUNT, [str(fist_withdraws_amount), str(second_withdraws_amount),
str(thrid_withdraws_amount)]) # 提交总的中奖额度信息
if len(withdraw_account) != 0:
old_withdraws_fist = int(withdraw_account[0])
old_withdraws_second = int(withdraw_account[1])
old_withdraws_thrid = int(withdraw_account[2])
PutArray(withdraw_account_key, [str(old_withdraws_fist + fist_withdraws_amount),
str(old_withdraws_second + second_withdraws_amount),
str(old_withdraws_thrid + thrid_withdraws_amount)]) # 提交指定期的兑奖额度信息
else:
PutArray(withdraw_account_key, [str(fist_withdraws_amount), str(second_withdraws_amount),
str(thrid_withdraws_amount)]) # 提交指定期的兑奖额度信息
Put(KEY_USER_POOL, user_pool - user_pool_amount) # 提交用户奖池
Put(KEY_SYSTEM_POOL, sys_pool - sys_pool_amount) # 提交系统奖池额度
stake_count_key = concat(KEY_MY_STAKE_COUNT, sender) # 我的投注统计,包括投注的总 token,和获取奖励的总 token
count_value = GetArray(stake_count_key)
betting_amount = count_value[0] # 总共投注
reward_amount = int(count_value[1]) # 获得奖励
PutArray(stake_count_key, [betting_amount, str(reward_amount + withdraws_all_amount)]) # 提交自己投注记录
key = concat(concat(KEY_REDEMPTION_USER, draws), sender) # 兑奖信息
PutArray(key, [str(time), str(withdraws_all_amount)]) # 提交用户的兑奖信息
withdraw_status_key = concat(concat(KEY_WITZHDRAWS_STATUS, draws), sender)
Put(withdraw_status_key, True) # 将用户此期的兑奖状态改成true
ContractBalanceSend(sender, GARD_DENOM, withdraws_all_amount) # 给投注人转入获取的奖励
return True
else:
raise Exception("当前投注没有中奖")
def get_promotion_reward(address): # 查询推广奖励
sr_key = concat(KEY_SHARED_REWARD, address)
return GetArray(sr_key) # 我的推广奖励,我被推广的奖励
def get_redemption_information(sender_address, draws): # 查询该地址对应期数的兑奖信息
if not IsValid(sender_address):
raise Exception("Incorrect address format.")
key = concat(concat(KEY_REDEMPTION_USER, draws), sender_address) # 兑奖信息
return GetArray(key)
def set_event_pool(amount): # 设立活动奖池
sender_address = GetTxSender()
if BalanceOf(sender_address, [GARD_DENOM])[0] < amount: # 判断余额是否足够初始化
raise Exception("余额不足")
event_pool = Get(KEY_EVENT_POOL)
if not event_pool:
ContractBalanceInject(sender_address, GARD_DENOM, amount)
Put(KEY_EVENT_POOL, amount)
return True
balance_amount = event_pool + amount
Put(KEY_EVENT_POOL, balance_amount)
ContractBalanceInject(sender_address, GARD_DENOM, balance_amount)
return True
def ppool(): # 查询活动奖池的额度
return Get(KEY_EVENT_POOL)
def query_prize_number(draws): # 根据期数查询中奖号码
key = concat(KEY_PRIZE_NUMBER, draws)
return Get(key)
def query_user_invitation_code(sender): # 查询地址查看生成的邀请码
if not IsValid(sender):
raise Exception("Incorrect address format.")
key = concat(KEY_INVITATION_CODE, sender)
return Get(key)
def query_invitation_code_user(invitation_code): # 根据邀请码,查询生成邀请码的地址
key = concat(KEY_INVITATION_CODE, invitation_code)
return Get(key)
def query_invitee(sender_address): # 查询被该地址邀请的人
if not IsValid(sender_address):
raise Exception("Incorrect address format.")
key = concat(KEY_INVITATION_RECORD, sender_address)
return GetArray(key)
def query_my_inviter(sender_address): # 查询该地址的上级邀请人
if not IsValid(sender_address):
raise Exception("Incorrect address format.")
key = concat(KEY_INVITED_RECORD, sender_address)
return Get(key)
def invitation_code_generation(): # 邀请码生成
sender = GetTxSender() # 获取当前操作人
for i in range(5, len(sender)):
invitation_code = concat(concat(sender[i], sender[i + 1]), concat(sender[i + 2], sender[i + 3]))
if query_invitation_code_user(invitation_code): # 判断该邀请码是否已经有归属地址
continue
else:
key = concat(KEY_INVITATION_CODE, sender)
Put(key, invitation_code) # 提交用户的邀请码信息
key = concat(KEY_INVITATION_CODE, invitation_code)
Put(key, sender) # 提交邀请码对应的人的信息
break
return True
def first_prize_match(draws, number): # 一等奖匹配规则
prize_number = query_prize_number(draws) # 期数的中奖号码
if prize_number == number:
return True
return False
def second_prize_match(draws, number): # 二等奖匹配规则
prize_len = len(number) # prize_len == 3
prize_number = query_prize_number(draws)
result = False
for i in range(prize_len):
if i < prize_len - 1:
if substr(number, i, 2) == substr(prize_number, i, 2):
result = True
break
else:
if substr(number, i, 1) == substr(prize_number, i, 1) and substr(number, 0, 1) == substr(prize_number, 0,
1):
result = True
break
return result
def thrid_prize_match(draws, number): # 三等奖匹配规则
prize_len = len(number) # prize_len == 3
prize_number = query_prize_number(draws)
result = False
for i in range(prize_len):
if substr(number, i, 1) == substr(prize_number, i, 1):
result = True
break
return result
def get_period_generation(): # 期数生成器
now_time = GetTime()
now_time = TimeFormat(now_time) # 格式 2019-09-25 17:15:30
time = split(now_time, " ") # 分成两个元素
time_01 = time[0] # 年月日
time_02 = time[1] # 分时秒
time_01 = split(time_01, "-")
time_02 = split(time_02, ":")
a = join("", time_01)
b = time_02[0]
period = concat(a, b) # 拼接
return period
def get_stake_account(address): # 我的投注统计
stake_count_key = concat(KEY_MY_STAKE_COUNT, address)
return GetArray(stake_count_key)
def get_stake_issue(address): # 我的投注列表
stake_all_key = concat(KEY_MY_ALL_STAKE, address)
return GetArray(stake_all_key) # 期数列表
def get_periods_exceeds(address, rd): # 返回一个一天内的投注列表
stake_all_key = concat(KEY_MY_ALL_STAKE, address) # 我所有的投注期号记录,只记录三天以内的
stake_all_value = GetArray(stake_all_key) # 期数列表
now_time = GetTime()
list = []
for i in range(len(stake_all_value)):
time = query_periods_time(stake_all_value[i]) # 根据期数查询时间戳
sub = now_time - time
if rd != stake_all_value[i] and 0 < sub <= 60 * 60 * 24 * 1: # 小于1天和不重复的
list.append(stake_all_value[i])
list.append(rd)
return list
def query_issue_account(): # 查询累计中奖额度信息
return GetArray(KEY_ISSUE_ACCOUNT)
def query_withdraw_account(rd): # 查询指定期数的中奖额度信息
withdraw_account_key = concat(KEY_ISSUE_ACCOUNT, rd)
return GetArray(withdraw_account_key)
def query_periods_time(draws): # 查询期数对应的时间戳
draws_time_key = concat(draws, KEY_PERIODS_TIME)
return Get(draws_time_key) # 当前期号对应的时间戳
def query_periods_list(): # 查询所有的期数列表,仅显示24个
return GetArray(KEY_PERIODS_LIST)
def query_user_bet_num(rd, sender_address): # 查询用户对该期数的投注次数
user_bets_key = concat(concat(KEY_USER_BETS, sender_address), rd) # 用户投注次数
return Get(user_bets_key)
def query_user_withdraw_status(rd, address): # 查询用户指定期数的兑奖状态
withdraw_status_key = concat(concat(KEY_WITZHDRAWS_STATUS, rd), address)
return Get(withdraw_status_key)