Розробка системи масового розподілу токенів

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

Розробка системи масового розповсюження токенів

Масова роздача токенів — це не просто цикл з transfer() у смарт-контракті. Коли отримувачів десятки тисяч, а кожна транзакція коштує газ, неправильна архітектура перетворює airdrop на збиткове підприємство для проекту та кошмар для користувачів, які не можуть отримати токени годинами через перевантаження мережі.

Завдання системи масового розповсюження: доставити токени максимальній кількості адрес з мінімальними витратами на газ, із захистом від зловживань та можливістю аудиту кожної виплати.

Push vs Pull: ключовий архітектурний вибір

Перше рішення — хто ініціює передачу токенів.

Push (проект → користувач): проект самостійно відправляє токени на адреси. Просто для користувача, дорого для проекту. При 50,000 отримувачів та стандартному transfer (21,000 gas) на Ethereum mainnet — мільйони доларів газу при будь-якому навантаженні на мережу.

Pull (користувач забирає): отримувач самостійно вызиває claim(). Витрати на газ падають на користувача. Додатковий бар'єр входу, але економічно справедливіше.

Merkle drop (pull з доказом): золотий стандарт для великих airdrop. Список отримувачів публікується як Merkle tree, on-chain зберігається тільки root. Користувач надає proof принадлежності до списку.

contract MerkleDistributor {
    address public immutable token;
    bytes32 public immutable merkleRoot;
    
    // Бітова карта для відслідковування claim без зберігання маппінгу адрес
    mapping(uint256 => uint256) private claimedBitMap;
    
    event Claimed(uint256 indexed index, address indexed account, uint256 amount);
    
    constructor(address token_, bytes32 merkleRoot_) {
        token = token_;
        merkleRoot = merkleRoot_;
    }
    
    function isClaimed(uint256 index) public view returns (bool) {
        uint256 claimedWordIndex = index / 256;
        uint256 claimedBitIndex = index % 256;
        uint256 claimedWord = claimedBitMap[claimedWordIndex];
        uint256 mask = (1 << claimedBitIndex);
        return claimedWord & mask == mask;
    }
    
    function claim(
        uint256 index,
        address account,
        uint256 amount,
        bytes32[] calldata merkleProof
    ) external {
        require(!isClaimed(index), "Already claimed");
        
        bytes32 node = keccak256(abi.encodePacked(index, account, amount));
        require(
            MerkleProof.verify(merkleProof, merkleRoot, node),
            "Invalid proof"
        );
        
        _setClaimed(index);
        IERC20(token).transfer(account, amount);
        
        emit Claimed(index, account, amount);
    }
    
    function _setClaimed(uint256 index) private {
        uint256 claimedWordIndex = index / 256;
        uint256 claimedBitIndex = index % 256;
        claimedBitMap[claimedWordIndex] |= (1 << claimedBitIndex);
    }
}

Бітова карта замість mapping(address => bool) економить значний обсяг storage, особливо при сотнях тисяч отримувачів.

Генерація та верифікація Merkle tree

Off-chain генерація дерева — критично важливий етап. Помилка у списку отримувачів означає неможливість отримати токени або двійні виплати.

const { MerkleTree } = require('merkletreejs');
const keccak256 = require('keccak256');
const { ethers } = require('ethers');

function generateMerkleTree(recipients) {
    // recipients: [{ index, address, amount }, ...]
    
    const leaves = recipients.map(({ index, address, amount }) => {
        return ethers.solidityPackedKeccak256(
            ['uint256', 'address', 'uint256'],
            [index, address, amount]
        );
    });
    
    const tree = new MerkleTree(leaves, keccak256, { sortPairs: true });
    const root = tree.getHexRoot();
    
    // Генеруємо proofs для кожного отримувача
    const proofs = recipients.map(({ index, address, amount }, i) => ({
        index,
        address,
        amount: amount.toString(),
        proof: tree.getHexProof(leaves[i])
    }));
    
    return { root, proofs };
}

// Публікуємо proofs через IPFS або API
// Користувач отримує свій proof та вызиває claim()

Захист від sybil та зловживань

Масове розповсюження без захисту — це запрошення до sybil-атаки. Типовий сценарій: атакуючий створює тисячі кошельків, виконує мінімальні вимоги з кожного та отримує непропорційну частку airdrop.

Рівні захисту:

On-chain критерії: враховувати тільки кошельки з реальною історією — перша транзакція до певної дати, обсяг комісій вище порога, взаємодія з конкретними протоколами.

Off-chain верифікація: Gitcoin Passport (агрегатор identity proof), Proof of Humanity, верифікація через social proof (аккаунт Twitter/Github пов'язаний з адресою). Інтегрується через signature: користувач підписує своїм кошельком повідомлення, що підтверджує власність.

Tiered airdrop: різні суми для різних категорій активності. Ранні користувачі отримують більше, ніж ті, що почали за тиждень до snapshot.

Категорія Критерій Множник
OG users Перша транзакція > 12 місяців назад 3x
Active users > 10 транзакцій за останні 6 місяців 2x
Regular users Хоча б 1 транзакція за останні 3 місяці 1x
Snapshot hunters Транзакція за останні 2 тижні 0.5x

Batch distribution для push-сценаріїв

Коли push необхідний (наприклад, компенсація постраждалих у exploit, retroactive rewards для верифікованих адрес), використовують batch transfer контракти.

Простий паттерн: multicall з кількома transfer() в одній транзакції. Більш ефективний: Disperse.app паттерн — один виклик контракту, який ітерує по масиву отримувачів.

function disperseToken(
    IERC20 token,
    address[] calldata recipients,
    uint256[] calldata amounts
) external {
    uint256 total = 0;
    for (uint256 i = 0; i < amounts.length; i++) {
        total += amounts[i];
    }
    
    token.transferFrom(msg.sender, address(this), total);
    
    for (uint256 i = 0; i < recipients.length; i++) {
        token.transfer(recipients[i], amounts[i]);
    }
}

Оптимальний розмір батча — 200–500 адрес на транзакцію залежно від мережі. Перевищення ліміту block gas limit призводить до reverts.

Vesting поверх airdrop

Для команд та інвесторів часто комбінують масове розповсюження з vesting: токени клеймяться, але не одразу доступні повністю, розблоковуються по розписанню.

Реалізація: при claim користувач не отримує токени напрямик, а деплоїться персональний VestingWallet (або створюється запис у спільному vesting контракті) з заданим розписанням. Дорожче по газу, але дає повну гнучкість у налаштуванні індивідуальних vesting schedule.

Мониторинг та аналітика

Після запуску airdrop слід відслідковувати: відсоток claimed від загального пулу, скільки адрес claim'нули у перші 24/48/72 годин, адреси, що негайно продають (on-chain через DEX events), середнє утримання токенів через 30 днів.

Ці метрики прямо пов'язані з якістю аудиторії та дозволяють скорегулювати наступний airdrop.

Терміни розробки

Merkle distributor з off-chain генерацією дерева та базовим frontend для claim — 3–4 тижні. Повнофункціональна система з sybil-захистом, tiered розповсюженням, vesting інтеграцією та аналітичним dashboard — 2–3 місяці.