Разработка NFT-membership системы

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка NFT-membership системы
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка NFT-membership системы

Самая частая ошибка в NFT-membership: разработчики реализуют проверку ownerOf(tokenId) == msg.sender и считают задачу решённой. Но NFT можно одолжить, flash loan-нуть (на один блок) или выставить на маркетплейс, сохранив доступ через делегирование. Правильная membership система требует понимания этих векторов и явного выбора модели доверия.

Контрактная архитектура

Базовая модель: владение токеном

Для простых кейсов (доступ к контенту, Discord-верификация) достаточно ERC-721 с функцией проверки:

function isMember(address user) public view returns (bool) {
    return balanceOf(user) > 0;
}

balanceOf дешевле ownerOf при множественных токенах и устойчивее к edge cases. Но она не защищает от listing: владелец может выставить NFT на OpenSea, получить доступ к закрытому контенту, и снять листинг после.

Тиерная membership через ERC-1155

Для нескольких уровней доступа (Bronze/Silver/Gold, или месяц/год/lifetime) ERC-1155 нативно подходит лучше ERC-721. Каждый tokenId — тир:

uint256 public constant TIER_BRONZE = 1;
uint256 public constant TIER_SILVER = 2;
uint256 public constant TIER_GOLD = 3;

function getMemberTier(address user) external view returns (uint256) {
    if (balanceOf(user, TIER_GOLD) > 0) return TIER_GOLD;
    if (balanceOf(user, TIER_SILVER) > 0) return TIER_SILVER;
    if (balanceOf(user, TIER_BRONZE) > 0) return TIER_BRONZE;
    return 0; // не участник
}

Тиры с накопленным доступом: Gold включает всё что есть в Silver и Bronze. Проверяем сверху вниз.

Soulbound (нетрансферабельные) membership токены

Если цель — привязать доступ к конкретному человеку, а не кошельку, используем EIP-5192 (Minimal Soulbound NFT) или просто переопределяем transfer функции:

function _beforeTokenTransfer(
    address from,
    address to,
    uint256 tokenId,
    uint256 batchSize
) internal override {
    require(from == address(0) || to == address(0), "Soulbound: non-transferable");
    super._beforeTokenTransfer(from, to, tokenId, batchSize);
}

from == address(0) — mint, to == address(0) — burn. Всё остальное запрещено. Проблема: потеря ключей = потеря membership. Решение: предусмотреть recovery механизм через мультисиг или социальное восстановление (ERC-4337 account abstraction).

Временная membership

Expiring membership требует хранения дат. Два подхода:

On-chain timestamp: маппинг tokenId → expiresAt. Проверка в isMember() включает block.timestamp < memberships[tokenId].expiresAt. Renewal — транзакция с оплатой, обновляет timestamp. Газ на каждую проверку.

Signature-based off-chain: бэкенд выдаёт подписанные JWT с expiry, контракт не хранит время. Дешевле по газу, но требует доверия к сервису подписей. Подходит для Web2-hybrid систем.

Для fully on-chain — первый подход. ERC-5643 — черновик стандарта для subscription NFT с renewSubscription(uint256 tokenId, uint64 duration).

Интеграция с off-chain системами

Верификация через EIP-1271

Для проверки membership в бэкенде без транзакций: пользователь подписывает сообщение (EIP-191 или EIP-712), бэкенд верифицирует через eth_call к isValidSignature(bytes32 hash, bytes signature) для смарт-кошельков или через ecrecover для EOA.

async function verifyMembership(
  userAddress: string,
  signature: string,
  message: string,
  nftContract: ethers.Contract
): Promise<boolean> {
  const signerAddress = ethers.verifyMessage(message, signature);
  if (signerAddress.toLowerCase() !== userAddress.toLowerCase()) return false;
  const balance = await nftContract.balanceOf(userAddress);
  return balance.gt(0);
}

Делегирование через delegate.xyz

delegate.cash (EIP-нет, но де-факто стандарт) позволяет владельцу NFT делегировать cold wallet → hot wallet. Для membership систем это важно: держатели хранят дорогой NFT в cold wallet, а взаимодействуют через горячий. Интеграция:

IDelegationRegistry constant DELEGATION_REGISTRY = 
    IDelegationRegistry(0x00000000000076A84feF008CDAbe6409d2FE638B);

function isMember(address user) public view returns (bool) {
    if (balanceOf(user) > 0) return true;
    // Проверяем делегирование
    address[] memory delegators = DELEGATION_REGISTRY.getDelegationsByDelegate(user);
    for (uint i = 0; i < delegators.length; i++) {
        if (balanceOf(delegators[i]) > 0) return true;
    }
    return false;
}

Это реальная потребность: Moonbirds, Doodles и другие крупные коллекции интегрировали delegate.cash именно для этого.

Mint механизм и ценообразование

Allowlist через Merkle Tree — стандарт для presale:

bytes32 public merkleRoot;

function allowlistMint(bytes32[] calldata proof) external payable {
    bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
    require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");
    require(msg.value >= PRICE, "Insufficient payment");
    _safeMint(msg.sender, _nextTokenId());
}

Proof генерируется off-chain (merkletreejs), root загружается в контракт. Список на 10,000 адресов — proof из ~14 хэшей, calldata ~450 байт.

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

ERC-721 membership с тирами и Merkle allowlist — 2 дня. Добавление временной подписки (ERC-5643 стиль) + бэкенд верификация — ещё 1-2 дня. Полная система с делегированием, soulbound recovery и фронтендом — 4-5 дней.