Разработка GameFi-проекта
GameFi — это пересечение двух очень разных инженерных дисциплин: game development с требованиями к real-time, low latency и высокой частоте событий, и blockchain development с его finalité, gas costs и immutability. Попытка просто "добавить блокчейн в игру" почти всегда проваливается — либо игра становится неиграбельной из-за транзакций, либо blockchain-часть декоративна и ничего не даёт пользователям. Правильная архитектура GameFi — это чёткая граница между тем, что должно быть on-chain, и тем, что должно оставаться off-chain.
Фундаментальный вопрос: что идёт on-chain
Не всё в игре должно быть на блокчейне. Блокчейн — это дорогой, медленный, но trustless и permanent storage. Используйте его именно там, где нужны эти свойства.
Должно быть on-chain:
- Ownership активов (NFT персонажи, предметы, земли)
- Финансовые операции (покупка, продажа, staking, rewards)
- Критические результаты, влияющие на экономику (победа в турнире, получение редкого дропа)
- Governance решения (если есть DAO)
Должно быть off-chain (игровые серверы):
- Игровая механика в реальном времени
- Позиции игроков, столкновения, физика
- Большинство gameplay событий
- Социальные функции (чат, guilds)
- Аналитика и логирование
Хорошая модель: игровой сервер — источник правды для gameplay, блокчейн — источник правды для ownership и экономики. Синхронизация происходит в определённых checkpoint'ах.
Архитектура: серверы, контракты, клиент
Игровой бэкенд
Game Client (Unity/Unreal/Web)
↓
Game Server (authoritative)
└── Game State DB (Redis для real-time, PostgreSQL для persistence)
↓ (при значимых событиях)
Blockchain Sync Service
↓
Smart Contracts (Assets, Economy, Rewards)
↓
The Graph (индексирование для UI/лидерборды)
Authoritative server model — клиент никогда не принимает финальных решений. Клиент отправляет input (переместиться влево, атаковать), сервер верифицирует и применяет. Это предотвращает читинг без какого-либо блокчейна.
Blockchain Sync Service — отдельный сервис, который слушает игровые события и транслирует значимые из них в on-chain транзакции. Работает асинхронно, не блокирует gameplay.
NFT активы: стандарты и метаданные
ERC-721 для уникальных предметов, ERC-1155 для stackable items (ресурсы, расходники) — в GameFi почти всегда комбинация обоих.
Метаданные игровых NFT — отдельная тема. On-chain метаданные (полностью в контракте) — максимальная permanence, но дорого и ограничено по объёму. IPFS — компромисс: content-addressed, но требует pinning. Централизованный сервер — быстро, дёшево, но зависит от вас.
contract GameItem is ERC1155 {
struct ItemType {
string name;
uint8 rarity; // 1=Common, 2=Rare, 3=Epic, 4=Legendary
uint16 baseAttack;
uint16 baseDefense;
bool tradeable;
}
mapping(uint256 => ItemType) public itemTypes;
mapping(uint256 => uint256) public itemMaxSupply;
mapping(uint256 => uint256) public itemCurrentSupply;
// Только game server может минтить предметы
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
function mintItem(
address to,
uint256 itemTypeId,
uint256 amount,
bytes memory data
) external onlyRole(MINTER_ROLE) {
require(
itemCurrentSupply[itemTypeId] + amount <= itemMaxSupply[itemTypeId],
"Max supply exceeded"
);
itemCurrentSupply[itemTypeId] += amount;
_mint(to, itemTypeId, amount, data);
}
// Non-transferable soulbound items
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal override {
for (uint i = 0; i < ids.length; i++) {
if (from != address(0) && to != address(0)) { // не mint/burn
require(itemTypes[ids[i]].tradeable, "Item is soulbound");
}
}
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
}
Игровой токен: tokenomics
Большинство провальных GameFi проектов провалились именно из-за плохой tokenomics, а не из-за плохой игры. Основные ошибки:
Инфляционная спираль — токен выдаётся как reward за gameplay без достаточного sink'а. Чем больше игроков, тем больше предложение, тем ниже цена, тем меньше стимул играть. Это убило Axie Infinity в 2022.
Двухтокенная модель — попытка разделить "governance token" (дефляционный) и "utility token" (инфляционный) часто создаёт irrational peg между ними и ещё более сложный fail mode.
Правильный подход — балансировать emission и sink:
contract GameEconomy {
// Emission: только через игровые достижения, верифицированные сервером
function claimDailyReward(
address player,
uint256 amount,
uint256 nonce,
bytes memory serverSignature
) external {
// Верификация подписи сервера
bytes32 message = keccak256(abi.encodePacked(player, amount, nonce));
require(
ECDSA.recover(message.toEthSignedMessageHash(), serverSignature) == GAME_SERVER,
"Invalid server signature"
);
require(!usedNonces[nonce], "Nonce already used");
usedNonces[nonce] = true;
// Лимит дневного дропа
require(dailyClaimed[player][today()] + amount <= MAX_DAILY_REWARD, "Daily limit");
dailyClaimed[player][today()] += amount;
gameToken.mint(player, amount);
}
// Sink: craft, upgrade, fee, burn
function craftItem(uint256 recipeId) external {
Recipe memory recipe = recipes[recipeId];
gameToken.burnFrom(msg.sender, recipe.tokenCost);
// mint NFT предмет
}
}
Game Server Signature Pattern
Это критический паттерн для GameFi: игровой сервер является доверенным source of truth, и его решения верифицируются on-chain через signature проверку.
Пользователь не может сам вызвать claimReward — он должен получить подписанный сервером voucher. Это предотвращает:
- Фабрикацию результатов через прямой вызов контракта
- Двойную трату одного результата (nonce)
- Читинг через replay attack'и
// Game Server side (Node.js)
import { ethers } from "ethers";
const serverWallet = new ethers.Wallet(process.env.SERVER_PRIVATE_KEY);
async function generateRewardVoucher(
playerAddress: string,
rewardAmount: bigint,
gameSessionId: string
): Promise<{ nonce: string; signature: string; amount: string }> {
const nonce = ethers.hexlify(ethers.randomBytes(32));
const message = ethers.solidityPackedKeccak256(
["address", "uint256", "bytes32"],
[playerAddress, rewardAmount, nonce]
);
const signature = await serverWallet.signMessage(ethers.getBytes(message));
return { nonce, signature, amount: rewardAmount.toString() };
}
Marketplace: P2P торговля активами
contract GameMarketplace {
struct Listing {
address seller;
address nftContract;
uint256 tokenId;
uint256 amount; // для ERC-1155
uint256 price; // в ERC-20 токене или нативном
uint256 expiresAt;
}
mapping(bytes32 => Listing) public listings;
uint256 public feePercent = 250; // 2.5%
function buyItem(bytes32 listingId) external {
Listing memory listing = listings[listingId];
require(block.timestamp < listing.expiresAt, "Listing expired");
require(listing.seller != address(0), "Listing not found");
uint256 fee = (listing.price * feePercent) / 10_000;
uint256 sellerAmount = listing.price - fee;
// Перевод токенов
paymentToken.transferFrom(msg.sender, listing.seller, sellerAmount);
paymentToken.transferFrom(msg.sender, treasury, fee);
// Передача NFT
IERC1155(listing.nftContract).safeTransferFrom(
address(this), msg.sender, listing.tokenId, listing.amount, ""
);
delete listings[listingId];
}
}
Anti-cheat на уровне блокчейна
On-chain верификация результатов возможна через несколько механизмов:
Commit-reveal для случайности — игра не может знать исход заранее, но и блокчейн не должен быть manipulable:
- Игрок commit'ит hash(seed) до начала
- После игры reveal'ит seed
- Блокчейн верифицирует: random = hash(seed, block.hash) — нельзя предсказать заранее
Chainlink VRF v2 — для on-chain randomness (loot drops, matchmaking):
import { VRFConsumerBaseV2 } from "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
contract LootBox is VRFConsumerBaseV2 {
mapping(uint256 => address) public requestToPlayer;
function openLootBox() external returns (uint256 requestId) {
requestId = vrfCoordinator.requestRandomWords(
keyHash, subscriptionId, 3, 100_000, 3 // 3 random words
);
requestToPlayer[requestId] = msg.sender;
}
function fulfillRandomWords(uint256 requestId, uint256[] memory words) internal override {
address player = requestToPlayer[requestId];
// Определяем дроп на основе verifiable random
uint256 itemTier = words[0] % 1000; // 0-999
_mintReward(player, itemTier);
}
}
Технический стек для GameFi
Game Engine: Unity (WebGL + native mobile) или Phaser 3 (browser-first). Unity с WebGL — стандарт для casual GameFi.
Web3 интеграция в Unity: Nethereum для EVM, Solana.Unity-SDK для Solana. Для browser — MetaMask SDK через JSLib bridge.
Бэкенд: Go или Node.js для game server (latency критична), отдельный TypeScript сервис для blockchain interactions.
Индексирование: The Graph для лидербордов, NFT коллекций, transaction history. Своя PostgreSQL для game-специфичной аналитики.
Сети: Polygon PoS или Arbitrum Nova (ultra-low gas для частых транзакций), Ethereum mainnet для ценных активов.
Этапы и сроки
| Фаза | Содержание | Срок |
|---|---|---|
| Game design & tokenomics | Механики, economy model, whitepaper | 4–6 нед |
| Smart contracts (assets, economy) | ERC-1155, marketplace, staking | 4–8 нед |
| Game server | Authoritative logic, signature service | 4–8 нед |
| Game client | Unity/Phaser + wallet integration | 6–12 нед |
| Smart contract аудит | — | 4–6 нед |
| Testnet & балансировка | Economy testing, anti-cheat | 4–6 нед |
| Launch | Mainnet деплой, monitoring | 2 нед |
Минимальный бюджет для полноценного GameFi MVP — $200k–400k. Проекты с бюджетом ниже обычно жертвуют либо качеством игры, либо качеством смарт-контрактов — оба выбора ведут к провалу.







