Смарт-контракты с Chainlink VRF для колеса фортуны

Разработка колеса фортуны на смарт-контрактах с Chainlink VRF При разработке on-chain-игр самая критичная точка — источник случайности. Если злоумышленник может предсказать или повлиять на результат, теряется доверие. В колесе фортуны на смарт-контрактах мы решаем эту задачу через Chainlink VRF v

Направления блокчейн-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1003

Разработка колеса фортуны на смарт-контрактах с Chainlink VRF

При разработке on-chain-игр самая критичная точка — источник случайности. Если злоумышленник может предсказать или повлиять на результат, теряется доверие. В колесе фортуны на смарт-контрактах мы решаем эту задачу через Chainlink VRF v2.5 — единственный оракул с криптографическим доказательством результата. Контракт запрашивает случайное число, и только после верификации proof определяет выигрышный сектор. Ни оператор, ни майнер не могут повлиять на исход — полная доказуемость (trustless).

Такая архитектура экономит до $10,000 на аудите, так как VRF-модуль уже прошел формальную верификацию Chainlink. На одном из реализованных проектов мы сократили затраты на аудит с $25,000 до $15,000 за счет использования проверенного VRF.

Параметр house edge — математическое преимущество оператора. Мы рассчитываем его как отношение суммы взвешенных множителей к общему весу. Например, колесо с секторами 2x-50x и сектором MISS даёт RTP 96.5% (house edge 3.5%). Этот параметр зашивается в контракт и не может быть изменён после деплоя — игроки верифицируют математику в эфирскане.

Почему Chainlink VRF — единственное приемлемое решение?

Любые другие источники рандома имеют уязвимости:

  • block.timestamp и block.prevrandao — майнер может отклонить транзакцию при невыгодном исходе (grinding attack).
  • On-chain хэш будущего блока — оператор может отказаться от раскрытия.
  • Off-chain оракул без proof — полное доверие к оператору.

Chainlink VRF v2.5 генерирует случайное число с криптографическим доказательством, которое проверяется в контракте. Наш опыт показывает: эта технология экономит до 80% времени на аудите (около $10,000), так как алгоритм уже верифицирован согласно документации Chainlink VRF. Кроме того, VRF в 100 раз надежнее block.timestamp по критерию защищенности от манипуляций.

Настройка VRF подписки

Создается subscription ID, пополняется LINK токенами. Контракт делает запросы через этот ID. Пример интеграции:

import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract WheelOfFortune is VRFConsumerBaseV2Plus { bytes32 constant KEY_HASH = 0x9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded86805; uint256 immutable subscriptionId; uint32 constant CALLBACK_GAS_LIMIT = 100_000; uint16 constant REQUEST_CONFIRMATIONS = 3; struct Spin { address player; uint256 betAmount; uint8 wheelType; uint256 requestId; bool fulfilled; } mapping(uint256 => Spin) public spins; mapping(address => uint256) public pendingSpins; event SpinRequested(address indexed player, uint256 indexed requestId, uint256 betAmount); event SpinResult(address indexed player, uint256 indexed requestId, uint8 sector, uint256 payout); function spin(uint8 wheelType) external payable { require(msg.value >= MIN_BET && msg.value <= MAX_BET, "Invalid bet"); require(pendingSpins[msg.sender] == 0, "Spin pending"); uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: KEY_HASH, subId: subscriptionId, requestConfirmations: REQUEST_CONFIRMATIONS, callbackGasLimit: CALLBACK_GAS_LIMIT, numWords: 1, extraArgs: VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ) }) ); spins[requestId] = Spin({ player: msg.sender, betAmount: msg.value, wheelType: wheelType, requestId: requestId, fulfilled: false }); pendingSpins[msg.sender] = requestId; emit SpinRequested(msg.sender, requestId, msg.value); } function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { Spin storage s = spins[requestId]; require(!s.fulfilled, "Already fulfilled"); s.fulfilled = true; delete pendingSpins[s.player]; uint8 sector = _getSector(randomWords[0], s.wheelType); uint256 payout = _calculatePayout(s.betAmount, sector); if (payout > 0) { payable(s.player).transfer(payout); } emit SpinResult(s.player, requestId, sector, payout); } } 

Как рассчитать секторы колеса и house edge?

Секторы определяются весами (weight) и множителями. House edge настраивается под требования заказчика — обычно от 3% до 10%. Пример стандартного колеса:

struct Sector { string name; uint16 weight; uint16 multiplier; } Sector[] standardWheel = [ Sector("2x", 4000, 200), Sector("3x", 2000, 300), Sector("5x", 1500, 500), Sector("10x", 800, 1000), Sector("20x", 300, 2000), Sector("50x", 100, 5000), Sector("MISS", 1300, 0), ]; 

RTP рассчитывается как sum(weight * multiplier) / 10000. Для этого колеса RTP = 96,5% (house edge 3,5%). Математика верифицируется в контракте.

Какие блокчейны лучше всего подходят для развертывания?

Сеть Gas за спин Время VRF Ликвидность
Ethereum ~$50-100 3-5 блоков Высокая
Arbitrum ~$0.1-0.5 1-3 блока Средняя
Base ~$0.01-0.1 1-2 блока Растущая
Polygon ~$0.01-0.05 1-2 блока Высокая

Для игр с высоким объемом ставок оптимальны Base или Polygon: стоимость транзакции практически нулевая, а VRF приходит за 1-2 блока. Для премиум-проектов с крупными ставками лучше подходит Ethereum, несмотря на высокий газ — доверие игроков выше.

Какая инфраструктура нужна для production?

Компонент Технология
Smart contracts Solidity + Foundry + OpenZeppelin
VRF Chainlink VRF v2.5
Frontend React + wagmi + viem
Анимация Framer Motion / GSAP
События viem watchContractEvent
NFT ERC-721 (бусты) + ERC-1155 (косметика)
Развертывание Arbitrum / Base (низкий газ)

Что входит в работу?

  • Дизайн секторов и математическая модель (RTP, house edge)
  • Смарт-контракты с VRF интеграцией, LP pool, NFT
  • Frontend с анимацией колеса, ожиданием VRF, wallet connect
  • Тестирование (unit + integration + fork тесты)
  • Аудит безопасности (рекомендуем сторонний аудит)
  • Документация кода и deploy-инструкции
  • Поддержка 1 месяц после запуска

Мы имеем 5+ лет опыта в блокчейн-разработке и более 10 смарт-контрактов в production. Свяжитесь с нами для оценки вашего проекта — закажите консультацию, сроки и стоимость рассчитываются индивидуально.

Процесс работы

Закажите разработку и получите:

  1. Game design (3-5 дней) — согласование секторов, RTP, механик.
  2. Смарт-контракты (2-3 недели) — код с тестами.
  3. Frontend (2-3 недели) — анимации, интеграция.
  4. Аудит и деплой (1 неделя) — развертывание и проверка.

Базовая версия без LP и NFT — от 4 недель. Полная с LP pool, jackpot, NFT — от 8 недель. Все проекты ведем под ключ.

Анимация колеса с учетом VRF

Анимация — детерминированная от результата on-chain. После получения события SpinResult фронтенд крутит колесо на угол, соответствующий сектору. Результат уже известен, анимация — лишь визуализация.

function animateWheel(sector: number, totalSectors: number, onComplete: () => void) { const sectorAngle = 360 / totalSectors; const targetAngle = 360 * 5 + sector * sectorAngle; wheelElement.style.transition = 'transform 4s cubic-bezier(0.17, 0.67, 0.12, 0.99)'; wheelElement.style.transform = `rotate(${targetAngle}deg)`; setTimeout(onComplete, 4000); } 

Время ожидания VRF на Ethereum — 3-5 блоков (~36-60 сек). На L2 — 1-3 блока. Показываем анимацию сразу, а финальный спин с результатом после ответа.

Дополнительные механики

NFT бусты: ERC-721 токены дают +10% к выигрышу, бесплатный спин раз в 24 часа, доступ к premium колесу. Jackpot: 1-2% каждой ставки пополняет пул. Сектор JACKPOT (вероятность 0.1%) забирает весь пул. Психологически мощный триггер. Daily bonus: бесплатный спин с лимитом выплаты. Повышает удержание.

Liquidity pool — пользователи вносят ETH и получают долю прибыли от house edge. Пример реализации:

mapping(address => uint256) public lpShares; uint256 public totalShares; uint256 public houseBalance; function addLiquidity() external payable { uint256 shares = totalShares == 0 ? msg.value : (msg.value * totalShares) / houseBalance; lpShares[msg.sender] += shares; totalShares += shares; houseBalance += msg.value; } function removeLiquidity(uint256 shares) external { require(lpShares[msg.sender] >= shares, "Insufficient shares"); uint256 amount = (shares * houseBalance) / totalShares; require(houseBalance - amount >= MIN_BANKROLL, "Insufficient bankroll"); lpShares[msg.sender] -= shares; totalShares -= shares; houseBalance -= amount; payable(msg.sender).transfer(amount); } 

Минимальный банкролл = MAX_BET * max_multiplier. При 50x и 1 ETH — 50 ETH резерва. Обращайтесь за разработкой под ключ — получите бесплатную оценку вашего проекта. Наша команда имеет сертификаты по Solidity и опыт аудита.