В PvP-играх на блокчейне центральная проблема — обеспечить честность при скрытых ходах и низкие задержки для real-time геймплея. On-chain транзакции дороги (0.1–1$ за ход) и медленны (>12 секунд). Просто оставить логику на сервере — значит отказаться от trustless-свойств блокчейна. Мы разрабатываем смарт-контракты, которые обеспечивают честный матчмейкинг, скрытые ходы через commit-reveal и молниеносные off-chain ходы через state channels. Наш опыт — более 5 лет в Web3, 50+ успешных проектов, команда senior-инженеров с фокусом на игровую механику. Получите консультацию блокчейн-архитектора: расскажите о своей игре, мы подберём оптимальный стек и оценим стоимость.
Как commit-reveal решает проблему скрытых ходов?
В карточных играх и стратегиях каждый ход противника должен быть скрыт до момента его применения. На блокчейне все данные публичны, поэтому применяется commit-reveal паттерн. Игроки сначала отправляют хэш своего действия с секретом, а затем раскрывают его. Если кто-то не раскрывает ход в срок — он автоматически проигрывает. Это исключает подглядывание и back-running.
Пример реализации на Solidity (с использованием Foundry):
contract PvPGame {
struct GameState {
address player1;
address player2;
bytes32 p1CommitHash; // hash(action + secret)
bytes32 p2CommitHash;
uint8 p1Action; // раскрывается после commit обоих
uint8 p2Action;
Phase phase;
uint256 commitDeadline;
uint256 revealDeadline;
}
enum Phase { WAITING, COMMIT, REVEAL, RESOLVED }
// Phase 1: оба игрока отправляют hash(action + secret)
function commitAction(uint256 gameId, bytes32 commitHash) external {
GameState storage game = games[gameId];
require(game.phase == Phase.COMMIT, "Not commit phase");
require(block.timestamp <= game.commitDeadline, "Commit deadline passed");
if (msg.sender == game.player1) {
game.p1CommitHash = commitHash;
} else if (msg.sender == game.player2) {
game.p2CommitHash = commitHash;
} else revert("Not a player");
// Если оба сделали commit — переход к reveal
if (game.p1CommitHash != bytes32(0) && game.p2CommitHash != bytes32(0)) {
game.phase = Phase.REVEAL;
game.revealDeadline = block.timestamp + REVEAL_WINDOW;
}
}
// Phase 2: раскрываем реальные действия
function revealAction(uint256 gameId, uint8 action, bytes32 secret) external {
GameState storage game = games[gameId];
require(game.phase == Phase.REVEAL, "Not reveal phase");
bytes32 expectedHash = keccak256(abi.encodePacked(action, secret));
if (msg.sender == game.player1) {
require(game.p1CommitHash == expectedHash, "Hash mismatch");
game.p1Action = action;
} else if (msg.sender == game.player2) {
require(game.p2CommitHash == expectedHash, "Hash mismatch");
game.p2Action = action;
}
// Если оба раскрыли — resolve
if (game.p1Action != 0 && game.p2Action != 0) {
_resolveGame(gameId);
}
}
// Если игрок не reveal в срок — forfeit
function claimTimeout(uint256 gameId) external {
GameState storage game = games[gameId];
require(game.phase == Phase.REVEAL, "Not reveal phase");
require(block.timestamp > game.revealDeadline, "Deadline not passed");
// Игрок который не reveal — проигрывает
address winner;
if (game.p1Action == 0 && game.p2Action != 0) {
winner = game.player2;
} else if (game.p2Action == 0 && game.p1Action != 0) {
winner = game.player1;
} else {
// Оба не revealed — возврат ставок
_refundBothPlayers(gameId);
return;
}
_payWinner(gameId, winner);
}
}
Почему state channels — оптимальный выбор для real-time PvP?
On-chain каждый ход стоит газа и занимает >12 секунд. State channels позволяют совершать тысячи ходов между двумя игроками без комиссий, а на кону только депозит. После игры канал закрывается одной on-chain транзакцией. Сравните:
| Критерий | On-chain | State channel |
|---|---|---|
| Время хода | 12+ секунд | <50 мс |
| Комиссия | $0.1–$1 | $0 (только открытие/закрытие) |
| Пропускная способность | ~15 tx/s | 1000+ ходов/s |
| Trustlessness | Полная | Высокая (требуется слот для оспаривания) |
State channels в 1000 раз быстрее on-chain транзакций, что критично для реал-тайм стратегий. Экономия на газе достигает 90% при использовании state channels.
Как мы защищаем игру от читеров?
Для on-chain PvP вся логика в смарт-контракте — читерство невозможно. Для off-chain + on-chain settlement нужна серверная валидация. Мы реализуем проверку очерёдности, допустимости хода, таймстампов и защиту от повторений. Для скрытых данных используем zk-SNARKs — игрок доказывает корректность хода, не раскрывая его.
class GameValidator {
async validateMove(
gameState: GameState,
move: Move,
playerId: string
): Promise<ValidationResult> {
// 1. Проверяем очерёдность хода
if (gameState.currentTurn !== playerId) {
return { valid: false, reason: "Not your turn" };
}
// 2. Проверяем допустимость хода по правилам игры
const allowedMoves = this.getAllowedMoves(gameState, playerId);
if (!allowedMoves.includes(move.type)) {
return { valid: false, reason: "Invalid move" };
}
// 3. Проверяем что move не был уже сделан (replay protection)
if (this.moveCache.has(move.id)) {
return { valid: false, reason: "Duplicate move" };
}
// 4. Проверяем timestamp (move не старше N секунд)
if (Date.now() - move.timestamp > MAX_MOVE_AGE_MS) {
return { valid: false, reason: "Move too old" };
}
return { valid: true };
}
}
Как реализована турнирная система?
contract PvPTournament {
struct Tournament {
uint256 entryFee;
uint256 maxPlayers;
address[] participants;
TournamentType tournamentType; // SINGLE_ELIMINATION, ROUND_ROBIN, SWISS
uint256 prizePool;
TournamentStatus status;
}
// Prize distribution (в basis points)
uint256[] public prizeDistribution = [5000, 3000, 1500, 500]; // 50%, 30%, 15%, 5%
function registerForTournament(uint256 tournamentId) external payable {
Tournament storage t = tournaments[tournamentId];
require(t.participants.length < t.maxPlayers, "Tournament full");
require(msg.value == t.entryFee, "Wrong entry fee");
t.participants.push(msg.sender);
t.prizePool += msg.value;
}
function distributePrizes(uint256 tournamentId, address[] calldata rankedPlayers)
external onlyAdmin
{
Tournament storage t = tournaments[tournamentId];
for (uint i = 0; i < prizeDistribution.length && i < rankedPlayers.length; i++) {
uint256 prize = (t.prizePool * prizeDistribution[i]) / 10000;
payable(rankedPlayers[i]).transfer(prize);
}
}
}
Как работает матчмейкинг?
Для высоконагруженных PvP-игр используем Redis sorted sets. Каждый игрок встаёт в очередь с рейтингом (MMR). При совпадении рейтинга с другим игроком — они автоматически соединяются в смарт-контракт. Это позволяет обрабатывать тысячи запросов в секунду без блокировок. Очередь хранится off-chain, но матч подтверждается on-chain транзакцией.
Процесс разработки
- Анализ — описание игровой механики и экономики
- Проектирование — архитектура смарт-контрактов, схема данных
- Разработка — написание контрактов на Solidity, тестирование в Foundry
- Аудит — проверка безопасности, fuzzing, формальная верификация
- Деплой — публикация на выбранной L2, настройка инфраструктуры, интеграция с фронтендом
Что входит в работу
- Архитектурная документация (схемы, спецификации контрактов)
- Исходный код смарт-контрактов (Solidity, Foundry)
- Полный набор тестов (unit, integration, fuzz)
- Интеграция с Chainlink VRF для рандома
- Настройка state channels (если требуется)
- Деплой на выбранную L2 и настройка мониторинга
- Аудит безопасности (Slither, Mythril, fuzzing, manual review)
- Скрипты для верификации контрактов в эксплорере
- Обучение команды (1-2 сессии, документация)
- Поддержка в течение 1 месяца после деплоя
Сроки
- 1v1 игра (Coinflip, RPS, базовая карточная): 4-6 недель
- State Channel PvP: +3-4 недели
- Tournament система: +3-4 недели
- Сложная карточная/стратегия игра: 3-5 месяцев
- Security audit: обязателен, +4-6 недель
Стек технологий
| Компонент | Технология |
|---|---|
| Smart contracts | Solidity + Foundry, State Channels |
| Randomness | Chainlink VRF v2.5 |
| Real-time комм. | WebSocket (Socket.io) |
| Game server | Node.js + TypeScript |
| Matchmaking | Redis sorted sets |
| Frontend | React / Unity WebGL |
| L2 | Arbitrum / Base / Polygon |
| Anti-cheat | Сервер-side validation + zkProofs |
commit-reveal — стандартный протокол для скрытой отправки данных.
Закажите консультацию сегодня — мы проанализируем вашу идею и предложим архитектуру без предоплаты. Наша гарантия: прозрачный процесс, фиксированные сроки, полное сопровождение после деплоя. Получите консультацию блокчейн-архитектора — расскажите о своей игре, мы подберём оптимальный стек и оценим стоимость.







