Розробка децентралізованої біржі (DEX)

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка децентралізованої біржі (DEX)
Складний
від 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

Розробка DEX (децентралізованої біржі)

Децентралізована біржа — це смарт-контракти, які дозволяють торгувати без посередника. Користувач ніколи не передає контроль над коштами третій стороні: усі торги відбуваються on-chain, розрахунки атомарні, кастодія — в гаманці користувача. Uniswap V3 торгує понад $1B на день. Завдання: розробити DEX з нуля — від механізму AMM до фронтенду.

Вибір моделі DEX

AMM (Automated Market Maker)

Ліквідність надається до пулів замість книги ордерів. Ціна визначається математичною формулою.

Constant Product (x * y = k) — модель Uniswap V2. Проста, працює для будь-якої пари. Недолік: низька ефективність капіталу — більшість ліквідності ніколи не використовується.

Concentrated Liquidity — модель Uniswap V3. LP вказують діапазон цін для своєї ліквідності. Ефективність капіталу в 10–100 разів вища. Складніше для LP — потрібне активне управління.

Stableswap (Curve) — для активів з подібною ціною (USDC/USDT, stETH/ETH). Мінімальний слліпаж при великих обсягах.

Order Book DEX

On-chain книга ордерів дорога в газі (кожне розміщення/скасування = транзакція). Рішення: off-chain orderbook з on-chain розрахунком (dYdX v3, Serum), або L2-based CLOB (dYdX v4 на Cosmos).

Для більшості DEX на EVM — AMM з концентрованою ліквідністю.

Constant Product AMM: смарт-контракт

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

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";

contract ConstantProductPool is ERC20 {
    address public immutable token0;
    address public immutable token1;
    
    uint256 private reserve0;
    uint256 private reserve1;
    
    uint256 private constant FEE_NUMERATOR = 997;   // 0.3% fee
    uint256 private constant FEE_DENOMINATOR = 1000;
    
    event Swap(address indexed sender, uint256 amount0In, uint256 amount1In,
               uint256 amount0Out, uint256 amount1Out, address indexed to);
    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
    
    constructor(address _token0, address _token1) ERC20("LP Token", "LP") {
        token0 = _token0;
        token1 = _token1;
    }
    
    // Додавання ліквідності
    function mint(address to) external returns (uint256 liquidity) {
        uint256 balance0 = IERC20(token0).balanceOf(address(this));
        uint256 balance1 = IERC20(token1).balanceOf(address(this));
        uint256 amount0 = balance0 - reserve0;
        uint256 amount1 = balance1 - reserve1;
        
        uint256 totalSupply_ = totalSupply();
        
        if (totalSupply_ == 0) {
            // Перше додавання ліквідності: геометричне середнє мінус MINIMUM_LIQUIDITY
            liquidity = Math.sqrt(amount0 * amount1) - 1000;
            _mint(address(0xdead), 1000); // заблокувати мінімум для запобігання інфляційній атаці
        } else {
            liquidity = Math.min(
                amount0 * totalSupply_ / reserve0,
                amount1 * totalSupply_ / reserve1
            );
        }
        
        require(liquidity > 0, "INSUFFICIENT_LIQUIDITY_MINTED");
        _mint(to, liquidity);
        
        reserve0 = balance0;
        reserve1 = balance1;
        
        emit Mint(msg.sender, amount0, amount1);
    }
    
    // Видалення ліквідності
    function burn(address to) external returns (uint256 amount0, uint256 amount1) {
        uint256 liquidity = balanceOf(address(this));
        uint256 totalSupply_ = totalSupply();
        
        amount0 = liquidity * reserve0 / totalSupply_;
        amount1 = liquidity * reserve1 / totalSupply_;
        
        require(amount0 > 0 && amount1 > 0, "INSUFFICIENT_LIQUIDITY_BURNED");
        
        _burn(address(this), liquidity);
        IERC20(token0).transfer(to, amount0);
        IERC20(token1).transfer(to, amount1);
        
        reserve0 = IERC20(token0).balanceOf(address(this));
        reserve1 = IERC20(token1).balanceOf(address(this));
        
        emit Burn(msg.sender, amount0, amount1, to);
    }
    
    // Swap
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external {
        require(amount0Out > 0 || amount1Out > 0, "INSUFFICIENT_OUTPUT_AMOUNT");
        require(amount0Out < reserve0 && amount1Out < reserve1, "INSUFFICIENT_LIQUIDITY");
        
        // Оптимістичний трансфер (flash loan паттерн)
        if (amount0Out > 0) IERC20(token0).transfer(to, amount0Out);
        if (amount1Out > 0) IERC20(token1).transfer(to, amount1Out);
        
        // Flash loan callback якщо потрібен
        if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
        
        uint256 balance0 = IERC20(token0).balanceOf(address(this));
        uint256 balance1 = IERC20(token1).balanceOf(address(this));
        
        uint256 amount0In = balance0 > reserve0 - amount0Out ? balance0 - (reserve0 - amount0Out) : 0;
        uint256 amount1In = balance1 > reserve1 - amount1Out ? balance1 - (reserve1 - amount1Out) : 0;
        
        require(amount0In > 0 || amount1In > 0, "INSUFFICIENT_INPUT_AMOUNT");
        
        // Перевіряємо інваріант з урахуванням комісії: (x + 0.997*dx)(y - dy) >= x*y
        uint256 balance0Adjusted = balance0 * FEE_DENOMINATOR - amount0In * (FEE_DENOMINATOR - FEE_NUMERATOR);
        uint256 balance1Adjusted = balance1 * FEE_DENOMINATOR - amount1In * (FEE_DENOMINATOR - FEE_NUMERATOR);
        
        require(
            balance0Adjusted * balance1Adjusted >= reserve0 * reserve1 * FEE_DENOMINATOR ** 2,
            "K_INVARIANT_VIOLATED"
        );
        
        reserve0 = uint256(balance0);
        reserve1 = uint256(balance1);
        
        emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
    }
    
    // Обчислення вихідної кількості за формулою AMM
    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) 
        public pure returns (uint256) 
    {
        require(amountIn > 0, "INSUFFICIENT_INPUT_AMOUNT");
        require(reserveIn > 0 && reserveOut > 0, "INSUFFICIENT_LIQUIDITY");
        
        uint256 amountInWithFee = amountIn * FEE_NUMERATOR;
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = reserveIn * FEE_DENOMINATOR + amountInWithFee;
        
        return numerator / denominator;
    }
}

Factory і Router

Архітектура стилю Uniswap: Factory створює пули, Router — точка входу для користувачів.

Безпека AMM

Захист від reentrancy

Всі зовнішні виклики після оновлення стану (Checks-Effects-Interactions) + ReentrancyGuard від OpenZeppelin.

Маніпуляція цінами (TWAP)

Spot ціна легко маніпулюється через flash loan на один блок. Для oracle — Time-Weighted Average Price.

Захист від MEV

Атаки frontrunning на DEX — стандартна проблема. Пом'якшення:

  • Slippage tolerance: користувач встановлює макс. слліпаж (0.5–1%), транзакція відновлюється при перевищенні
  • Deadline: транзакція відновлюється, якщо не виконана до deadline
  • Flashbots / private mempool: для великих свопів — відправка через Flashbots для запобігання frontrunning

Фронтенд DEX інтерфейс

Критичні компоненти фронтенду для AMM DEX:

  • Swap interface з real-time ціновою впливом і мінімальним отриманим
  • Liquidity management з візуалізацією діапазону (для V3-style)
  • Charts — інтеграція з The Graph для історичних даних пула
  • Wallet integration — wagmi + viem, підтримка WalletConnect v2
  • Transaction simulation — tenderly simulate перед відправкою

The Graph індексує події пула (Swap, Mint, Burn) і надає GraphQL API для аналітики.

Таймлайн розробки

Компонент Термін
AMM core контракти 4–6 тижнів
Factory + Router 3–4 тижні
TWAP oracle 1–2 тижні
Subgraph 2–3 тижні
Frontend (swap + ліквідність) 4–6 тижнів
Аудит смарт-контрактів 4–8 тижнів

MVP DEX на mainnet: 4–6 місяців з урахуванням аудиту.