Розробка стейблкоїна

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

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

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

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

  • 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

Розробка стейблкоїна

Коли приходить запит "нам потрібен стейблкоїн", перше запитання не "яку ціну підтримувати?", а "за рахунок чого тримається прив'язка?". Це визначає все: архітектуру контрактів, вимоги до інфраструктури, регуляторні ризики та складність операційного управління. Існують три принципово різні архітектури — кожна зі своїми умовами робочого стану.

Три моделі стейблкоїна

Забезпечений фіатом

Модель USDC, USDT: 1 токен = 1 доларів на банківському рахунку. Технічно найпростіша: мінтери мінтять при отриманні фіату, бернери спалюють при виводі. Центральний емітент виступає кастодіаном.

Технічні компоненти: ERC-20 з role-based minting, чорний список (так, USDC і USDT можуть заморозити вашу адресу — договірне зобов'язання перед регуляторами), upgradeable proxy (Circle оновлював контракт USDC кілька разів).

Регуляторна реальність: в ЄС потребує ліцензію EMI (Electronic Money Institution) під MiCA з 2024 року. В США — state money transmitter licenses у кожному штаті. Бар'єр входу — десятки мільйонів доларів у резервах та compliance.

Забезпечений крипто

Модель DAI (MakerDAO CDP модель): користувач блокує ETH/WBTC як забезпечення, отримує DAI. Over-collateralization на 150%+ забезпечує буфер при волатильності. Коли ціна забезпечення падає нижче порога ліквідації — позиція ліквідується.

Це найбільш складна та цікава архітектура з інженерної точки зору.

Алгоритмічний

Не прив'язаний до зовнішнього активу — seigniorage механіка або rebase. Історія алгоритмічних стейблкоїнів похмура: Terra/Luna ($40B капіталізація → $0 за три дні в травні 2022), Basis Cash, Empty Set Dollar — всі розпались при втраті довіри. Чистий алгоритмічний стейблкоїн без якого-небудь collateral backing — це матеріал для академічних робіт, не для production.

Детальна реалізація CDP стейблкоїна

Сосредоточимось на крипто-забезпеченій архітектурі — вона реалістична для незалежної розробки та технічно змістовна.

Структура основних контрактів

VaultManager     — відкриття/закриття позицій, управління забезпеченням
PriceFeed        — Chainlink оракули для цін забезпечення
LiquidationEngine — автоматична ліквідація недостатньо забезпечених позицій
StablecoinToken  — ERC-20 стейблкоїн з контрольованим мінтингом
StabilityPool    — пул ліквідаторів, отримують забезпечення зі знижкою
FeeCollector     — збір stability fee, розподіл kazny

VaultManager: Відкриття позиції

contract VaultManager {
    struct Vault {
        uint256 collateralAmount;  // ETH/WBTC заблоковано
        uint256 debtAmount;        // мінтені стейблкоїни
        address collateralToken;
        uint256 lastFeeTimestamp;
    }
    
    mapping(address => mapping(address => Vault)) public vaults;
    
    // Параметри за типом забезпечення
    mapping(address => CollateralParams) public collateralParams;
    
    struct CollateralParams {
        uint256 liquidationRatio;    // напр., 150% = 15000 (bps)
        uint256 stabilityFeeRate;    // річна ставка, напр., 0.5%
        uint256 liquidationPenalty;  // штраф при ліквідації, напр., 13%
        uint256 debtCeiling;         // максимум боргу за цим забезпеченням
        bool    isEnabled;
    }
    
    function openVault(
        address collateralToken,
        uint256 collateralAmount,
        uint256 stablecoinAmount    // скільки стейблкоїнів хочемо отримати
    ) external nonReentrant {
        CollateralParams memory params = collateralParams[collateralToken];
        require(params.isEnabled, "Collateral not supported");
        
        // Перевірити що ratio забезпечення достатній
        uint256 collateralValueUSD = _getCollateralValue(
            collateralToken,
            collateralAmount
        );
        
        uint256 requiredCollateral = (stablecoinAmount * params.liquidationRatio) / 10000;
        require(collateralValueUSD >= requiredCollateral, "Insufficient collateral");
        
        // Перевірити потолок боргу
        require(
            totalDebt[collateralToken] + stablecoinAmount <= params.debtCeiling,
            "Debt ceiling reached"
        );
        
        // Прийняти забезпечення
        IERC20(collateralToken).transferFrom(msg.sender, address(this), collateralAmount);
        
        // Оновити vault
        Vault storage vault = vaults[msg.sender][collateralToken];
        vault.collateralAmount += collateralAmount;
        vault.debtAmount += stablecoinAmount;
        vault.collateralToken = collateralToken;
        vault.lastFeeTimestamp = block.timestamp;
        
        totalDebt[collateralToken] += stablecoinAmount;
        
        // Мінтити стейблкоїн користувачу
        stablecoin.mint(msg.sender, stablecoinAmount);
        
        emit VaultOpened(msg.sender, collateralToken, collateralAmount, stablecoinAmount);
    }
}

Stability Fee: Безперервне нарахування

Stability fee — це процентна ставка, яка безперервно нараховується на борг. Це служить як регуляторний важіль (підвищення fee → менше мінтять → менше пропозиція → ціна тяжіє до $1 при нижньому тиску) та як джерело доходу протоколу.

function _accrueFee(address user, address collateralToken) internal {
    Vault storage vault = vaults[user][collateralToken];
    if (vault.debtAmount == 0) return;
    
    CollateralParams memory params = collateralParams[collateralToken];
    uint256 elapsed = block.timestamp - vault.lastFeeTimestamp;
    
    // Безперервне компаундування: debt * (1 + rate)^t ≈ debt * (1 + rate * t) для малих t
    // Точна формула з натуральним логарифмом:
    uint256 feeMultiplier = _continuousCompound(params.stabilityFeeRate, elapsed);
    uint256 newDebt = (vault.debtAmount * feeMultiplier) / RAY;  // RAY = 1e27
    uint256 fee = newDebt - vault.debtAmount;
    
    vault.debtAmount = newDebt;
    vault.lastFeeTimestamp = block.timestamp;
    
    // Fee йде в Surplus Buffer протоколу
    surplusBuffer += fee;
    stablecoin.mint(address(this), fee);  // стейблкоїн "створюється" як fee
}

Математика: rpow(base, n, RAY) — точне цілочисельне піднесення в степінь, з MakerDAO DSMath.

Рушій ліквідації

contract LiquidationEngine {
    // Collateral Ratio = (collateralValue / debtValue) * 100
    function getCollateralRatio(
        address user,
        address collateralToken
    ) public view returns (uint256) {
        Vault memory vault = vaultManager.getVault(user, collateralToken);
        if (vault.debtAmount == 0) return type(uint256).max;
        
        uint256 collateralValue = priceFeed.getPrice(collateralToken) 
            * vault.collateralAmount / 1e18;
        
        return (collateralValue * 10000) / vault.debtAmount;
    }
    
    function liquidate(
        address user,
        address collateralToken,
        uint256 debtToRepay
    ) external nonReentrant {
        CollateralParams memory params = collateralParams[collateralToken];
        
        uint256 cr = getCollateralRatio(user, collateralToken);
        require(cr < params.liquidationRatio, "Vault is healthy");
        
        // Ліквідатор погашає частину боргу, отримує забезпечення зі знижкою
        // Приклад: погашає $100 боргу, отримує $113 в ETH (бонус 13%)
        uint256 collateralToSeize = (debtToRepay 
            * (10000 + params.liquidationPenalty)  // додаємо штраф
            * 1e18) / (priceFeed.getPrice(collateralToken) * 10000);
        
        // Перевірити що не забираємо більше ніж є
        Vault storage vault = vaults[user][collateralToken];
        collateralToSeize = Math.min(collateralToSeize, vault.collateralAmount);
        
        // Ліквідатор спалює стейблкоїн для погашення
        stablecoin.burnFrom(msg.sender, debtToRepay);
        
        vault.debtAmount -= debtToRepay;
        vault.collateralAmount -= collateralToSeize;
        
        // Ліквідатор отримує забезпечення
        IERC20(collateralToken).transfer(msg.sender, collateralToSeize);
        
        emit Liquidation(user, collateralToken, debtToRepay, collateralToSeize);
    }
}

Проблема швидких падінь ринку — якщо ціна ETH падає на 30% за кілька хвилин (flash crashes), ліквідатори не встигають середньої, система накопичує bad debt. Рішення: Dutch Auction liquidations (як у MakerDAO v2 Liquidations 2.0): ціна аукціону стартує високою і знижується кожні кілька секунд, спонукаючи ліквідаторів діяти швидше.

Price Oracle: Критичний компонент

Стейблкоїн повністю залежить від надійності оракула. Chainlink Data Feeds — стандарт:

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceFeed {
    mapping(address => AggregatorV3Interface) public priceFeeds;
    uint256 public constant PRICE_STALENESS_THRESHOLD = 3600; // 1 година
    
    function getPrice(address token) external view returns (uint256) {
        AggregatorV3Interface feed = priceFeeds[token];
        (
            uint80 roundId,
            int256 price,
            ,
            uint256 updatedAt,
            uint80 answeredInRound
        ) = feed.latestRoundData();
        
        require(price > 0, "Invalid price");
        require(updatedAt >= block.timestamp - PRICE_STALENESS_THRESHOLD, "Stale price");
        require(answeredInRound >= roundId, "Stale round");
        
        return uint256(price);  // 8 decimals для більшості Chainlink feeds
    }
}

Ніколи не користуйтеся spot price з Uniswap/Curve напряму — flash loan атаки маніпулюють ціною в одному блоці. TWAP як резервний оракул, Chainlink як первинний.

Механізми утримання прив'язки

Arbitrage incentives — ринковий механізм:

  • Ціна стейблкоїна < $1: арбітражери купують дешево, погашають борг (спалюють стейблкоїн), отримують забезпечення → пропозиція падає → ціна зростає
  • Ціна > $1: користувачі мінтять новий стейблкоїн (продають його) → пропозиція зростає → ціна падає

PSM (Peg Stability Module) — як у MakerDAO: прямий 1:1 своп між стейблкоїном та USDC за невелику комісію. Жорсткий якір, але вводить USDC як централізований актив якоря.

Динамічна Stability Fee — governance змінює fee rate у відповідь на відхилення ціни. Повільний механізм (потребує governance vote або автоматизованої політики).

Безпека та відомі атаки

Cream Finance Hack (2021, $130M) — flash loan атака на CREAM з використанням власного токена як забезпечення для себе. Циркулярна залежність в оракулі + flash loan = drain. Для CDP: забезпечення не повинно залежати від вартості стейблкоїна.

Euler Finance Hack (2023, $197M) — уразливість в депонуванні забезпечення без відповідного збільшення боргу. Ретельна перевірка облікових інваріантів обов'язкова: totalCollateral * price >= totalDebt * liquidationRatio повинна триматися в будь-який момент після будь-якої транзакції.

Invariant testing у Foundry — обов'язковий паттерн:

// Інваріант: протокол завжди платоспроможний
function invariant_solvency() public view {
    uint256 totalCollateralValue = calculateTotalCollateralValue();
    uint256 totalDebt = stablecoin.totalSupply();
    assertGe(totalCollateralValue, totalDebt);
}

Розклад та фази

Фаза Вміст Тривалість
Protocol design Механіка, параметри, tokenomics 2–3 тижні
Core contracts VaultManager, LiquidationEngine, PriceFeed 4–6 тижнів
Governance & parameters TimeGovernor, система регулювання параметрів 2–3 тижні
Testing suite Unit + fuzz + invariant тести 3–4 тижні
Frontend interface UI управління Vault 3–5 тижнів
Audit 1–2 аудиторських фірми 4–8 тижнів
Testnet + bug bounty 4–6 тижнів
Mainnet (staged rollout) Поступовий розширення потолку боргу 2–4 тижні

Мінімальний реалістичний термін до mainnet: 6–9 місяців. Два аудити — не розкіш, а необхідність: протягом 2021–2023 років CDP протоколи втратили >$500M через помилки в логіці ліквідації та оракулах.