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

QuickLotteryTON

عقد ذكي لليانصيب العشوائي البسيط على بلوكتشين TON

عنوان العقد: EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 تم النسخ!

Tonviewer | Verifier

الملخص

كويك لوتاري TON هو عقد ذكي بسيط على بلوكتشين TON. يدخل المشاركون عبر استدعاء enter وإرسال 1 أو أكثر TON (أعداد صحيحة فقط، بدون كسور).

بعد أن يشارك 10+ أشخاص ويمر 24 ساعة، يمكن لأي مشارك تنفيذ draw. سيختار العقد عشوائياً حوالي 10٪ من المشاركين ويوزع الجائزة بينهم.

هذا كل شيء!

يمكنك رؤية الكود المصدري بالأسفل (الانتقال إلى الكود).

كيفية الدخول

للدخول إلى اليانصيب، أرسل ببساطة 1 TON (أو 2، 3، 4 ...) إلى عنوان العقد EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 تم النسخ! مع التعليق enter (استخدم الكلمة بالضبط، بدون فراغات وبأحرف صغيرة).

الاستجابات

إذا أرسلت مبلغًا يحتوي على كسور (مثل 1.002 TON)، سيتم إعادة أموالك مع رسالة Can only enter with 1 TON or multiples of 1 TON.

إذا كنت قد شاركت بالفعل في هذه الجولة، ستُعاد أموالك مع الرسالة You have already entered this draw.

إذا نجح دخولك، ستحصل على الرسالة Successfully entered the lottery draw with 1 TON!

السحب

يجب على مشارك واحد فقط إجراء السحب في كل جولة. عادةً لست بحاجة لفعل ذلك، حيث سيتم تلقائيًا بواسطة مشارك آخر. فقط ادخل وانتظر النتائج بعد 24 ساعة!

إذا أردت تنفيذ السحب، أرسل 0.05 TON أو أكثر (حسب عدد المشاركين، لتغطية الغاز) إلى عنوان العقد EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6 تم النسخ! مع التعليق draw.

إذا كان السحب السابق قبل أقل من 24 ساعة، ستُعاد أموالك مع رسالة Cannot draw yet, X seconds remaining until next draw.

إذا كان عدد المشاركين أقل من 10، ستُعاد أموالك مع رسالة Not enough participants for draw.

وإلا سيختار الكود حوالي 10٪ من المشاركين عشوائيًا ويوزع عليهم الجائزة! 1٪ يُحتجز كرسوم غاز.

الفائزون يتلقون أموالهم مع رسالة Congratulations! You won 10000000000 nanoTON in the lottery draw!

الطرق

في Verifier أو TonViewer يمكنك أيضًا استدعاء دوال العقد. الدوال المتاحة:

النتائج تكون بنظام hex ويجب تحويلها إلى عشري.

الكود المصدري

يمكن أيضاً التحقق من الكود عبر TON Verifier:

  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. }