Разработка lazy-minting NFT
Стандартный минт NFT-коллекции: создатель деплоит контракт, заранее минтит все токены, платит газ за каждый. При 10 000 токенов на Ethereum mainnet при 30 gwei — это 30–50 ETH только на минтинг. Для независимого художника, выпускающего 100 работ, это $3000–5000 авансом, до первой продажи.
Lazy minting переворачивает модель: NFT существует только как подписанный voucher до момента первой покупки. Покупатель оплачивает газ на минт в момент покупки. Создатель несёт нулевые затраты до получения revenue.
Как работает lazy minting на уровне криптографии
Voucher = подписанная структура данных
Создатель подписывает офф-чейн данные своим приватным ключом. Voucher содержит все параметры будущего NFT:
struct NFTVoucher {
uint256 tokenId;
uint256 minPrice; // минимальная цена в wei
string uri; // IPFS URI метаданных
bytes signature; // подпись создателя
}
Подпись создаётся через EIP-712 (typed structured data signing), а не через сырой eth_sign. EIP-712 важен: пользователь видит читаемые данные в MetaMask при подписи, а не hex-строку. Это защищает от phishing — поддельный домен не может создать валидную EIP-712 подпись для чужого контракта.
On-chain верификация подписи
При вызове redeem(voucher, recipient) контракт восстанавливает адрес подписанта через ecrecover:
function _verify(NFTVoucher calldata voucher) internal view returns (address) {
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
keccak256("NFTVoucher(uint256 tokenId,uint256 minPrice,string uri)"),
voucher.tokenId,
voucher.minPrice,
keccak256(bytes(voucher.uri))
)));
return ECDSA.recover(digest, voucher.signature);
}
Если восстановленный адрес совпадает с MINTER_ROLE — подпись валидна, минт разрешён. Контракт использует ECDSA из OpenZeppelin 5.x для безопасного recover.
Критические уязвимости lazy minting
Replay attack — без уникального nonce или tokenId одну подпись можно использовать многократно. Защита: проверка _exists(tokenId) перед минтом + tokenId является частью подписанных данных. Уже заминтированный tokenId вернёт revert.
Cross-contract replay — подпись валидна для конкретного контракта на конкретной сети. EIP-712 domain включает chainId и verifyingContract адрес. Подпись с Ethereum mainnet не пройдёт верификацию на Polygon — они имеют разные chainId. Разные контракты — разные verifyingContract — разные domain separator.
Front-running voucher — технически любой, кто видит voucher в мемпуле, может попробовать заминтить на свой адрес. Защита: recipient включён в подписанные данные. Voucher валиден только для конкретного адреса получателя.
Хранение и дистрибуция vouchers
Vouchers хранятся off-chain — в базе данных платформы или в IPFS. Marketplace API выдаёт voucher при инициации покупки. Для открытых продаж (кто угодно может купить) vouchers публичны. Для whitelist продаж — voucher выдаётся только верифицированным адресам.
Lazy minting для creator platforms (Rarible, OpenSea model)
На платформах типа OpenSea lazy minting работает иначе: создатель подписывает voucher через платформенный сервис. Платформа хранит vouchers. При первой продаже — платформа вызывает mintAndTransfer или lazyMint. Роялти EIP-2981 включены в voucher данные.
Для кастомного marketplace: тот же принцип, но контракт и signing service под вашим контролем.
Стек и инструменты
Контракт: Solidity 0.8.x, OpenZeppelin ERC721URIStorage, EIP-712 через EIP712 из OpenZeppelin, AccessControl для MINTER_ROLE.
Бэкенд: voucher generation сервис — Node.js с viem для signing, хранение в PostgreSQL или Redis.
Фронтенд: wagmi хуки для writeContract, отображение состояния транзакции, интеграция с IPFS через NFT.Storage для загрузки метаданных при создании.
Тесты: Foundry — тест корректной верификации, тест replay attack (должен revert), тест cross-contract (должен revert), fork-тест на mainnet для проверки ECDSA совместимости.
Процесс и сроки
Разработка контракта (1–2 дня): ERC-721 с lazy mint логикой, EIP-712 signing, верификация, роялти.
Voucher сервис (0.5 дня): API для генерации и хранения vouchers, signing через приватный ключ создателя.
Frontend компонент (1 день): купить/заминтировать страница с wallet connect, отображение pending транзакции.
Тестирование (0.5 дня): Foundry unit-тесты включая replay attacks.
Итого: 3–5 дней. Для платформы с несколькими создателями и dashboard управления vouchers — 1–2 недели. Стоимость рассчитывается индивидуально.







