Розробка utility-токена

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка utility-токена
Простий
~2-3 дні
Часті запитання

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

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

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

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

Розробка utility-токена

Utility-токен відрізняється від governance токена або security токена не юридично, а функціонально: він потрібен для чогось конкретного всередину протоколу. Оплата газу (ETH), оплата обчислень (FIL в Filecoin), доступ до сервісу (API credits), знижки на fees (BNB на Binance) — все це utility. Проблема більшості «utility» токенів: utility штучна, токен не потрібен для роботи протоколу, його примусово вставили в tokenomics ради продажу.

Настоящий utility-токен вирішує проблему, яку неможливо вирішити без токена: скоординовані incentives для учасників мережі, trustless escrow, програмовані умови доступу.

Проектування utility механіки

Необхідність токена: тест

Перед проектуванням токена відповідьте: можна замінити токен на USDC або ETH? Якщо так — можливо, токен не потрібен. Якщо ні — чому ні?

Переконливі причини мати власний токен:

  • Governance: токен = право голосу, ETH не може замінити без централізації
  • Staking для безпеки: валідатори стейкають токен, слєшинг при мошенництві — skin in game не можна замінити зовнішнім активом
  • Protocol revenue sharing: токенхолдери отримують частину fees протоколу
  • Інфляційні награди: субсидування bootstrapping через інфляцію нативного токена

Capture механіка

Utility-токен повинен «захоплювати» частину ціності протоколу. Популярні паттерни:

Fee switch: протокол бере X% від операцій. Частина в treasury, частина — токенхолдерам або buyback/burn. Uniswap governance голосує за fee switch саме за цією логікою.

Staking для доступу: провайдери послуг повинні стейкати токен. Stake = гарантія добросовісності. При порушенні — slashing. Chainlink операторів стейкають LINK.

Token-denominated pricing: послуга коштує N токенів, не N доларів. Спрос на послугу → спрос на токен. Filecoin: зберігання коштує FIL.

Реалізація: staking utility

Типовий utility-токен зі staking для доступу до сервісу:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract UtilityToken is ERC20, ERC20Permit, AccessControl, ReentrancyGuard {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant SERVICE_ROLE = keccak256("SERVICE_ROLE");
    
    uint256 public constant PROVIDER_STAKE_REQUIRED = 10_000 * 10**18; // 10k токенів
    
    struct ProviderStake {
        uint256 amount;
        uint256 stakedAt;
        bool active;
    }
    
    mapping(address => ProviderStake) public providerStakes;
    mapping(address => uint256) public serviceCredits; // оплачені кредити
    
    uint256 public constant CREDIT_PRICE = 1 * 10**18; // 1 токен = 1 кредит
    uint256 public burned;
    
    event ProviderRegistered(address indexed provider, uint256 stake);
    event ProviderSlashed(address indexed provider, uint256 amount, string reason);
    event CreditsPurchased(address indexed user, uint256 amount);
    
    constructor(address admin, address treasury, uint256 initialSupply)
        ERC20("Utility Token", "UTL")
        ERC20Permit("Utility Token")
    {
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(MINTER_ROLE, admin);
        _mint(treasury, initialSupply);
    }
    
    // Провайдер стейкає токени для реєстрації
    function stakeAsProvider() external nonReentrant {
        require(!providerStakes[msg.sender].active, "Already registered");
        require(
            balanceOf(msg.sender) >= PROVIDER_STAKE_REQUIRED,
            "Insufficient balance"
        );
        
        _transfer(msg.sender, address(this), PROVIDER_STAKE_REQUIRED);
        providerStakes[msg.sender] = ProviderStake({
            amount: PROVIDER_STAKE_REQUIRED,
            stakedAt: block.timestamp,
            active: true
        });
        
        _grantRole(SERVICE_ROLE, msg.sender);
        emit ProviderRegistered(msg.sender, PROVIDER_STAKE_REQUIRED);
    }
    
    // Користувач купує кредити
    function purchaseCredits(uint256 creditAmount) external nonReentrant {
        uint256 tokenCost = creditAmount * CREDIT_PRICE;
        require(balanceOf(msg.sender) >= tokenCost, "Insufficient tokens");
        
        // 80% burn, 20% в treasury — дефляційна механіка
        uint256 burnAmount = tokenCost * 80 / 100;
        uint256 treasuryAmount = tokenCost - burnAmount;
        
        _burn(msg.sender, burnAmount);
        burned += burnAmount;
        _transfer(msg.sender, treasury, treasuryAmount);
        
        serviceCredits[msg.sender] += creditAmount;
        emit CreditsPurchased(msg.sender, creditAmount);
    }
    
    // Провайдер списує кредити за оказану послугу
    function consumeCredits(address user, uint256 amount) external onlyRole(SERVICE_ROLE) {
        require(serviceCredits[user] >= amount, "Insufficient credits");
        serviceCredits[user] -= amount;
    }
    
    // Slashing при порушенні провайдером
    function slashProvider(
        address provider, 
        uint256 amount, 
        string calldata reason
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        ProviderStake storage stake = providerStakes[provider];
        require(stake.active, "Not active provider");
        require(amount <= stake.amount, "Exceeds stake");
        
        stake.amount -= amount;
        _burn(address(this), amount); // спалюємо слєшнуті токени
        burned += amount;
        
        if (stake.amount < PROVIDER_STAKE_REQUIRED / 2) {
            stake.active = false;
            _revokeRole(SERVICE_ROLE, provider);
        }
        
        emit ProviderSlashed(provider, amount, reason);
    }
}

Unstaking cooldown

Провайдер не повинен миттєво виводити stake. Cooldown період — захист від slash evasion (виявив проблему → швидко вивів stake → немає slashing):

uint256 public constant UNSTAKE_COOLDOWN = 14 days;

mapping(address => uint256) public unstakeRequestedAt;

function requestUnstake() external {
    require(providerStakes[msg.sender].active, "Not active");
    unstakeRequestedAt[msg.sender] = block.timestamp;
    providerStakes[msg.sender].active = false;
    _revokeRole(SERVICE_ROLE, msg.sender);
}

function finalizeUnstake() external nonReentrant {
    require(unstakeRequestedAt[msg.sender] > 0, "No unstake request");
    require(
        block.timestamp >= unstakeRequestedAt[msg.sender] + UNSTAKE_COOLDOWN,
        "Cooldown not elapsed"
    );
    
    uint256 amount = providerStakes[msg.sender].amount;
    providerStakes[msg.sender].amount = 0;
    unstakeRequestedAt[msg.sender] = 0;
    
    _transfer(address(this), msg.sender, amount);
}

Розподіл supply

Типовий розподіл для utility-токена протоколу:

Аллокація % Vesting
Команда та консультанти 15–20% 4 роки, cliff 1 рік
Інвесторів 15–25% 2–3 роки, cliff 6 місяців
Екосистема/гранти 20–30% Лінійно 3–5 років
Ліквідність/DEX 5–10% TGE або за потребою
Treasury 20–30% Governance вирішує
Публічний продаж / IDO 5–15% Частково TGE

Загальна сума TGE (Token Generation Event) — бажано не більше 15–20% supply. Занадто великий TGE float створює тиск продажів.

Уникання антипаттернів

Бесполезний buyback: buyback токена з treasury та спалювання — це переміщення ціності від treasury до токенхолдерів. Само по собі не створює ціність. Має сенс тільки якщо у протоколу є реальний revenue.

Circular dependency: токен потрібен для використання протоколу, протокол потрібен для отримання токена. Без зовнішньої ціності — замкнутий круг.

Governance без влади: governance токен, у якого немає реального права змінювати параметри протоколу — декоративний. Користувачі це розуміють.

Терміни розробки utility-токена з базовою staking механікою та credits системою: 1–2 тижні включаючи тести. Складна tokenomics з кількома механіками — 3–4 тижні.