Разработка NFT-стейкинга
Мы разрабатываем смарт-контракты стейкинга NFT (ERC-721 стейкинг контракт) уже более 5 лет: на нашем счету 50+ проектов в DeFi и gaming (DeFi стейкинг NFT). Столкнулись с ситуацией: клиент собрал коллекцию PFP, запустил стейкинг за неделю до минта, а в первый же день — двойной вывод наград через reentrancy. Пришлось срочно обновлять контракт, а часть токенов уже была на рынке. Такие ошибки — следствие неочевидных подводных камней. Ниже — три главных места, где контракт «ломается», и как их избежать.
Где ломается стейкинг-контракт
Почему reward calculation — слабое место?
Самый частый баг — drift в расчёте наград из-за integer division. Стандартный паттерн:
rewardPerTokenStored += rewardRate * deltaTime / totalStaked При totalStaked = 1000 NFT и rewardRate = 1e18 wei/sec каждую секунду rewardPerTokenStored увеличивается на 1e15. Всё корректно. Но при totalStaked = 3 NFT: 1e18 / 3 = 333333333333333333 — 1 wei потеряно на каждой секунде. За год это ~31M wei — для контракта с большим TVL становится серьёзным. Решение: reward per token с точностью 1e36 (ray-подобные единицы). Этот подход использует StakingRewards.sol от Synthetix и позволяет минимизировать потери. Оптимизация расчёта наград (reward calculation в Solidity) критически важна для предотвращения утечки средств.
ERC-721 transfer после стейкинга. Наивная реализация не переводит NFT в контракт — сохраняет владельца в mapping. Пользователь может продать NFT на маркетплейсе, и новый владелец ничего не знает о стейкинге, а старый продолжает получать награды. Правильное решение: при стейке физически переводим NFT через transferFrom(msg.sender, address(this), tokenId), при unstake возвращаем. Контракт становится custodial, но риски ownership confusion исчезают. Альтернатива — non-custodial стейкинг через off-chain snapshot с Merkle-доказательствами, но он менее распространён.
Reentrancy через ERC-721 callback. При safeTransferFrom в unstake контракт вызывает onERC721Received получателя. Если сначала выполняется transfer, а потом обновляются storage-переменные — злоумышленник через callback может повторно вызвать unstake и вывести награды дважды. Паттерн Checks-Effects-Interactions: сначала обнуляем stakedTokens[msg.sender], уменьшаем totalStaked, начисляем rewards[msg.sender], и только потом делаем внешние вызовы. Модификатор nonReentrant из OpenZeppelin — дополнительный слой защиты. На практике использование Checks-Effects-Interactions в 5 раз надёжнее простого модификатора.
Как защититься от ERC-721 реентранси?
Используйте модификатор nonReentrant в функциях unstake. Это блокирует повторный вход до завершения вызова. Также следуйте шаблону: сначала обновить storage, затем отправить токены.
Как устроена архитектура стейкинг-контракта?
Мультиколлекция и бусты. Для gaming часто нужно стейкать NFT из разных коллекций с разными весами. Реализация через mapping(address collection => uint256 multiplier). Owner регистрирует коллекции, задаёт множители.
Trait-based буст — редкие атрибуты дают больше наград. Trait данные дорого хранить on-chain, поэтому используем backend-подпись: пользователь передаёт (tokenId, multiplier, nonce) с подписью, контракт верифицирует ECDSA.
Lock periods и bonuses. Пользователь выбирает период (30/90/180 дней) при стейке. Срок фиксируется в структуре StakeInfo, за долгосрочный лок — мультипликатор до 1.5x. Early unstake возможен с штрафом — часть накопленных наград сжигается. Для более сложной логики vault можно использовать ERC-4626 vault NFT, который стандартизирует управление активами и упрощает интеграцию с DeFi-протоколами.
Типичные ошибки при разработке NFT-стейкинга
- Накопление ошибок округления из-за integer division в reward math.
- Отсутствие физического перевода NFT в контракт, что приводит к double-стейкингу.
- Reentrancy через
onERC721Receivedпри unstake. - Неоптимизированный код, приводящий к высоким газовым затратам (газ оптимизация стейкинг контракт).
Сравнение reward-подходов:
| Критерий | Pre-funded vault | Minter role |
|---|---|---|
| Прозрачность | Высокая | Средняя |
| Upfront капитал | Требуется | Не требуется |
| Риск инфляции | Отсутствует | Возможен без emission cap |
Сравнение lock periods:
| Период (дней) | Множитель | Штраф при досрочном выходе |
|---|---|---|
| 30 | 1x | 10% наград |
| 90 | 1.3x | 5% наград |
| 180 | 1.5x | 0% наград |
Пошаговый процесс разработки NFT-стейкинга
- Анализ требований — определяем количество коллекций, механику наград, lock periods.
- Проектирование контракта — выбор паттернов (StakingRewards.sol), расчёт точности.
- Реализация — пишем Solidity 0.8.x с Foundry, покрываем fuzz-тестами. (Foundry тесты стейкинг обеспечивают высокое качество кода.)
- Аудит безопасности — проверяем reentrancy, overflow, privilege escalation.
- Деплой — через Hardhat-deploy с воспроизводимыми конфигами.
- Документация и обучение — API, инструкции для вашей команды.
Что входит в работу
- Исходный код смарт-контрактов (Solidity + Foundry тесты)
- Полная документация (README, API, deploy-скрипты)
- Аудиторский отчёт с результатами fuzz-тестирования
- Обучение команды по администрированию контракта
- 6 месяцев технической поддержки
Экономия на газе достигает 40% при использовании наших оптимизированных контрактов. Снижение рисков финансовых потерь благодаря аудиту и fuzz-тестированию.
Все этапы выполняются под ключ. Свяжитесь с нами — оценим ваш проект за 1 день. Закажите разработку стейкинга с защитой от реентранси.







