Написание смарт-контракта для NFT
Привет! Меня зовут Костанян Карен, я занимаюсь разработкой на Node.js в цифровом интеграторе Secreate. В этой статье мы разберемся как написать смарт контракт и отчеканить наши нфт.
19К открытий19К показов
Карен Костанян
Node.js разработчик Secreate
Привет! Меня зовут Костанян Карен, я занимаюсь разработкой на Node.js в цифровом интеграторе Secreate. В этой статье мы разберемся как написать смарт контракт и отчеканить наши нфт.
Если у вас нет медиафайлов и метаданных NFT в формате JSON, мы создали коллекцию изображений, с которыми вы можете поэкспериментировать. Вы можете найти медиафайлы здесь и файлы метаданных JSON здесь.
Мы будем использовать Hardhat, стандартную среду разработки Ethereum, для разработки, развертывания и проверки наших смарт-контрактов. Создайте пустую папку для нашего проекта и инициализируйте пустой файл package.json, выполнив в терминале следующую команду:
Теперь вы должны находиться в папке my-nft и иметь файл с именем package.json. Далее давайте установим Hardhat. Выполните следующую команду:
После установки hardhat, мы можем создать пример проекта Hardhat, выполнив следующую команду:
После этой команды, мы увидим несколько пунктов для выбора, выберите пункт (Create a basic sample project) и согласитесь со всем по умолчанию.
Давайте проверим, правильно ли установлен наш пример проекта. Выполните следующую команду:
Если все прошло успешно, вы должны увидеть следующее, отличия может быть адрес контракта:
Теперь у нас есть успешно настроенная среда разработки hardhat.
Далее, давайте установим пакет контрактов OpenZeppelin. Это даст нам доступ к контрактам ERC721 (стандарт для NFT).
Если мы хотим поделиться кодом нашего проекта публично (на веб-сайте, таком как GitHub), и при этом мы не хотим делиться конфиденциальной информацией, такой как наш закрытый ключ, API Etherscan или наш URL-адрес Alchemy (не беспокойтесь, если некоторые из этих слов вам пока не понятны), давайте установим другую библиотеку с именем dotenv.
Теперь мы установили все зависимости и можем приступить написанию нашего контракта.
Написание смарт-контракта
Наш контракт должен уметь чеканить наши NFT, а именно чеканить NFT бесплатно для владельца и продавать NFT нашим пользователям. И самое главное выводить эфиры на наш кошелек.
Вот как будет сначала выглядит наш контракт:
1. pragma solidity ^0.8.9
Весь исходный код Solidity должен начинаться с объявления версии компилятора Solidity, которую должен использовать этот код. Это делается для предотвращения проблем с будущими версиями компилятора, которые потенциально могут внести изменения, которые могут нарушить ваш код.
2. import
Если у вас есть несколько файлов и вы хотите импортировать один файл в другой, Solidity использует ключевое слово import.
3. PRICE
Цена для чеканки(mint) одного NFT.
4. baseTokenURI
URL-адрес IPFS папки, содержащей метаданные JSON.
5. mapping
Это одно из видов хранилища данных (ключей и значений) который называется Storage, здесь мы будет хранить все токены принадлежащего пользователя.
6. event
Это способ нашего контракта сообщает интерфейсу вашего приложения о том, что что-то произошло в блокчейне, и может прослушивать определенные события и предпринимать действия, когда они происходят.
Далее, мы установим baseTokenURI в нашем конструкторе. Мы также вызовем родительский конструктор(ERC721) и установим имя и символ для наших NFT.
Таким образом, наш конструктор выглядит так:
Когда мы устанавливаем его в качестве базового URI, реализация OpenZeppelin автоматически выводит URI для каждого токена. Предполагается, что метаданные токена 1 будут доступны по адресу
ipfs:/QmTMo6DFrfzKGGbkYsyMZRe16jBJcCcV72ZJHcM3a3Z2w7/1,
а метаданные токена 2 будут доступны по адресу ipfs:/QmTMo6DFrfzKGGbkYsyMZRe16jBJcCcV72ZJHcM3a3Z2w7/2
и так далее.
Однако нам нужно сообщить нашему контракту, что переменная baseTokenURI, которую мы определили, является базовым URI, который должен использовать контракт. Для этого мы переопределяем пустую функцию _baseURI() и возвращаем baseTokenURI.
Мы также пишем функцию для владельца, которая позволяет владельцу изменять baseTokenURI даже после развертывания контракта.
Резервация nft для владельца
Как владелец, вы можете зарезервировать несколько NFT для себя бесплатно (оплату надо сделать только за газ).
Здесь мы определяем публичную функцию reserveNFT, которая принимает один параметр _tokenId. Это и будет наш токен который мы хотим чеканить и зарезервировать для себя. Обратите внимание, что у этого параметра есть нижнее подчеркивание (_). Он не обязателен, но есть не прописанное внутреннее правило, что все входящие параметры мы пишем со знаком _;
1. _safeMint
Это та самая чудесная функция которая делает чеканку, ее мы берем из контракта ERC721.
2. nftOwner.
Сохраняем кому принадлежит этот токен.
3. emit
Запускаем наше событие, что пользователь (msg.sender) сделал чеканку (_tokenId)
Функция Mint NFT
Пришло время заработать немного денег. Для того чтобы пользователи могли чеканить наши nft они должны вызвать функцию mintNFT.
1. payable
Это модификатор, который дает знать что функция подлежит к оплате и пользователь отправляет эфир.
2. require:
Проверяет чтобы отправленный эфир был достаточным для чеканки nft.
Получение всех токенов, принадлежащих определенному пользователю.
Функция принимает адрес пользователя и возвращает токены которые мы хранили в хранилище nftOwner.
Вывод баланса
Самая прекрасная функция. Ее запуск, отправляет на кошелек владельца все заработанные эфиры.
Функцию может запустить только владелец.
1. balance – выбирает всю сумму на балансе контракта.
2. Проверяет чтобы баланс был положительным.
3. Отправляет эфир на кошелек владельца.
4. Проверяет что трансфер прошел успешно, в противном случае идет откат транзакции.
Проверка токена (modifier)
Если вы заметили, наши функции для чеканки reserveNFT, mintNFT могут чеканить токен который уже ранее уже был отчеканен. И перед началом процесса, мы не проверяем был ли данный токе уже отчеканен или нет. Для этого мы создадим модифаер который будет проверять статус токена до чеканки.
Модификатор функции выглядит так же как функция, но использует ключевое слово modifier вместо function. Его нельзя вызвать напрямую как функцию, вместо этого мы можем присоединить имя модификатора в конце определения функции, чтобы изменить ее поведение.
В modifier мы проверяем отчеканен ли переданный на чеканку токен. А все уже отчеканенные токены мы будем хранить в хранилище soldedTokenIds.
Самую главную роль здесь играет нижнее подчеркивание, которое находится в последней строке у модификатора. Оно вызывает остальную часть функции, на которую был вызван модификатор checkTokenStatus.
Для того чтобы наш модификатор начал правильно функционировать, мы должны добавить одно хранилище (Storage) soldedTokenIds и немного отредактировать наши функции для чеканки reserveNFT и mintNFT.
1. В самом верху контракт добавляем наше хранилище.
2. Отредактируем наши функции reserveNFT и mintNFT.
После чеканки мы храним ид токен в хранилище soldedTokenIds, и в конце функции мы добавили наш модификатор с параметром который получает наша функция.
Вот мы закончили с нашим смарт контрактом, он должен выглядеть следующим образом.
Развертывание контракта
Для того чтобы мы могли посмотреть как работает наш контракт, мы должны развернуть его на тестовых сетях, например на Rinkeby.
Примечание. Советую развернуть его на сети Rinkeby, чтобы мы могли посмотреть результат на платформе opensea, так как из других сетей на данный момент это будет невозможно.
Для развертывания нам понадобятся следующие вещи. URL-адрес RPC, закрытый ключ от кошелька и апи ключ от etherscan.io
1. Нам понадобится URL-адрес RPC, который позволит транслировать нашу транзакцию создания контракта. Мы будем использовать Алхимию. Создайте учетную запись в Alchemy, потом необходимо создать приложение (это бесплатно).
Пишем любое название, CHAIN: Ethereum, NETWORK: Rinkeby
После того как приложение создано, перейдите на панель инструментов Alchemy и выберите его. Откроется новое окно с кнопкой View Key в правом верхнем углу. Нажмите на кнопку и выберите URL-адрес HTTP.
2. Для того чтобы получить приватный ключ от кошелька, откройте расширение Metamask, нажмите на троеточие в правом углу, и в открывшемся окне нажмите на “Реквизиты счета”, затем на кнопку “Экспортировать закрытый ключ”.
После получения HTTP-адреса и закрытого ключа от кошелька, мы их пропишем в .env файл.
Теперь замените файл hardhat.config.js следующим содержимым.
Затем создадим файл scripts/run.js со следующим содержимым. IPFS URL замените со своим ipfs-ом (пример: ipfs://some_token/) или можете использовать наш ipfs который был описан выше.
Мы уже готовы для разворачивания нашего смарт контракта, но для этого нам потребуются деньги на нашем счете.
Фейковый эфир, вы можете взять отсюда:
Теперь когда у вас на счете есть деньги, нам надо развернуть наш контракт, для этого нужно набрать следующую команду и так как это уже реальная транзакция в сети rinkeby, мы должны будем платить газ, вот для чего нам нужен был эфир на счете.
Если все прошло успешно вы должны увидеть адрес вашего контракта. В нашем случае:
0xd440a80F4845D5bf1AdD3868573e286e2Df04df0
Вы можете проверить этот контракт на Etherscan. Перейдите на Etherscan и введите адрес контракта. Вы должны увидеть что-то вроде этого.
Нам осталось верифицировать наш контракт, чтобы полноценно использовать его.
Для верификации нам понадобится ключ Etherscan API. Зарегистрируйте бесплатную учетную запись здесь и получите доступ к своим ключам API здесь. Добавим этот ключ API в наш файл .env.
Установим следующий пакет для проверки нашего контракта.
npm install @nomiclabs/hardhat-etherscan
Теперь наш hardhat.config.js должен выглядеть следующим образом:
Теперь выполните следующие две команды:
npx hardhat clean
На места DEPLOYED_CONTRACT_ADDRESS поставьте тот адрес контракта который получили ранее, на места BASE_TOKEN_URI поставьте ваш ipfs url.
В нашем случае вторая команда выглядела так:
Теперь, если вы посетите страницу Rinkeby Etherscan вашего контракта, вы должны будете увидеть маленькую зеленую галочку рядом с вкладкой Contract, которая подтверждает что ваш контракт верифицирован и ваши пользователи теперь смогут подключаться к web3 с помощью Metamask и вызывать функции вашего контракта из самого Etherscan! Попробуйте это сами.
Подключите учетную запись, которую вы использовали для развертывания контракта и вызовите функцию reserveNFT, потом можете попросить кого-нибудь сделать чеканку через функцию mintNFT.
После того как вы отчеканили nft через reserveNFT или через mintNFT, вы на стороне OpenSea должны увидеть ваши nft (testnets.opensea.io)
После того как у вас в балансе у контракта появится эфир, только вы как владелец можете запустить функцию withdraw и после успешной транзакции на ваш кошелек зачислится весь баланс из контракта.
Заключение
Теперь у нас есть развернутый смарт-контракт, который позволяет пользователям чеканить NFT из нашей коллекции. Очевидным следующим шагом будет создание приложения web3, которое позволит нашим пользователям создавать NFT прямо с вашего веб-сайта.
19К открытий19К показов