Розробка token unlock трекера

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

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

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

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

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

Розробка Sybil-resistant airdrop системи

Sybil-атака на airdrop — не екзотика, це норма. Будь-який airdrop, оголошений заздалегідь, отримує армію ботів ще до момента snapshot. Після того як Optimism роздав токени в 2022 році і швидко виявилося, що значна частина отримувачів — кластери Sybil-гаманців, стандарт для серйозних дистрибуцій змінився. Тепер Sybil-resistance — обов'язковий компонент, а не опція.

Анатомія Sybil-атаки на airdrop

Атакуючий створює N гаманців, імітує критерії eligibility на кожному, отримує N долей airdrop, переводить все на головний гамань. Складність атаки залежить від вартості імітації одного гамання versus очікуваної виплати.

Три рівні Sybil-атак за складністю:

Рівень 1 — address farming. Створити гаманці, зробити мінімальні дії. Дёшево і масово. Працює проти простих критеріїв типу «хоча б одна транзакція в мережі».

Рівень 2 — activity simulation. Скриптовані взаємодії з протоколами: свапи, bridging, liquidity provision. Вартість вище — gas + час. Працює проти критеріїв обсягу транзакцій.

Рівень 3 — social graph manipulation. Створення зв'язків між акаунтами, імітація organic behavior. Дорого, але застосовується при великих сумах airdrop.

Ключове спостереження: жодний метод не дає 100% захисту. Ціль — піднести вартість Sybil-атаки вище очікуваного прибутку.

On-chain аналіз: кластеризація адрес

Граф транзакцій та common funder detection

Найбазовіший і найефективніший метод — аналіз джерела фінансування гаманців. Sybil-гаманці майже завжди фінансуються з однієї адреси або через один CEX-вивід.

import networkx as nx
from collections import defaultdict

def build_funding_graph(addresses: list[str], provider) -> nx.DiGraph:
    """
    Будуємо граф: хто кого фінансував.
    addresses — список eligible адрес.
    """
    G = nx.DiGraph()
    
    for addr in addresses:
        # Беремо першу вхідну транзакцію (initial funding)
        first_tx = provider.get_first_incoming_tx(addr)
        if first_tx:
            funder = first_tx['from']
            G.add_edge(funder, addr, tx=first_tx['hash'])
    
    return G

def detect_sybil_clusters(G: nx.DiGraph, threshold: int = 5) -> list[list[str]]:
    """
    Якщо одна адреса профінансувала >= threshold eligible адрес — кластер.
    """
    clusters = []
    for node in G.nodes():
        successors = list(G.successors(node))
        if len(successors) >= threshold:
            clusters.append(successors)
    return clusters

На практиці threshold підбирається під конкретний airdrop. Для великого airdrop з тисячами адрес — 5 цілком консервативно. Для маленького — достатньо 3.

Temporal pattern analysis

Sybil-гаманці створюються та використовуються батчами. Характерний паттерн: N гаманців активні в однакові часові вікна, з однаковими паузами між транзакціями.

def detect_temporal_clusters(
    addresses: list[str],
    txs_by_address: dict,
    time_window_seconds: int = 300,
    min_cluster_size: int = 3
) -> list[list[str]]:
    """
    Шукаємо адреси, чиї транзакції попадають в однакові
    часові вікна підозріло часто.
    """
    # Групуємо транзакції по часовим слотам
    time_slots = defaultdict(list)
    
    for addr, txs in txs_by_address.items():
        for tx in txs:
            slot = tx['timestamp'] // time_window_seconds
            time_slots[slot].append(addr)
    
    # Будуємо граф спільної активності
    co_activity = defaultdict(lambda: defaultdict(int))
    for slot, addrs in time_slots.items():
        for i, a in enumerate(addrs):
            for b in addrs[i+1:]:
                co_activity[a][b] += 1
                co_activity[b][a] += 1
    
    # Кластери з високою спільною активністю
    clusters = []
    visited = set()
    
    for addr in addresses:
        if addr in visited:
            continue
        cluster = [addr]
        for other, count in co_activity[addr].items():
            if count >= 3 and other not in visited:  # збігалися 3+ рази
                cluster.append(other)
        if len(cluster) >= min_cluster_size:
            clusters.append(cluster)
            visited.update(cluster)
    
    return clusters

Gas price та nonce patterns

Скрипти, що створюють Sybil-гаманці, часто використовують однакові параметри. Однакові gasPrice / maxFeePerGas в транзакціях різних гаманців в одному блоці — сильний сигнал. Nonce = 0 або 1 у великої кількості адрес говорить про недавнє створення під конкретний airdrop.

Identity-based верифікація

Proof of Humanity та Worldcoin

Найнадійніший Sybil-resistance — доказ унікальності особистості. Два основних протоколи:

Proof of Humanity (PoH): відео-реєстрація + соціальна верифікація (vouch від існуючих учасників). Зберігає список verified humans on-chain (Gnosis Chain). Повільно масштабується, але висока якість.

Worldcoin: біометрична верифікація через iris scan на Orb-пристроях. Видає World ID — ZK-proof унікальності особистості без розкриття біометрії.

interface IWorldID {
    function verifyProof(
        uint256 root,
        uint256 groupId,
        uint256 signalHash,
        uint256 nullifierHash,
        uint256 externalNullifierHash,
        uint256[8] calldata proof
    ) external view;
}

contract SybilResistantAirdrop {
    IWorldID public immutable worldId;
    uint256 public immutable groupId = 1;
    uint256 public immutable externalNullifier;
    
    // nullifierHash привязаний до конкретної дії (claim цього airdrop)
    // один человек = один nullifierHash = один claim
    mapping(uint256 => bool) public usedNullifiers;
    
    constructor(IWorldID _worldId, string memory appId, string memory action) {
        worldId = _worldId;
        externalNullifier = abi.encodePacked(
            abi.encodePacked(appId).hashToField(),
            abi.encodePacked(action).hashToField()
        ).hashToField();
    }
    
    function claim(
        address recipient,
        uint256 root,
        uint256 nullifierHash,
        uint256[8] calldata proof
    ) external {
        require(!usedNullifiers[nullifierHash], "Already claimed");
        
        worldId.verifyProof(
            root,
            groupId,
            abi.encodePacked(recipient).hashToField(),
            nullifierHash,
            externalNullifier,
            proof
        );
        
        usedNullifiers[nullifierHash] = true;
        _distributeTokens(recipient);
    }
}

Ключова властивість: nullifierHash унікальний для комбінації (людина, дія). Один человек не може отримати два різні nullifierHash-і для однієї дії — це забезпечується ZK-proof-ом.

Gitcoin Passport

Gitcoin Passport агрегує сигнали з різних джерел: GitHub акаунт, Twitter, ENS імя, BrightID верифікація, Proof of Humanity, POAP колекції. Кожен stamp дає score. Вище score — вище вероятність що це реальна людина.

// Перевірка Gitcoin Passport score через API
async function getPassportScore(address: string): Promise<number> {
  const response = await fetch(
    `https://api.scorer.gitcoin.co/registry/score/${scorerId}/${address}`,
    { headers: { 'X-API-KEY': process.env.GITCOIN_API_KEY! } }
  );
  const data = await response.json();
  return parseFloat(data.score ?? '0');
}

// Поріг score для eligibility
const MINIMUM_PASSPORT_SCORE = 15.0;

async function buildEligibleList(candidates: string[]): Promise<string[]> {
  const scores = await Promise.all(
    candidates.map(async (addr) => ({
      address: addr,
      score: await getPassportScore(addr)
    }))
  );
  
  return scores
    .filter(({ score }) => score >= MINIMUM_PASSPORT_SCORE)
    .map(({ address }) => address);
}

Багаторівнева scoring система

На практиці жоден метод не використовується в ізоляції. Найкращий підхід — scoring: кожна адреса отримує баллы за різні сигнали, фінальна eligibility визначається сумою.

Критерій Баллы Обґрунтування
World ID верифікація +50 Унікальність особистості
Gitcoin Passport ≥ 20 +30 Агрегована ідентичність
ENS імя +10 Довгострокова on-chain identity
Вік гамання > 1 року +10 Не створено під airdrop
Активність в кількох протоколах +15 Organic usage pattern
Без збігів в фандинг-графі +5 Не частина Sybil-кластера
Сума для eligibility ≥ 40 Налаштовується під проект

Адреси, що потрапили в Sybil-кластер при аналізі графа, отримують penalty або повну дисквалифікацію незалежно від score.

Апеляційний механізм

Будь-яка автоматична фільтрація дає false positives. Потрібен процес обжалування:

  • On-chain appeal: адреса відправляє транзакцію з доказом (Proof of Humanity proof, підпис від PoH реєстрації, пояснення пов'язаності гаманців)
  • Timelock: період для подачі апелій фіксований (наприклад, 14 днів після публікації snapshot)
  • Multisig review: команда розглядає апелії через multisig, рішення прозорі on-chain
  • Публічний список: всі відфільтровані адреси і причини публікуються до початку claim-періоду

Прозорість критична — спільнота повинна бачити, що фільтрація не произвільна.

Архітектура контракту дистрибуції

contract SybilResistantDistributor {
    bytes32 public merkleRoot;
    mapping(address => bool) public claimed;
    
    // Адреси, заблоковані за результатами Sybil-аналізу
    mapping(address => bool) public sybilBlacklist;
    
    // Мінімальний Passport score (зберігається off-chain, верифікується підписом)
    address public scoreOracle;
    
    struct ClaimData {
        uint256 amount;
        bytes32[] merkleProof;
        // Опціонально: підпис оракула що підтверджує Passport score
        bytes oracleSignature;
        uint256 passportScore;
    }
    
    function claim(ClaimData calldata data) external nonReentrant {
        require(!claimed[msg.sender], "Already claimed");
        require(!sybilBlacklist[msg.sender], "Address flagged as Sybil");
        
        // Верифікуємо Passport score якщо потрібно
        if (requirePassport) {
            _verifyPassportScore(msg.sender, data.passportScore, data.oracleSignature);
            require(data.passportScore >= minPassportScore, "Insufficient Passport score");
        }
        
        // Верифікуємо merkle proof
        bytes32 leaf = keccak256(bytes.concat(
            keccak256(abi.encode(msg.sender, data.amount))
        ));
        require(
            MerkleProof.verify(data.merkleProof, merkleRoot, leaf),
            "Invalid proof"
        );
        
        claimed[msg.sender] = true;
        token.safeTransfer(msg.sender, data.amount);
        emit Claimed(msg.sender, data.amount);
    }
    
    function _verifyPassportScore(
        address user,
        uint256 score,
        bytes calldata sig
    ) internal view {
        bytes32 hash = keccak256(abi.encodePacked(user, score, block.chainid));
        bytes32 ethHash = hash.toEthSignedMessageHash();
        require(ethHash.recover(sig) == scoreOracle, "Invalid oracle signature");
    }
}

Часові затримки як захист

Один з недооцінених інструментів — часове вікно між snapshot та оголошенням eligibility. Якщо airdrop оголошений без дати snapshot, farming вже йде. Найкраща практика:

  • Snapshot робиться без попередження або з мінімальним сповіщенням
  • Eligibility оголошується після snapshot — у атакуючих немає часу адаптуватися
  • Merkle root деплоїться через timelock (24–72 години) — спільнота може перевірити список до початку claim

Інструменти та дані

Аналіз on-chain даних: Dune Analytics (готові запити за Sybil паттернам), Nansen (wallet labeling), Arkham Intelligence (entity clustering).

Identity протоколи: Worldcoin (World ID), Proof of Humanity, BrightID, Gitcoin Passport, Lens Protocol (social graph).

Технічні інструменти: Python + networkx для граф-аналізу, The Graph для індексації, Alchemy/QuickNode для bulk RPC запитів.

Строки та scope робіт

Фаза Содержание Срок
Дизайн критеріїв eligibility Визначення метрик, порогів, scoring моделі 1–2 тиж
On-chain аналіз Збір даних, кластеризація, фільтрація 2–3 тиж
Смарт-контракти Distributor + identity інтеграція 2–3 тиж
Off-chain інфраструктура API, Merkle tree, оракул підписів 2–3 тиж
Апеляційний процес Контракт + UI + процедура 1–2 тиж
Аудит та тестування 2–3 тиж

Мінімальний реалістичний срок для production-ready системи — 10–16 тижнів. Поспіх у Sybil-фільтрації дорого обходиться репутаційно: якщо спільнота бачить очевидних ботів у списку отримувачів, довіра до проекту падає різко.