Developing a utility token with staking and burn mechanics

When a utility token lacks real value, the ecosystem loses trust and worth. We build utility tokens with well-designed staking and burn mechanics that address your protocol's specific needs. Our team delivers the project turnkey—from tokenomics to implementation—with ongoing support.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1335
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1293
  • B2B Advance company logo design
    B2B Advance company logo design
    738
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1031
  • AIDER company logo development
    AIDER company logo development
    978
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1087

We build utility tokens that solve real protocol problems — not artificially inserted into tokenomics just for fundraising. A utility token differs from governance or security tokens functionally: it is required for something concrete within the ecosystem. Paying gas (ETH), computation (FIL in Filecoin), service access (API credits), fee discounts (BNB on Binance) — all are examples of genuine utility. The problem with most "utility" tokens: the utility is artificial, the token is not needed for the protocol to operate. A real utility token solves a problem that cannot be solved without a token: coordinated incentives for network participants, trustless escrow, programmable access conditions. Our team has over 7 years of blockchain development experience, more than 30 launched tokens, and deep industry expertise — allowing us to design a working economy from the start.

Designing utility mechanics

How to verify if a token is necessary?

Before designing the token, we analyze: can it be replaced by USDC or ETH? If replacement is possible — a native token is not needed. If not — we identify unique utility. Compelling reasons to have your own token: Governance (voting rights), Staking for security (validators stake tokens, slashing for cheating — skin in the game), Protocol revenue sharing (token holders receive part of fees), inflationary rewards for ecosystem bootstrap. Staking can reduce fees by up to 20% for token holders.

Capture mechanics

A utility token must capture part of the protocol's value. Popular patterns: Fee switch (protocol takes a % of operations, part goes to token holders or buyback/burn), Staking for access (providers lock tokens as guarantee), Token-denominated pricing (service costs N tokens). Demand for the service generates demand for the token.

Implementation: staking utility

A typical utility token with staking for access to a service: We use the OpenZeppelin library for standard contracts.

// 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 tokens

    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;
    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");
        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;
        emit CreditsConsumed(user, msg.sender, amount);
    }

    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);
    }
}

Why staking is the foundation of a utility token?

Staking creates obligations for network participants. Service providers must hold tokens as a guarantee of good behavior. On violation — slashing. This locks token value inside the ecosystem. Compared to buyback: staking for access is 3–5 times more effective in retaining users.

Unstaking cooldown

Providers should not be able to withdraw the stake instantly. Cooldown period — protection against slash evasion:

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);
}

Comparison of value retention mechanics

Mechanic Efficiency Example
Staking for access High BNB, FIL
Buyback and burn Medium Fee → buyback
Fee switch High AMM protocols
Inflationary rewards Low (without utility) DeFi 2.0

Supply distribution

Typical distribution for a protocol utility token:

Allocation % Vesting
Team & advisors 15–20% 4 years, cliff 1 year
Investors 15–25% 2–3 years, cliff 6 months
Ecosystem/grants 20–30% Linear 3–5 years
Liquidity/DEX 5–10% TGE or as needed
Treasury 20–30% Governance decides
Public sale / IDO 5–15% Partially at TGE

Total TGE supply should ideally not exceed 15–20% of total supply.

How to avoid utility token antipatterns?

Useless buyback — buying back tokens from treasury without real revenue creates no value. Circular dependency — token needed to use protocol, protocol needed to get token — a closed loop. Governance without power — a token without the right to change protocol parameters is decorative. We design mechanics, each of which brings measurable benefit. Proper tokenomics can increase service provider profitability by 30–50%.

How we work on a utility token project

  1. Analysis: determine if an ERC20 token is needed and what utility it will provide.
  2. Design: develop tokenomics and economic models.
  3. Implementation: write Solidity smart contracts using OpenZeppelin.
  4. Testing: cover with unit and fuzz tests using Foundry.
  5. Audit: check code for vulnerabilities (reentrancy, overflow, etc.).
  6. Deployment and verification on Etherscan.
  7. Support: one month of technical support after launch.

If you are planning a token launch, contact us — we will help design the economy and implement the contracts.

What is included in utility token development

  • Tokenomics: analysis and white paper
  • Smart contracts: Solidity (ERC20, staking, burn, permit)
  • Testing: Foundry (unit + fuzzing)
  • Deployment and verification on Etherscan
  • Integration with wallets (MetaMask, WalletConnect)
  • Documentation for the team
  • Technical support for 1 month after launch

Contact us for a project evaluation. Get a tokenomics consultation.