Разработка системы ретроактивных баллов для airdrop
Ретроактивный airdrop — это награда пользователям, которые уже взаимодействовали с протоколом до момента snapshot. Идея: вместо того чтобы раздавать токены всем подряд по whitelist-у, проект вознаграждает реальных участников — тех, кто торговал, предоставлял ликвидность, использовал governance. Первый масштабный прецедент — Uniswap в 2020 году. После него модель points + airdrop стала стандартом индустрии.
Проблема в том, что наивная реализация («взял on-chain данные, посчитал баллы, раздал токены») не работает. Sybil-атаки — одна адресная ферма с сотнями кошельков съедает 30–60% allocation. Tokens без vesting немедленно дампятся. Поэтому система баллов — это не просто SQL-запросы по on-chain данным, а инфраструктура с многоуровневой защитой и продуманной механикой.
Архитектура points-системы
Off-chain vs on-chain подсчёт
Большинство production-систем считают баллы off-chain и публикуют Merkle root в смарт-контракт. Причина простая: полный on-chain подсчёт с историческими данными нереален по газу. Схема:
- Индексация on-chain событий через The Graph или собственный indexer (PostgreSQL + событийная модель)
- Расчёт баллов по правилам (Python/TypeScript скрипт, воспроизводимый и аудируемый)
- Публикация итоговой таблицы
address → pointsв IPFS - Построение Merkle tree из этой таблицы
- Запись Merkle root в контракт airdrop
Пользователь при claim предоставляет Merkle proof своего адреса и количества баллов. Контракт проверяет proof против root — не нужно хранить on-chain все 500k+ адресов.
Структура правил начисления баллов
Хорошая points-система многомерная. Пример для DEX-протокола:
| Действие | База | Множитель | Примечание |
|---|---|---|---|
| Volume торговли | 1 балл / $100 | × 1.5 за early user | До определённой даты |
| LP позиция | 0.1 балл / день / $1000 TVL | × 2 за concentrated range | Uniswap V3-стиль |
| Governance vote | 50 баллов / голос | × 1.2 за делегирование | Только реальные пропозалы |
| Referral | 10% баллов реферала | — | Ограничено глубиной 1 |
Временной decay — важный параметр. Ранние пользователи получают множитель, который уменьшается по мере приближения к snapshot. Это стимулирует взаимодействие заранее, а не rush в последний момент.
Sybil-защита
Это самый технически сложный компонент. Стандартные подходы:
On-chain кластерный анализ. Адреса, которые финансируются с одного источника, используют одинаковые паттерны газа, взаимодействуют в одинаковое время UTC — флагируются как потенциальные кластеры. Инструменты: Hop Protocol использовал анализ транзакционных графов; Arbitrum применял комбинацию финансового анализа и активности.
Минимальные пороги. Адрес с объёмом менее $500 и менее 5 транзакций — исключается полностью. Это отсекает большинство автоматических ферм с минимальными депозитами.
Верификация через Gitcoin Passport или Worldcoin. Опционально: пользователь с верифицированной идентичностью получает бонусный множитель (1.5–2x). Это incentivize верификацию без hard requirement-а.
Decay баллов для быстрых кошельков. Если кошелёк появился за 2 недели до snapshot и сразу набрал максимум — баллы урезаются на 50–80%. Органические пользователи взаимодействуют на протяжении месяцев.
Контракт airdrop с vesting
Базовая Merkle-based структура
contract AirdropWithVesting {
bytes32 public merkleRoot;
mapping(address => uint256) public claimedAmount;
mapping(address => uint256) public vestingStart;
uint256 public constant CLIFF = 30 days;
uint256 public constant VESTING_DURATION = 180 days;
function claim(
uint256 totalPoints,
uint256 tokenAmount,
bytes32[] calldata proof
) external {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, tokenAmount));
require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");
require(vestingStart[msg.sender] == 0, "Already claimed");
vestingStart[msg.sender] = block.timestamp;
// токены переводятся в контракт vesting, не сразу пользователю
_startVesting(msg.sender, tokenAmount);
}
}
Vesting вместо мгновенного release — стандарт после того, как airdrop-ы без vesting (например, раздача токенов новым L2-проектов) немедленно дампились на 80–90% в первый день.
Линейный vesting с cliff
После cliff-а (30–90 дней) начинается линейный vesting на 3–6 месяцев. Claim в любой момент освобождает накопленную часть:
function claimable(address user) public view returns (uint256) {
if (block.timestamp < vestingStart[user] + CLIFF) return 0;
uint256 elapsed = block.timestamp - (vestingStart[user] + CLIFF);
uint256 vested = (totalAllocation[user] * min(elapsed, VESTING_DURATION)) / VESTING_DURATION;
return vested - claimedAmount[user];
}
Инструменты индексации и расчёта
The Graph — стандарт для индексации событий. Subgraph на AssemblyScript описывает обработчики для каждого события протокола, данные хранятся в GraphQL-доступной базе. Запросы для расчёта баллов — GraphQL с агрегацией.
Dune Analytics — быстрый способ прототипировать правила начисления через SQL без собственной инфраструктуры. Не подходит для production-расчётов (нет гарантии реального времени), но отлично для валидации методологии.
Собственный indexer — PostgreSQL + event listener (ethers.js или viem). Полный контроль над данными, возможность сложных JOIN-запросов. Требует поддержки инфраструктуры.
Стек и сроки
Расчётный backend: Python (pandas для трансформаций) или TypeScript. Merkle tree: OpenZeppelin merkle-tree библиотека (JavaScript). Смарт-контракт: Solidity 0.8.x + Foundry. Тестирование: генерация тестовых Merkle proof в Foundry-тестах.
Типичные сроки: проектирование правил и анализ данных — 2–3 недели, разработка контракта и индексера — 3–4 недели, sybil-анализ и финальный snapshot — 1–2 недели.
Стоимость определяется после уточнения протокола, количества адресов и требований к sybil-защите.







