Розробка системи buyback-and-burn

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка системи buyback-and-burn
Середній
~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
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1147
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    885

Розробка системи buyback-and-burn

Buyback-and-burn — дефляційний механізм: протокол використовує частину выручки для виконання своєю токена на ринку та його знищення. BNB, MKR, GMX — усі використовують варіації цього механізму. Реалізація потребує чіткої on-chain логіки, правильного вибору DEX-роутера та захисту від sandwich-атак.

Як працює механізм

Базова схема: protocol fee -> buyback contract -> swap на DEX -> burn. Ключові рішення:

Джерело коштів: комісії протоколу (trading fees, lending fees, mint fees). Зазвичай контракт накопичує USDC/ETH, buyback триггерується по розписанню або при досягненні порога.

DEX для swap: Uniswap V3 через Universal Router або Swap Router 02 — найбільш ліквідний варіант для Ethereum/L2. На BSC — PancakeSwap. Для великих buyback важливий маршрут через кілька пулів.

Burn механізм: token.transfer(address(0xdead)) або token.burn(amount) якщо функція існує. Відправка на 0xdead — не справжній burn з точки зору totalSupply(), але прийнятий стандарт. Справжній burn через _burn() зменшує totalSupply.

Контракт buyback

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

import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

interface IBurnable is IERC20 {
    function burn(uint256 amount) external;
}

contract BuybackAndBurn is Ownable2Step, ReentrancyGuard {
    using SafeERC20 for IERC20;

    ISwapRouter public immutable swapRouter;
    IERC20 public immutable paymentToken;  // USDC/ETH/WETH
    IBurnable public immutable projectToken;
    address public immutable BURN_ADDRESS = address(0xdead);

    uint24 public poolFee = 3000;          // 0.3% пул, налаштовується
    uint256 public maxSlippageBps = 200;   // 2% максимальний slippage
    uint256 public minBuybackAmount;       // мінімальний порог для триггера

    event BuybackExecuted(
        uint256 paymentAmount,
        uint256 tokensBought,
        uint256 tokensBurned
    );

    constructor(
        address _router,
        address _paymentToken,
        address _projectToken,
        uint256 _minBuybackAmount
    ) Ownable(msg.sender) {
        swapRouter = ISwapRouter(_router);
        paymentToken = IERC20(_paymentToken);
        projectToken = IBurnable(_projectToken);
        minBuybackAmount = _minBuybackAmount;
    }

    function executeBuyback(uint256 amountIn, uint256 amountOutMinimum)
        external
        nonReentrant
        onlyOwner
    {
        require(amountIn >= minBuybackAmount, "Below minimum buyback amount");
        require(
            paymentToken.balanceOf(address(this)) >= amountIn,
            "Insufficient balance"
        );

        paymentToken.approve(address(swapRouter), amountIn);

        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
            tokenIn: address(paymentToken),
            tokenOut: address(projectToken),
            fee: poolFee,
            recipient: address(this),
            deadline: block.timestamp + 300, // 5 хвилин
            amountIn: amountIn,
            amountOutMinimum: amountOutMinimum, // захист від sandwich
            sqrtPriceLimitX96: 0
        });

        uint256 amountOut = swapRouter.exactInputSingle(params);

        // Сжигаємо куплені токени
        projectToken.burn(amountOut);

        emit BuybackExecuted(amountIn, amountOut, amountOut);
    }

    // Розрахунок minAmountOut off-chain через Uniswap SDK перед вызовом
    function getMinAmountOut(uint256 amountIn)
        external
        view
        returns (uint256)
    {
        // Це view-helper для front-end, реальний розрахунок через quoter
        // quoter.quoteExactInputSingle() поза контрактом
        revert("Use Quoter contract off-chain");
    }
}

Захист від маніпуляцій

Sandwich атака — головна загроза buyback транзакцій. MEV-боти бачать pending buyback у mempool, вставляють свій swap перед ним (задираючи ціну) та одразу після (фіксуючи прибуток). Захист:

  • amountOutMinimum: ніколи не ставити 0. Розраховувати через Uniswap V3 Quoter з запасом 1-2%.
  • Flashbots / MEV blocker: відправляти buyback транзакції через приватний mempool (Flashbots Protect, MEV Blocker від CoW Protocol).
  • Розбивка на частини: замість одного великого buyback — кілька менших з інтервалом. Знижує impact та робить предсказуваність меншою.
  • TWAP pricing: порівнювати ціну swap з TWAP ціною Uniswap V3 оракула. Якщо відхилення > N% — revert.
// Перевірка через Uniswap V3 TWAP оракул
function checkPriceDeviation(uint256 amountIn, uint256 amountOut) internal view {
    // Отримуємо TWAP за останні 30 хвилин
    uint32[] memory secondsAgo = new uint32[](2);
    secondsAgo[0] = 1800; // 30 хвилин назад
    secondsAgo[1] = 0;    // зараз

    (int56[] memory tickCumulatives,) = IUniswapV3Pool(pool)
        .observe(secondsAgo);

    int56 tickDelta = tickCumulatives[1] - tickCumulatives[0];
    int24 twapTick = int24(tickDelta / 1800);

    // Розраховуємо очікуваний amountOut по TWAP
    uint256 expectedAmountOut = getAmountFromTick(twapTick, amountIn);

    // Допускаємо відхилення не більше 3% від TWAP
    require(
        amountOut >= (expectedAmountOut * 97) / 100,
        "Price deviation too high"
    );
}

Автоматизація та триггери

Два підходи до запуску buyback:

Keeper-based (рекомендується): Chainlink Automation або Gelato Network. Смарт-контракт визначає умову (checkUpkeep), keeper вызиває performUpkeep. Децентралізовано, не потрібно доверено сервера.

// Сумісність з Chainlink Automation
function checkUpkeep(bytes calldata)
    external
    view
    returns (bool upkeepNeeded, bytes memory)
{
    upkeepNeeded = paymentToken.balanceOf(address(this)) >= minBuybackAmount;
}

function performUpkeep(bytes calldata) external {
    require(
        paymentToken.balanceOf(address(this)) >= minBuybackAmount,
        "Condition not met"
    );
    uint256 balance = paymentToken.balanceOf(address(this));
    uint256 minOut = _calculateMinOut(balance);
    executeBuyback(balance, minOut);
}

Schedule-based: щоденний/щотижневий buyback по часу. Простіше для комунікації зі спільнотою, але менш capital efficient.

Прозорість та репортинг

Спільнота повинна бачити кожен buyback. Рекомендовані метрики для публічного дашборда:

Метрика Описання
Total burned Сумарний burn за все час
Buyback frequency Кількість buyback за період
Avg price Середня ціна покупки
Protocol revenue Виручка, спрямована на buyback
Burn rate % пропозиції знищено

Усі дані беруться з on-chain подій BuybackExecuted — додаткової інфраструктури не потрібно, тільки індексація подій.