Blackjack на блокчейні: VRF та чесність

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1305 послуг
Blackjack на блокчейні: VRF та чесність
Середній
~5 днів
Часті запитання

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

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1351
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    951
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1186
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    642
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    922

Уявіть: ви хочете запустити онлайн-казино з Blackjack на блокчейні. Проблема — як забезпечити випадковість карт, не довіряючи централізованому серверу? В off-chain казино сервер здає карти, але гравець не бачить колоду. On-chain все прозоро — будь-хто може прочитати storage контракту. Якщо ми заздалегідь згенеруємо deck і збережемо, гравець побачить усі майбутні карти. Рішення — commit-reveal з VRF або Mental Poker. Ми використовуємо Chainlink VRF, але з оптимізацією: генеруємо весь deck одним запитом, а потім карти відкриваються поетапно без додаткових VRF. Наша команда з понад 7 років досвіду в Web3 реалізувала 20+ блокчейн-ігор та DeFi-проектів. Зв'яжіться з нами, щоб отримати консультацію з архітектури та аудиту.

Як Chainlink VRF забезпечує випадковість?

Chainlink VRF генерує верифіковане випадкове число off-chain із криптографічним доказом, яке перевіряється on-chain. Ніхто — ні гравець, ні оператор — не може передбачити результат. Це в 10 разів надійніше, ніж зберігання seed на контракті.

Флоу для Blackjack:

  1. Гравець робить ставку, контракт запитує VRF
  2. VRF fulfillment (через callback) — контракт отримує random, генерує deck або перші карти
  3. Гравець вирішує: hit або stand
  4. Якщо hit — новий VRF запит для наступної карти

Проблема з "якщо hit": кожен VRF запит — затримка (1-3 блоки) та додатковий LINK. Для реалтайм-гри некомфортно.

Оптимізація: запитати весь deck одразу — блокчейн казино blackjack

contract Blackjack is VRFConsumerBaseV2Plus {
    struct Game {
        address player;
        uint256 bet;
        uint8[] deck;     // всі 52 карти в зашифрованому порядку
        uint8 playerIdx;  // поточний індекс в декі
        uint8 dealerIdx;
        bool active;
    }
    
    mapping(uint256 => Game) public games;         // requestId -> game
    mapping(address => uint256) public playerGame; // player -> gameId
    
    function startGame() external payable {
        require(msg.value >= MIN_BET, "Below minimum bet");
        
        uint256 requestId = s_vrfCoordinator.requestRandomWords(
            VRFV2PlusClient.RandomWordsRequest({
                keyHash: KEY_HASH,
                subId: subscriptionId,
                requestConfirmations: 3,
                callbackGasLimit: 300000,
                numWords: 1, // одне велике число для shuffle
                extraArgs: VRFV2PlusClient._argsToBytes(
                    VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
                )
            })
        );
        
        games[requestId] = Game({
            player: msg.sender,
            bet: msg.value,
            deck: new uint8[](0),
            playerIdx: 0,
            dealerIdx: 4, // дилер бере карти з позиції 4
            active: false // стане true після fulfillment
        });
        playerGame[msg.sender] = requestId;
    }
    
    function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override {
        Game storage game = games[requestId];
        
        // Fisher-Yates shuffle детермінований з одного seed
        uint8[52] memory deck;
        for (uint8 i = 0; i < 52; i++) deck[i] = i;
        
        uint256 seed = randomWords[0];
        for (uint8 i = 51; i > 0; i--) {
            seed = uint256(keccak256(abi.encodePacked(seed)));
            uint8 j = uint8(seed % (i + 1));
            (deck[i], deck[j]) = (deck[j], deck[i]);
        }
        
        // Перші 4 карти одразу здаються: player, dealer, player, dealer
        game.deck = new uint8[](52);
        for (uint8 i = 0; i < 52; i++) game.deck[i] = deck[i];
        game.active = true;
        
        emit GameStarted(requestId, game.player, deck[0], deck[2]); // видимі карти гравця
        // deck[1] і deck[3] - карти дилера, deck[1] прихована до кінця
    }
}

Після fulfillment deck зашафлений і зафіксований. Наступні ходи (hit) беруть карти з вже згенерованого deck — без нових VRF запитів. Швидко і дешево.

Чому deck не можна зберігати відкрито?

Але весь deck зберігається в game.deck — публічно! Технічно гравець може прочитати всі майбутні карти з storage.

Рішення: зберігати тільки seed, карти обчислювати детерміновано тільки коли вони «відкриваються»:

// Не храним deck, только seed
mapping(uint256 => uint256) private gameSeeds;

function getCard(uint256 gameId, uint8 position) private view returns (uint8) {
    // Детерминированно вычисляем карту из seed и позиции
    // Карта не в storage — нельзя прочитать заранее
    return uint8(uint256(keccak256(abi.encodePacked(gameSeeds[gameId], position))) % 52);
}

Це не повністю вирішує проблему: технічно можна симулювати getCard для всіх позицій в тому ж блоці. Повне рішення — Mental Poker протокол з шифруванням кожної карти, але це значно складніше.

Як реалізувати логіку Blackjack в смарт-контракті?

Значення карт: туз = 1 або 11, картинки = 10, інші за номіналом:

function cardValue(uint8 card) internal pure returns (uint8) {
    uint8 rank = card % 13; // 0-12: туз, 2-10, валет, дама, король
    if (rank == 0) return 11; // туз (м'яке значення)
    if (rank >= 10) return 10; // картинки
    return rank + 1;
}

function handScore(uint8[] memory cards) internal pure returns (uint8) {
    uint8 score = 0;
    uint8 aces = 0;
    
    for (uint i = 0; i < cards.length; i++) {
        uint8 val = cardValue(cards[i]);
        if (val == 11) aces++;
        score += val;
    }
    
    // М'який туз стає жорстким (1) якщо bust
    while (score > 21 && aces > 0) {
        score -= 10;
        aces--;
    }
    
    return score;
}

Логіка дилера on-chain: дилер бере карти поки score < 17, зупиняється на 17+ (включаючи soft 17 залежно від правил).

Як управляти банкролом за допомогою Kelly Criterion?

Контракт повинен мати ETH для виплат. House edge в Blackjack ~0.5% при оптимальній стратегії — це реальна маржа. Але дисперсія висока, потрібен достатній bankroll.

Kelly Criterion для максимальної ставки: при edge e та bankroll B, максимальна ставка ≈ B * e / variance. Для Blackjack з edge 0.5% та дисперсією ~1.3 — максимальна ставка ≈ 0.38% від bankroll. На практиці: обмежити максимальну ставку на рівні 1-2% bankroll.

uint256 public constant MAX_BET_PERCENT = 200; // 2% = 200/10000

function maxBet() public view returns (uint256) {
    return address(this).balance * MAX_BET_PERCENT / 10000;
}

modifier validBet() {
    require(msg.value >= MIN_BET && msg.value <= maxBet(), "Invalid bet");
    _;
}

Чому UX критичний для блокчейн-блэкджека?

Блокчейн Blackjack потребує ретельного UX для асинхронності. VRF fulfillment — не миттєвий. Гравець натиснув "Deal" — чекає 1-3 блоки до появи карт.

Флоу в UI:

  1. Ставка → startGame() → статус "Dealing..." (чекаємо подію GameStarted)
  2. Карти з'являються → гравець бачить свої 2 карти, одну карту дилера
  3. Hit/Stand → миттєві, із зашафленого deck
  4. Stand → дилер відкриває карти → підсумок → виплата

Для polling подій: wagmi з useWatchContractEvent або WebSocket підключення до ноди.

Стек

Компонент Технологія
Smart contract Solidity 0.8.x + VRF v2.5
Тестування Foundry + VRF mock
Frontend React + wagmi + viem
Мережа Polygon / Arbitrum (низький gas)
Аудит Обов'язковий (gambling + custody коштів)

Аудит контракту: критична безпека

Контракт зберігає ETH та виплачує виграші — помилки в логіці виплат або генерації випадковості ведуть до прямих втрат. Ми використовуємо Slither та Mythril для статичного аналізу, а також рекомендуємо зовнішній аудит у партнерів. Ваша безпека — наша гарантія. Детальніше про аудит смарт-контрактів можна дізнатися в документації Chainlink.

Що входить в розробку блокчейн-блэкджека?

  • Архітектурна документація та вибір протоколу (VRF vs Mental Poker)
  • Смарт-контракт Blackjack з логікою гри та управлінням банкролом
  • Тести на Foundry (unit, fuzz, інтеграційні)
  • Інтеграція Chainlink VRF (v2.5) з підпискою
  • Frontend на React + wagmi + viem з підтримкою гаманців (MetaMask, WalletConnect)
  • Деплой в тестову та основну мережу (Polygon/Arbitrum за вашим вибором)
  • Код-рев'ю та фікси зауважень
  • Навчання вашої команди роботі з контрактом
  • Технічна підтримка на етапі запуску

Порівняння: VRF vs Mental Poker

Критерій Chainlink VRF Mental Poker
Складність реалізації Низька Висока (криптографія)
Швидкість 1-3 блоки 1 раунд (миттєво)
Вартість газу ~300k gas + LINK ~500k gas (шифрування)
Довіра Потрібна довіра до оракула Повністю децентралізовано
Рекомендація Для більшості проектів Для проектів з максимальною децентралізацією
Mental Poker: як це працює? Mental Poker — криптографічний протокол, що дозволяє гравцям роздавати карти без довіреної третьої сторони. Кожна карта шифрується спільним ключем, потім перетасовується і розшифровується. Це забезпечує максимальну децентралізацію, але потребує більше газу та складніший у реалізації.

Терміни орієнтовно

Робочий on-chain Blackjack (смарт-контракт, тести, базовий frontend): від 4 до 5 тижнів. З повним UI, анімаціями, статистикою та мобільною адаптацією: від 8 до 10 тижнів. Вартість розраховується індивідуально після аналізу вимог. Замовте розробку — ми підготуємо детальний план. Зв'яжіться з нами для обговорення вашого проекту.

GameFi розробка: ігрова економіка, контракти та on-chain механіка

Ми бачили цей сценарій не раз. Axie Infinity на піку мала великий дохід, але через 18 місяців токен різко знецінився, а аудиторія значно скоротилася. Причина — відсутність sink'ів: гравці заробляли SLP і виводили, а механізмів спалювання не вистачало. Ми пропонуємо GameFi розробку під ключ: від токеноміки до смарт-контрактів, щоб ваша економіка не повторила цю помилку. Оцінимо ваш проєкт на meetup або онлайн. Наш досвід — 5+ років, десятки реалізованих проєктів, включно з аудитом 15+ P2E ігор.

Чому ламається Play-to-Earn економіка?

Інфляційна токеноміка без sink'ів — головна причина смертельної спіралі. Гравець отримує токени за геймплей. Якщо sink'ів (механізмів спалювання або споживання) недостатньо — supply зростає швидше за demand. Ціна падає. Дохід гравця у fiat зменшується. Гравці йдуть.

Правильна конструкція — dual-token модель з чітким розподілом: governance/value token з обмеженим supply і utility/reward token для внутрішньоігрової економіки. Utility token має активно споживатися: крафтинг предметів, апгрейди, entry fees, breeding. Приклади: GODS/FLUX у Gods Unchained, AXS/SLP у Axie (хоча sink'ів там виявилося недостатньо). Ефективна економіка балансує mint та burn: типовий ratio — 1.2—1.5 burn на 1 mint для запобігання інфляції.

Які sink-механізми реально працюють?

Механізм Опис Приклад
Breeding / крафтинг Спалювання utility token за створення нового NFT Axie (але з правильним balancing)
Апгрейди персонажів Кожна еволюція вимагає спалювання токена Більшість P2E RPG
PvP entry fee Вхід у турнір спалює токени, частина йде в призовий пул Splinterlands
Дурабилити предметів Після N боїв предмет ламається, токен витрачається на ремонт Успадковано з MMORPG
Фінансові механіки Стейкінг з lock-up, що виводить токени з обігу на строк DeFi-шари

Наш досвід — десятки реалізованих проєктів у Web3, включно з аудитом 15+ P2E ігор. Ми знаємо, які sink'и працюють у довгостроковій перспективі. Наприклад, у проєкті з breeding RPG ми збільшили спалювання utility token на 300% за рахунок введення «ремеслу зношуваності» та обов'язкових апгрейдів.

On-chain vs Off-chain: де проходить межа

Всю ігрову логіку on-chain виносити не потрібно — кожна транзакція коштує газу і триває 12 секунд. Ігровий цикл — мілісекунди. Баланс:

Компонент On-chain Off-chain Приклади
Ownership активів + NFT предмети, land
Передача/торгівля + Маркетплейси
Фінанси (стейкінг, rewards) + Staking vaults, DAO
Random generation + (через VRF) Chainlink VRF
Ігровий процес + Бойова система, рух
State ігрового світу + Координати, health points
Матчмейкінг + Серверна логіка

Результати геймплею переносяться на блокчейн через signed message від сервера або ZK-proof. Verifiable off-chain з ZK: ігровий сервер генерує ZK-proof коректності сесії, контракт верифікує proof і нараховує винагороду. Реалізації: Cartridge (Starknet), zkSync game rollups.

Реалізація NFT ігрових предметів

Стандарт: ERC-1155 для взаємозамінних предметів (ресурси, consumables) + ERC-721 для унікальних (персонажі, land). ERC-1155 дає до 60% економії на газі при batch transfer у порівнянні з окремими ERC-721 переказами — для гри з сотнями предметів це економія сотень доларів на день.

Як реалізувати динамічні NFT без перевантаження блокчейна?

Характеристики предмета змінюються в процесі гри (experience, durability, upgrades). Два підходи:

  • Fully on-chain: атрибути зберігаються в mapping контракту, tokenURI генерується з атрибутів через SVG/JSON encoding. Дорого за газом при частому оновленні. Використовується для land і ключових активів.
  • Hybrid: атрибути зберігаються off-chain, в tokenURI — hash стану. Оновлення підписується сервером, верифікується on-chain при transfer або продажі. Дешевше, але вимагає довіри до сервера або ZK.

Breeding і crafting. Контракт: два батьківських NFT → оплата utility token (burn) → мінт нового NFT з атрибутами, що залежать від батьків + Chainlink VRF для випадковості. Без VRF майнери можуть маніпулювати рандомом через вибір блоку.

// Simplified breeding with Chainlink VRF
function breed(uint256 parent1Id, uint256 parent2Id) external {
    require(ownerOf(parent1Id) == msg.sender);
    require(ownerOf(parent2Id) == msg.sender);
    require(breedingToken.burnFrom(msg.sender, BREEDING_COST));

    uint256 requestId = vrfCoordinator.requestRandomWords(...);
    pendingBreeds[requestId] = BreedRequest(parent1Id, parent2Id, msg.sender);
}

function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
    BreedRequest memory req = pendingBreeds[requestId];
    uint256 childAttributes = deriveAttributes(req.parent1Id, req.parent2Id, randomWords[0]);
    _mintWithAttributes(req.requester, childAttributes);
}

Маркетплейс і роялті

Вбудований маркетплейс дає контроль над fee структурою та кастомною логікою (заборона торгівлі предметами до певного рівня). Роялті за EIP-2981 — стандарт, але не enforceable: Blur та інші маркетплейси ігнорують on-chain роялті. Для enforcement — whitelist-only transfer (тільки через контракти, що платять роялті). Жертвуємо composability заради захисту прав.

Staking та розподіл винагород

Staking NFT — механіка для утримання гравців. Проблема: нарахування rewards при тисячах стейкерів вимагає постійних транзакцій (дорого). Рішення — reward-per-share паттерн (як у MasterChef від SushiSwap): глобальний accRewardPerShare, при claim або change state перераховується заборгованість за формулою pendingReward = stakedAmount * (accRewardPerShare - userRewardDebt). O(1) складність незалежно від кількості стейкерів. Економія газу — до 70% порівняно з поелементним нарахуванням.

Детальніше про reward-per-shape реалізацію

Алгоритм працює так: при кожному депозиті/знятті стейку або при оновленні глобального пулу (наприклад, додаванні нових токенів винагороди) контракт оновлює accRewardPerShare = totalPendingReward / totalStaked. Потім для конкретного користувача розраховується pending = user.staked * (accRewardPerShare - user.rewardDebt). Після виплати user.rewardDebt встановлюється рівним accRewardPerShare. Це дозволяє не зберігати історію внесків кожного користувача. На практиці ми використовуємо для GameFi проєктів версію з multiplier для врахування різних ваг стейку (наприклад, рідкісні NFT дають більше винагороди).

Процес та терміни

Починаємо з game economics документа: token flows, mint/burn механіки, projected supply schedule, sink analysis. До написання коду економіка моделюється (Cadence, Python simulation).

Як ми будуємо GameFi: 5 етапів

  1. Економічне моделювання — 1-2 тижні. Розробляємо dual-token модель, розраховуємо sink'и, прописуємо стимули для long-term holding.
  2. Розробка токен-контрактів — 2-3 тижні. ERC-20 для governance, ERC-20 для utility, з настроюваною політикою mint/burn.
  3. Смарт-контракти NFT — 3-5 тижнів. ERC-721 / ERC-1155 з dynamic metadata, breeding/crafting, Chainlink VRF.
  4. Staking + rewards — 2-3 тижні. Контракт на базі reward-per-share, інтерфейси для frontend.
  5. Маркетплейс (опціонально) — 2-4 тижні. Кастомний маркетплейс з enforced royalty.

Що входить у роботу

  • Вихідний код усіх смарт-контрактів з тестами (Foundry/Hardhat)
  • Документація архітектури та економіки
  • Інтеграція з Chainlink, Tenderly для моніторингу
  • Аудит коду та формальна верифікація (Slither, Mythril, Echidna)
  • Навчання команди роботі з контрактами
  • Підтримка після деплою (3 місяці)

Базовий GameFi стек (токени + NFT + staking + маркетплейс) — від 8 до 16 тижнів. Повна гра з on-chain рандомом, breeding, dynamic NFT — 4-8 місяців. ZK-based verifiable gameplay — окремий проєкт від 6 місяців.

Зв'яжіться з нами для аудиту вашої токеноміки — оцінимо ризики та доопрацюємо sink-механізми. Замовте розробку GameFi проєкту — отримайте готовий продукт з перевіреною економікою. Наш досвід — десятки реалізованих проєктів у Web3, включно з аудитом 15+ P2E ігор. Гарантуємо стабільність контрактів і прозорість коду. Сертифіковані аудитори перевіряють кожен контракт на типові вразливості (reentrancy, flash loan, oracle manipulation).