English Русский فارسی العربية Türkçe Español

QuickLotteryTON

TON Blokzinciri üzerinde basit bir rastgele piyango için akıllı sözleşme

Sözleşme Adresi: EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 Kopyalandı!

Tonviewer | Verifier

Özet

QuickLotteryTON, TON blokzinciri üzerinde çalışan basit bir akıllı sözleşmedir. Katılımcılar enter komutunu kullanarak 1 veya daha fazla TON (tam sayı, küsurat yok) göndererek çekilişe katılır.

10+ katılımcı giriş yaptıktan ve 24 saat geçtikten sonra, herhangi bir katılımcı draw komutunu çağırabilir. Yaklaşık %10 katılımcı rastgele seçilerek havuz paylaştırılır.

Hepsi bu!

Kaynak kodu aşağıda görebilirsiniz (koda git).

Nasıl Katılınır

Çekilişe katılmak için 1 TON (veya 2, 3, 4 vb.) tutarı EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 Kopyalandı! adresine enter yorumu ile gönderin (tam olarak bu kelime, küçük harf ve boşluksuz).

Yanıtlar

Eğer kesirli miktar gönderirseniz (ör. 1.002 TON), paranız şu mesajla geri gelir: Can only enter with 1 TON or multiples of 1 TON.

Bu turda zaten katıldıysanız, paranız şu mesajla geri gelir: You have already entered this draw.

Başarıyla giriş yaptıysanız şu mesajı alırsınız: Successfully entered the lottery draw with 1 TON!

Çekiliş

Her turda yalnızca bir kişinin çekiliş yapması gerekir. Genellikle gerekmez, katılımcılardan biri otomatik olarak yapar. Sadece katılın ve 24 saat sonra sonucu bekleyin!

Çekiliş yapmak isterseniz, 0.05 TON veya daha fazlasını (katılımcı sayısına göre gaz için yeterli) EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 Kopyalandı! adresine draw yorumu ile gönderin.

Önceki çekiliş 24 saatten kısa süre önce yapıldıysa, paranız şu mesajla geri gelir: Cannot draw yet, X seconds remaining until next draw.

Eğer bu turda 10’dan az kişi varsa, paranız şu mesajla geri gelir: Not enough participants for draw.

Aksi halde kod yaklaşık %10 katılımcıyı rastgele seçer ve havuzu onlara dağıtır! %1 gaz ücreti sözleşme tarafından tutulur.

Kazanan şu mesajı alır: Congratulations! You won 10000000000 nanoTON in the lottery draw!

Metodlar

Verifier veya TonViewer bağlantısından sözleşme getter metodlarını da çağırabilirsiniz. Kullanılabilir metodlar:

Sonuçlar hex formatındadır, ondalığa çevrilmesi gerekir.

Kaynak Kodu

Kaynak kodu ayrıca TON Verifier ile doğrulanabilir:

  1. /**
  2. QuickLotteryTON contract
  3. Explorers:
  4. - Tonviewer: https://tonviewer.com/EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6
  5. - Verifier: https://verifier.ton.org/EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6
  6. Usage:
  7. - Enter lottery:
  8. • Send ≥ 1 TON (multiples of 1 TON) with comment "enter".
  9. • Each address may enter once per draw.
  10. - Getters:
  11. • balance() → current contract balance (nanoTON).
  12. • betPool() → total TON in the current lottery pool (nanoTON).
  13. • participantCount() → number of unique participants.
  14. - Draw:
  15. • Anyone can trigger via sending any amount of TON with comment "draw".
  16. • At most once every 24h.
  17. • Requires ≥ 10 participants before allowing draw.
  18. - Payout:
  19. • 1% fee to deployer for transaction fees.
  20. • Remaining pool distributed proportionally among ~10% of participants, chosen randomly.
  21. */
  22. import "@stdlib/deploy";
  23. const NANO_COUNT: Int = 1_000_000_000;
  24. message TransferEvent {
  25. amount: Int as int64;
  26. recipient: Address;
  27. }
  28. message EntryEvent {
  29. sender: Address;
  30. amount: Int as int64;
  31. }
  32. contract QuickLotteryTON with Deployable {
  33. const DRAW_EVERY: Int = 24 * 60 * 60; // Once every day at most.
  34. const MIN_PARTICIPANTS: Int = 10;
  35. lastDrawTime: Int;
  36. participants: map<Address, Int>;
  37. participantCount: Int;
  38. betPool: Int;
  39. deployer: Address;
  40. init() {
  41. nativeReserve(ton("1.0"), ReserveAtMost | ReserveBounceIfActionFail);
  42. self.deployer = sender();
  43. self.participantCount = 0;
  44. self.betPool = 0;
  45. self.participants = emptyMap();
  46. self.lastDrawTime = now();
  47. }
  48. receive("enter") {
  49. let amount: Int = context().value;
  50. if (amount < NANO_COUNT || amount % NANO_COUNT != 0) {
  51. self.reply("Can only enter with 1 TON or multiples of 1 TON.".asComment());
  52. return;
  53. }
  54. let sender: Address = sender();
  55. if (self.participants.exists(sender)) {
  56. self.reply("You have already entered this draw.".asComment());
  57. return;
  58. }
  59. self.participants.set(sender, amount);
  60. self.participantCount += 1;
  61. self.betPool += amount;
  62. // Emit entry event
  63. emit(EntryEvent{sender: sender, amount: amount}.toCell());
  64. // Send confirmation message to participant with bet amount
  65. let sb: StringBuilder = beginString();
  66. sb.append("Successfully entered the lottery draw with ");
  67. sb.append((amount / NANO_COUNT).toString());
  68. sb.append(" TON!");
  69. send(SendParameters{
  70. to: sender,
  71. bounce: false,
  72. value: 0, // No TON refunded
  73. mode: SendIgnoreErrors | SendPayFwdFeesSeparately,
  74. body: sb.toString().asComment()
  75. });
  76. }
  77. receive("draw") {
  78. // Check time since last draw
  79. let remaining: Int = self.DRAW_EVERY - (now() - self.lastDrawTime);
  80. if (remaining > 0) {
  81. let sb: StringBuilder = beginString();
  82. sb.append("Cannot draw yet, ");
  83. sb.append(remaining.toString());
  84. sb.append(" seconds remaining until next draw.");
  85. self.reply(sb.toString().asComment());
  86. return;
  87. }
  88. if (self.participantCount < self.MIN_PARTICIPANTS) {
  89. self.reply("Not enough participants for draw.".asComment());
  90. return;
  91. }
  92. // Send 1% fee to owner
  93. let ownerFee: Int = self.betPool / 100;
  94. if (ownerFee > 0) {
  95. emit(TransferEvent{amount: ownerFee, recipient: self.deployer}.toCell());
  96. send(SendParameters{
  97. to: self.deployer,
  98. bounce: true,
  99. value: ownerFee,
  100. mode: SendIgnoreErrors
  101. });
  102. }
  103. // Determine prize pool and winner count
  104. let pool: Int = self.betPool - ownerFee;
  105. let targetWinners: Int = self.participantCount / 10; // 10% winners
  106. // Select winners
  107. let winners: map<Address, Int> = emptyMap();
  108. let winnerCount: Int = 0;
  109. let totalWinnerWeight: Int = 0;
  110. // First pass: try to select winners with 10% chance
  111. while (winnerCount == 0) {
  112. foreach (adr, winnerWeight in self.participants) {
  113. if (random(1, 100) <= 10 && winnerCount < targetWinners) {
  114. winners.set(adr, winnerWeight);
  115. totalWinnerWeight += winnerWeight;
  116. winnerCount += 1;
  117. }
  118. }
  119. }
  120. // Distribute prizes proportionally to bet amounts
  121. foreach (winnerAddress, winnerWeight in winners) {
  122. let prize: Int = pool * winnerWeight / totalWinnerWeight;
  123. if (prize > 0) {
  124. // Create notification message with prize amount
  125. let sb: StringBuilder = beginString();
  126. sb.append("Congratulations! You won ");
  127. sb.append((prize).toString());
  128. sb.append(" nanoTON in the lottery draw!");
  129. // Emit transfer event
  130. emit(TransferEvent{amount: prize, recipient: winnerAddress}.toCell());
  131. // Send prize with notification message in a single transaction
  132. send(SendParameters{
  133. to: winnerAddress,
  134. bounce: true,
  135. value: prize,
  136. mode: SendIgnoreErrors,
  137. body: sb.toString().asComment()
  138. });
  139. }
  140. }
  141. // Reset lottery
  142. self.participantCount = 0;
  143. self.betPool = 0;
  144. self.participants = emptyMap();
  145. self.lastDrawTime = now();
  146. }
  147. get fun participantCount(): Int {
  148. return self.participantCount;
  149. }
  150. get fun betPool(): Int {
  151. return self.betPool;
  152. }
  153. get fun balance(): Int {
  154. return myBalance();
  155. }
  156. }