Разработка системы антибот-защиты при минтинге

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

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

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

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1286
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1122
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    859

Разработка системы антибот-защиты при минтинге

Azuki в январе 2022 года: 8700 NFT за 3 минуты, 30 ETH газ в пике. Боты сминтили 2/3 коллекции раньше реальных пользователей. OpenSea через неделю: одни адреса перепродают по 10x. Это классическая ситуация без антибот-защиты. Следующие крупные запуски — BAYC, CryptoPunks — учли ошибки и внедрили различные механизмы. Какой из них правильный для вашей коллекции — зависит от размера аудитории и желаемого распределения.

Механизмы защиты и их trade-offs

Merkle whitelist: самая распространённая защита

Merkle tree из адресов whitelist. Каждый адрес из листа может доказать своё членство, предоставив proof из O(log n) хэшей. Контракт хранит только один root (32 байта), не весь список.

bytes32 public merkleRoot;

function whitelistMint(uint256 quantity, bytes32[] calldata proof) external payable {
    bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
    require(MerkleProof.verify(proof, merkleRoot, leaf), "Not whitelisted");
    require(!_whitelistClaimed[msg.sender], "Already claimed");
    _whitelistClaimed[msg.sender] = true;
    _mint(msg.sender, quantity);
}

Генерация Merkle tree — off-chain TypeScript скрипт через merkletreejs. Root обновляется перед минтом через setMerkleRoot() (onlyOwner). Proofs пользователи получают через API или заранее публикуются в IPFS.

Уязвимость: если frontend компрометирован, атакующий может запросить proof для любого адреса из листа через API. Защита: proof выдаётся только wallet, который его запрашивает (signature-gated API), или публикуется весь список заранее (полная открытость).

Commit-reveal: защита от frontrunning при random mint

Без commit-reveal: бот анализирует mempool, видит транзакцию с параметрами, делает точную копию с более высоким gas — frontrunning. С commit-reveal: пользователь сначала публикует keccak256(secret + address), затем через N блоков раскрывает secret. За эти N блоков копировать бессмысленно — неизвестен secret.

Двухэтапный процесс неудобен для пользователей. Используем только там, где random distribution критична и пользователи готовы к двум транзакциям.

Per-address лимиты: необходимый минимум

Самая базовая защита — лимит на адрес:

mapping(address => uint256) public mintedByAddress;
uint256 public constant MAX_PER_ADDRESS = 3;

function mint(uint256 quantity) external {
    require(mintedByAddress[msg.sender] + quantity <= MAX_PER_ADDRESS, "Limit exceeded");
    mintedByAddress[msg.sender] += quantity;
    _mint(msg.sender, quantity);
}

Не защищает от Sybil — один бот создаёт тысячи адресов. Но повышает стоимость атаки: нужно больше кошельков, gas на перемещение ETH между ними. В комбинации с другими методами — эффективно.

Глубокое погружение: proof-of-work при минтинге

Самый редко применяемый, но интересный механизм. Идея: перед минтом нужно решить вычислительную задачу — найти nonce такой, что keccak256(address + nonce) < difficulty. Это CPU/GPU работа, которую бот делает быстрее, но она создаёт resource constraint.

uint256 public mintDifficulty = type(uint256).max / 1000; // 0.1% хэшей проходят

function mint(uint256 nonce) external {
    bytes32 hash = keccak256(abi.encodePacked(msg.sender, nonce, block.number / 100));
    require(uint256(hash) < mintDifficulty, "Invalid proof of work");
    _mint(msg.sender, 1);
}

block.number / 100 — окно в ~100 блоков (~20 минут). Nonce валиден только в этом окне, нельзя вычислить заранее. Сложность настраивается через mintDifficulty.

Проблема: мобильные пользователи тратят 10-30 секунд на вычисление. Боты с GPU — 0.1 секунды. Асимметрия не в пользу обычных пользователей. Proof-of-work эффективен только в сочетании с whitelist, где боты изначально не в листе.

Время ожидания и batch limits

Дополнительная механика против ботов: максимальный mint в первые N блоков от начала — 1 токен. После N блоков — до MAX_PER_ADDRESS. Бот, который бьёт в первую секунду, получает только 1 токен. Пользователи, пришедшие через минуту, могут взять больше.

uint256 public publicMintStartBlock;

function maxMintForBlock(uint256 _block) public view returns (uint256) {
    if (_block < publicMintStartBlock + 50) return 1;  // первые ~10 мин
    return MAX_PER_ADDRESS;
}

Сравнение механизмов

Механизм Стоимость атаки UX для пользователя Сложность реализации
Per-address limit Низкая (Sybil) Отлично Минимальная
Merkle whitelist Высокая Хорошо Средняя
Commit-reveal Высокая Плохо (2 транзакции) Высокая
Proof-of-work Средняя Нормально Средняя
Batch limit по времени Средняя Отлично Низкая

Рекомендованные комбинации

Маленькая коллекция (<1000), закрытое сообщество: Merkle whitelist + per-address limit 2-3.

Средняя коллекция (1000-10000), открытый mint: Whitelist фаза (Merkle) → public фаза с batch limit по времени + per-address limit.

Крупная коллекция (>10000), высокий спрос: Whitelist фаза + public фаза с proof-of-work или раffle через VRF.

Процесс разработки

Аналитика (1 день). Определяем механику: есть ли whitelist, сколько фаз, лимиты на адрес.

Разработка (1-3 дня). Контракт с выбранными механизмами. Off-chain скрипт генерации Merkle tree. API для выдачи proofs.

Тестирование. Отдельно тестируем каждый механизм: whitelist proof verification, лимиты, timing механики. Foundry fuzz тест: testMintLimit(address,uint256) — любая комбинация не должна превышать лимит.

Ориентиры по срокам

Система с Merkle whitelist + per-address limit — 1-2 дня. Полная многофазная система с proof-of-work и commit-reveal — 3-5 дней.