Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. NFT и стандарт ERC-721
erc721_nft

NFT и стандарт ERC-721

Не взаимозаменяемые токены, tokenId, tokenURI, метаданные, safeTransferFrom, ERC-1155

NFT и стандарт ERC-721

NFT — это не картинка, это уникальный токен с доказуемым правом собственности на блокчейне

#Что такое ERC-721

ERC-721 определяет стандарт невзаимозаменяемых (non-fungible) токенов. В отличие от ERC-20, каждый токен уникален и идентифицируется числовым tokenId. Нельзя поменять один NFT на другой "по номиналу" — у каждого своя история и метаданные.

Примеры применения: цифровое искусство (CryptoPunks, BAYC), игровые предметы, доменные имена (ENS), сертификаты, тикеты на события, deed на реальную собственность.

#Интерфейс ERC-721

Минимальный стандарт ERC-721 включает:

interface IERC721 { // Сколько NFT принадлежит owner function balanceOf(address owner) external view returns (uint256 balance); // Кто владеет tokenId function ownerOf(uint256 tokenId) external view returns (address owner); // Перевод NFT (небезопасный — не проверяет получателя) function transferFrom(address from, address to, uint256 tokenId) external; // Безопасный перевод — проверяет, что получатель умеет принимать NFT function safeTransferFrom(address from, address to, uint256 tokenId) external; // Разрешить конкретному адресу управлять одним tokenId function approve(address to, uint256 tokenId) external; // Разрешить/запретить адресу управлять ВСЕМИ NFT owner function setApprovalForAll(address operator, bool approved) external; // Кто имеет разрешение на конкретный tokenId function getApproved(uint256 tokenId) external view returns (address operator); // Проверить operator-разрешение function isApprovedForAll(address owner, address operator) external view returns (bool); event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); }

#Реализация NFT-коллекции

Напишем базовую NFT-коллекцию с использованием OpenZeppelin:

// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract ArtCollection is ERC721, Ownable { using Counters for Counters.Counter; Counters.Counter private _tokenIds; uint256 public constant MAX_SUPPLY = 10000; uint256 public mintPrice = 0.05 ether; // tokenId => URI метаданных mapping(uint256 => string) private _tokenURIs; constructor() ERC721("Art Collection", "ART") Ownable(msg.sender) {} // Минт за ETH function mint(string calldata tokenURI_) external payable returns (uint256) { require(msg.value >= mintPrice, "Insufficient payment"); require(_tokenIds.current() < MAX_SUPPLY, "Max supply reached"); _tokenIds.increment(); uint256 newTokenId = _tokenIds.current(); _safeMint(msg.sender, newTokenId); _tokenURIs[newTokenId] = tokenURI_; return newTokenId; } function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_ownerOf(tokenId) != address(0), "Token does not exist"); return _tokenURIs[tokenId]; } // Вывод средств владельцем function withdraw() external onlyOwner { payable(owner()).transfer(address(this).balance); } }

#tokenURI и метаданные

tokenURI(tokenId) — функция, возвращающая ссылку на JSON-файл с метаданными токена. Это может быть HTTP URL или IPFS URI.

Формат метаданных (OpenSea стандарт):

{ "name": "Art #1", "description": "Unique digital artwork", "image": "ipfs://QmHash.../1.png", "attributes": [ { "trait_type": "Background", "value": "Blue" }, { "trait_type": "Rarity", "value": "Legendary" } ] }

Для децентрализации метаданных используют IPFS. IPFS адресует файлы по содержимому (CID — Content Identifier, хэш файла), а не по местоположению. Если файл изменить — CID изменится. Это гарантирует, что изображение NFT не будет подменено после минта.

На практике многие проекты хранят метаданные централизованно (сервер продавца), что нарушает принцип decentralization. Полноценная децентрализация требует IPFS + Filecoin или Arweave для постоянного хранения.

#safeTransferFrom vs transferFrom

Разница критически важна при отправке NFT на смарт-контракты.

transferFrom просто перемещает токен — никакой проверки получателя. Если отправить NFT на контракт, который не умеет их обрабатывать, токен навсегда застрянет на этом адресе (нет метода для его вытащить).

safeTransferFrom перед завершением проверяет: если получатель — контракт, вызывает onERC721Received(operator, from, tokenId, data) и ожидает правильный return value (0x150b7a02). Если контракт не реализует этот интерфейс — транзакция откатывается, защищая токен от потери.

Правило: всегда используйте safeTransferFrom при неуверенности, что получатель — EOA.

#ERC-1155: мультитокен

ERC-1155 — расширение, позволяющее одному контракту управлять и взаимозаменяемыми, и невзаимозаменяемыми токенами. Каждый токен идентифицируется id, у него может быть произвольное amount.

Это эффективно для игр: предметы инвентаря (меч x1 — уникальный NFT; зелья x100 — взаимозаменяемые) хранятся в одном контракте. Один safeBatchTransferFrom вызов передаёт несколько типов токенов одновременно, экономя газ.

Выбор стандарта:

  • ERC-20: одинаковые взаимозаменяемые токены (валюта, governance)
  • ERC-721: уникальные невзаимозаменяемые токены (коллекционные, сертификаты)
  • ERC-1155: смесь взаимозаменяемых и невзаимозаменяемых (игровые активы, edition prints)

Далее: Безопасность смарт-контрактов