Описание
QuickLotteryTON — это простой смарт-контракт в блокчейне 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 вы также можете вызвать методы-геттеры контракта. Доступные методы:
getBetPool(): возвращает общее количество nanoTON в текущем пуле ставок.getParticipantCount(): возвращает количество участников текущего раунда.
Результаты в hex, требуется конвертация в десятичное значение.
Исходный код
Исходный код также можно проверить через TON Verifier:
/**QuickLotteryTON contractExplorers:- Tonviewer: https://tonviewer.com/EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6- Verifier: https://verifier.ton.org/EQCsihC1Z6fHRsFbz9N3sCHC6sUfvnlz4RbelethC-6Q34y6Usage:- Enter lottery:• Send ≥ 1 TON (multiples of 1 TON) with comment "enter".• Each address may enter once per draw.- Getters:• balance() → current contract balance (nanoTON).• betPool() → total TON in the current lottery pool (nanoTON).• participantCount() → number of unique participants.- Draw:• Anyone can trigger via sending any amount of TON with comment "draw".• At most once every 24h.• Requires ≥ 10 participants before allowing draw.- Payout:• 1% fee to deployer for transaction fees.• Remaining pool distributed proportionally among ~10% of participants, chosen randomly.*/import "@stdlib/deploy";const NANO_COUNT: Int = 1_000_000_000;message TransferEvent {amount: Int as int64;recipient: Address;}message EntryEvent {sender: Address;amount: Int as int64;}contract QuickLotteryTON with Deployable {const DRAW_EVERY: Int = 24 * 60 * 60; // Once every day at most.const MIN_PARTICIPANTS: Int = 10;lastDrawTime: Int;participants: map<Address, Int>;participantCount: Int;betPool: Int;deployer: Address;init() {nativeReserve(ton("1.0"), ReserveAtMost | ReserveBounceIfActionFail);self.deployer = sender();self.participantCount = 0;self.betPool = 0;self.participants = emptyMap();self.lastDrawTime = now();}receive("enter") {let amount: Int = context().value;if (amount < NANO_COUNT || amount % NANO_COUNT != 0) {self.reply("Can only enter with 1 TON or multiples of 1 TON.".asComment());return;}let sender: Address = sender();if (self.participants.exists(sender)) {self.reply("You have already entered this draw.".asComment());return;}self.participants.set(sender, amount);self.participantCount += 1;self.betPool += amount;// Emit entry eventemit(EntryEvent{sender: sender, amount: amount}.toCell());// Send confirmation message to participant with bet amountlet sb: StringBuilder = beginString();sb.append("Successfully entered the lottery draw with ");sb.append((amount / NANO_COUNT).toString());sb.append(" TON!");send(SendParameters{to: sender,bounce: false,value: 0, // No TON refundedmode: SendIgnoreErrors | SendPayFwdFeesSeparately,body: sb.toString().asComment()});}receive("draw") {// Check time since last drawlet remaining: Int = self.DRAW_EVERY - (now() - self.lastDrawTime);if (remaining > 0) {let sb: StringBuilder = beginString();sb.append("Cannot draw yet, ");sb.append(remaining.toString());sb.append(" seconds remaining until next draw.");self.reply(sb.toString().asComment());return;}if (self.participantCount < self.MIN_PARTICIPANTS) {self.reply("Not enough participants for draw.".asComment());return;}// Send 1% fee to ownerlet ownerFee: Int = self.betPool / 100;if (ownerFee > 0) {emit(TransferEvent{amount: ownerFee, recipient: self.deployer}.toCell());send(SendParameters{to: self.deployer,bounce: true,value: ownerFee,mode: SendIgnoreErrors});}// Determine prize pool and winner countlet pool: Int = self.betPool - ownerFee;let targetWinners: Int = self.participantCount / 10; // 10% winners// Select winnerslet winners: map<Address, Int> = emptyMap();let winnerCount: Int = 0;let totalWinnerWeight: Int = 0;// First pass: try to select winners with 10% chancewhile (winnerCount == 0) {foreach (adr, winnerWeight in self.participants) {if (random(1, 100) <= 10 && winnerCount < targetWinners) {winners.set(adr, winnerWeight);totalWinnerWeight += winnerWeight;winnerCount += 1;}}}// Distribute prizes proportionally to bet amountsforeach (winnerAddress, winnerWeight in winners) {let prize: Int = pool * winnerWeight / totalWinnerWeight;if (prize > 0) {// Create notification message with prize amountlet sb: StringBuilder = beginString();sb.append("Congratulations! You won ");sb.append((prize).toString());sb.append(" nanoTON in the lottery draw!");// Emit transfer eventemit(TransferEvent{amount: prize, recipient: winnerAddress}.toCell());// Send prize with notification message in a single transactionsend(SendParameters{to: winnerAddress,bounce: true,value: prize,mode: SendIgnoreErrors,body: sb.toString().asComment()});}}// Reset lotteryself.participantCount = 0;self.betPool = 0;self.participants = emptyMap();self.lastDrawTime = now();}get fun participantCount(): Int {return self.participantCount;}get fun betPool(): Int {return self.betPool;}get fun balance(): Int {return myBalance();}}





