Розробка контракту для airdrop через Merkle distributor

Розробка контракту для airdrop через Merkle distributor Ми часто бачимо класичну помилку — намагатися роздати токени через loop з on-chain відправкою кожному адресу. При 10 000 отримувачів це 10 000 транзакцій, десятки тисяч доларів газу та кілька годин роботи. Наша команда з 5+ річним досвідом у

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

Часті запитання

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

Розробка контракту для airdrop через Merkle distributor

Ми часто бачимо класичну помилку — намагатися роздати токени через loop з on-chain відправкою кожному адресу. При 10 000 отримувачів це 10 000 транзакцій, десятки тисяч доларів газу та кілька годин роботи. Наша команда з 5+ річним досвідом у блокчейні рекомендує інший підхід — Merkle distributor. Ви один раз on-chain встановлюєте Merkle root, а кожен отримувач сам клеймить свої токени, платячи лише за своє включення. Це знижує ваш рахунок за газ у сотні разів — Merkle distributor краще прямого перерахування у сотні разів за газом. Базова бібліотека для реалізації — OpenZeppelin MerkleProof. Економія газу становить до $50,000 на 100 000 адрес. Гарантуємо безпеку контракту за допомогою аудиту та формальної верифікації.

Які проблеми вирішуємо

  • Завеликий газ при великому списку. On-chain airdrop на 50 000 адрес може коштувати >$20,000 тільки на газі. Merkle distributor економить 99% коштів.
  • Вразливість second preimage attack. Наївна реалізація Merkle tree дозволяє зловмиснику підмінити leaf. Ми використовуємо double-hash leaf як в OpenZeppelin, що повністю блокує атаку.
  • Блокування токенів без deadline. Токени можуть назавжди залишитися в контракті, якщо ніхто не заклеймив. Додаємо deadline з можливістю повернення залишку токенів власнику.
  • Відсутність вестингу. Якщо токени повинні розподілятися поступово, вбудовуємо лінійний vesting прямо в distributor.

Порівняння підходів до airdrop

Параметр On-chain loop Merkle distributor
Транзакцій N (кожен отримувач — окремий виклик) 1 (встановлення root) + N (кожен claim — оплачує отримувач)
Газ (10k осіб, ETH mainnet) ~30 ETH ~0.1 ETH (за root) + ~0.02 ETH на користувача
Час виконання Години Хвилини (після деплою)
Безпека Залежить від газу Перевірена MerkleProof бібліотека

Фактор економії газу — до 300 разів при 10 000 адресах. Ми вже реалізували 15 airdrop контрактів для різних екосистем (Ethereum, Arbitrum, Base). Це особливо важливо для команд з обмеженим бюджетом на запуск токена.

Як працює Merkle distributor: порівняння з loop

Перехід на L2 знижує витрати на газ ще на порядок: на Arbitrum або Base claim коштує копійки, а не долари. Зв'яжіться з нами для детального розрахунку під вашу аудиторію.

Як ми це робимо

Використовуємо перевірений стек: Solidity 0.8.x + OpenZeppelin бібліотеки (MerkleProof, ERC20), для off-chain — TypeScript + @openzeppelin/merkle-tree. Розгортаємо на Ethereum L1 або L2 (Arbitrum, Base, Optimism) за вашим вибором. Приклад реалізації з bit packing для claimed status:

// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; contract MerkleAirdrop { IERC20 public immutable token; bytes32 public immutable merkleRoot; mapping(uint256 => uint256) private claimedBitMap; constructor(address _token, bytes32 _merkleRoot) { token = IERC20(_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 leaf = keccak256(bytes.concat( keccak256(abi.encode(index, account, amount)) )); // Double-hash проти second preimage attack require( MerkleProof.verify(merkleProof, merkleRoot, leaf), "Invalid proof" ); _setClaimed(index); require(token.transfer(account, amount), "Transfer failed"); emit Claimed(index, account, amount); } } 

Чому double-hash leaf?

Без нього — second preimage attack: зловмисник може підмінити leaf даними, які збігаються з intermediate node в дереві. OpenZeppelin використовує keccak256(bytes.concat(keccak256(abi.encode(...)))) саме з цієї причини.

Bit packing для claimed

Замість mapping(address => bool) використовуємо bit array: 256 статусів в одному uint256 slot. Економія SLOAD газу суттєва при великій кількості кламів.

Генерація Merkle tree off-chain

import { StandardMerkleTree } from "@openzeppelin/merkle-tree" const values = [ [0, "0xAddress1...", ethers.parseEther("100")], [1, "0xAddress2...", ethers.parseEther("250")], ] const tree = StandardMerkleTree.of(values, ["uint256", "address", "uint256"]) console.log("Merkle Root:", tree.root) for (const [i, v] of tree.entries()) { if (v[1] === "0xAddress1...") { const proof = tree.getProof(i) } } import fs from "fs" fs.writeFileSync("tree.json", JSON.stringify(tree.dump())) 

Proofs роздаєте через простий API: GET /proof?address=0x... → повертає { index, amount, proof[] }. Користувач вставляє ці дані в UI і викликає claim. API можна реалізувати на Fastify або Express — типовий код займає близько 50 рядків.

Коли потрібен vesting airdrop?

Якщо токени не повинні бути доступні одразу — вбудовуємо лінійний vesting в distributor. Клейм → токени на vesting schedule → користувач забирає їх з часом. Це захищає від миттєвого дампа.

Чому варто обрати L2 для airdrop?

На Ethereum mainnet claim коштує ~$2–10 за транзакцію. На Arbitrum, Base або Optimism — копійки. Якщо ваша аудиторія масова, L2 знижують бар'єр входу. Ми допоможемо обрати відповідний ролап і налаштувати міст для токенів.

Мережа Середня вартість claim Час підтвердження
Ethereum L1 $2–10 ~15 секунд
Arbitrum $0.01–0.05 ~1 хвилина
Base $0.01–0.03 ~1 секунда
Optimism $0.01–0.05 ~1 хвилина

Процес роботи

  1. Аналітика — обговорюємо список адрес, токен, L1/L2, чи потрібен vesting, deadline.
  2. Проектування — обираємо структуру Merkle tree, пишемо специфікацію контракту.
  3. Розробка — пишемо контракт з використанням OpenZeppelin, off‑chain скрипти, API.
  4. Тестування — unit тести, фаззинг (Echidna), симуляція в Tenderly.
  5. Деплой — на обрану мережу, верифікація контракту, тестовий claim.
  6. Підтримка — моніторинг, допомога користувачам при проблемах з claim.

Що входить в роботу

  • Смарт-контракт (Merkle distributor з опціями deadline/vesting)
  • Off-chain генератор Merkle tree + TypeScript скрипти
  • API для роздачі proofs (Fastify/Express)
  • Приклад UI інтеграції (React + viem)
  • Документація по деплою та експлуатації
  • 2 тижні пост-запуску підтримки

Ми використовуємо Echidna для fuzzing контракту, перевіряючи коректність перевірки proof, неможливість повторного claim та газові ліміти. Симуляція в Tenderly дозволяє відтворити будь-яку транзакцію до деплою.

Строки та вартість

Стандартна реалізація під ключ займає від 1 до 2 тижнів. Вартість розраховується індивідуально залежно від опцій (vesting, gasless claim, кастомний UI). Оцінимо ваш проект за один робочий день — просто напишіть нам, і ми підготуємо пропозицію. Замовте реалізацію під ключ вже сьогодні.