|
| 1 | +() recv_internal(int my_balance, int msg_value, cell in_msg_cell, slice in_msg) impure { |
| 2 | + var cs = in_msg_cell.begin_parse(); |
| 3 | + var flags = cs~load_uint(4); |
| 4 | + |
| 5 | + if (flags & 1) { |
| 6 | + ;; ignore bounced messages |
| 7 | + return (); |
| 8 | + } |
| 9 | + |
| 10 | + var sender = cs~load_msg_addr(); |
| 11 | + (int wc, _) = parse_std_addr(sender); |
| 12 | + throw_if(31, wc); ;; we don't want waste too much on fwd_fee, ensure wc = 0 |
| 13 | + |
| 14 | + var (ends_at, jackpot, last_player, seqno) = load_data(); |
| 15 | + if (ends_at < now()) { |
| 16 | + ;; we have a WINNER |
| 17 | + var msg = begin_message(0x10, last_player, jackpot).store_comment(text::winner()); |
| 18 | + send_raw_message(msg.end_cell(), 0); |
| 19 | + |
| 20 | + var log = begin_log_msg() |
| 21 | + .store_uint(2, 8) ;; tag |
| 22 | + .store_uint(jackpot, 64); |
| 23 | + send_raw_message(log.end_cell(), 0); |
| 24 | + |
| 25 | + ;; return msg_value |
| 26 | + var msg = begin_message(0x10, sender, 0); |
| 27 | + send_raw_message(msg.end_cell(), 64 + 2); |
| 28 | + |
| 29 | + ;; withdraw the rest |
| 30 | + var msg = begin_message(0x10, settings::owner(), 0); |
| 31 | + send_raw_message(msg.end_cell(), 128 + 2); |
| 32 | + |
| 33 | + ;; restart the game |
| 34 | + return save_data(0xffffffff, 0, sender, 0); |
| 35 | + } |
| 36 | + |
| 37 | + int bet = msg_value; |
| 38 | + throw_if(30, bet < settings::min_bet()); |
| 39 | + |
| 40 | + int fee = muldiv(bet, settings::owner_fee(), 100); |
| 41 | + int rest = bet - fee; |
| 42 | + jackpot += rest; |
| 43 | + last_player = sender; |
| 44 | + seqno += 1; |
| 45 | + |
| 46 | + (int utime_since, int utime_until) = current_round(); |
| 47 | + int time = now(); |
| 48 | + int delay = settings::delay(); |
| 49 | + if (time > utime_until - delay * 2) | (time < utime_since + settings::big_delay()) { |
| 50 | + delay = settings::big_delay(); |
| 51 | + } |
| 52 | + ends_at = time + delay; |
| 53 | + |
| 54 | + ;; testnet only (delete me) |
| 55 | + ;; throw_if(1000, utime_until - utime_since > 10000); |
| 56 | + |
| 57 | + int reward = 0; |
| 58 | + ifnot (seqno % 10) { |
| 59 | + reward = settings::start_reward(); |
| 60 | + ;; unroll loop (lower gas fees) |
| 61 | + ifnot (seqno % 100) { reward *= 10; |
| 62 | + ifnot (seqno % 1000) { reward *= 10; |
| 63 | + ifnot (seqno % 10000) { reward *= 10; |
| 64 | + ifnot (seqno % 100000) { reward *= 10; |
| 65 | + ifnot (seqno % 1000000) { reward *= 10; |
| 66 | + ifnot (seqno % 10000000) { reward *= 10; |
| 67 | + } } } } } } |
| 68 | + } |
| 69 | + |
| 70 | + if (reward > 0) { |
| 71 | + jackpot -= reward; |
| 72 | + |
| 73 | + ;; send reward |
| 74 | + slice txt = (reward > msg_value ? text::reward() : text::payback()); |
| 75 | + ifnot (seqno % 1000000) { |
| 76 | + txt = text::big_reward(); |
| 77 | + } |
| 78 | + var msg = begin_message(0x10, sender, reward).store_comment(txt); |
| 79 | + send_raw_message(msg.end_cell(), 1); |
| 80 | + } |
| 81 | + |
| 82 | + var log = begin_log_msg() |
| 83 | + .store_uint(1, 8) ;; tag |
| 84 | + .store_uint(jackpot, 64) |
| 85 | + .store_uint(seqno, 40) |
| 86 | + .store_uint(reward, 64) |
| 87 | + .store_uint(ends_at, 32); |
| 88 | + send_raw_message(log.end_cell(), 0); |
| 89 | + |
| 90 | + if (my_balance - reward - jackpot > settings::withdraw_at()) { |
| 91 | + ;; auto-withdraw owner balance |
| 92 | + ;; reserve some grams for gas fees |
| 93 | + raw_reserve(jackpot + (1 << 30), 0); |
| 94 | + var msg = begin_message(0x10, settings::owner(), 0).store_comment(text::withdrawal()); |
| 95 | + send_raw_message(msg.end_cell(), 128); |
| 96 | + } |
| 97 | + |
| 98 | + save_data(ends_at, jackpot, last_player, seqno); |
| 99 | + |
| 100 | + ;; we suppose that fee (0.2 ton) is always enough for paying blockchain fees |
| 101 | + ;; we could check the config, but it seems to be overcomplication |
| 102 | + ;; we ensure that sender wc is 0 to limit fwd_fee |
| 103 | + ;; the max amount of gas used is a constant |
| 104 | +} |
0 commit comments