ζ༼Ɵ͆ل͜Ɵ͆༽ᶘ

Анализ смарт-контракта Pepsi NFT

0 комментов
31.08.2022
8 мин чтения

Pepsi отказалась от своей первоначальной коллекции NFT в декабре 2021 года (источник), и на сегодняшний день объем торгов по этому проекту составляет 2,3 тыс. ETH (5,6 млн долларов). Я внимательно изучил контракт Pepsi NFT, чтобы узнать, как они реализовали этот проект. В этом уроке я объясню смарт-контракт построчно.

Для кого эта статья?

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

Предпосылки

Если вы понимаете ERC-721 и имеете опыт программирования, вы можете пропустить этот раздел.

  • Solidity: до сих пор большинство контрактов NFT используют Solidity. Вам не нужно знать Solidity, чтобы понять концепцию. Но если вы хотите реализовать контракт NFT самостоятельно, некоторый опыт программирования будет очень полезен. Чтобы изучить Solidity, я настоятельно рекомендую прочитать официальную документацию.
  • ERC-721: Pepsi NFT построена на смарт-контракте ERC-721, реализованном Open Zeppelin. Вкратце, стандарт ERC-721 обеспечивает базовые функции NFT, включая перевод, проверку баланса счета, минт и т. д. В этой статье дается отличный обзор: Стандарт невзаимозаменяемых токенов ERC-721.

Где смарт-контракт?

Многие проекты открывают исходный код своего контракта, и люди могут посмотреть его, прежде чем принимать какое-либо решение. Прозрачность также является одной из моих любимых функций в Blockchain индустрии.

Pepsi обнародовала адрес своего контракта NFT на официальном сайте. Вы можете просто скопировать этот адрес и найти его в Etherscan. Это место, где можно проверить информацию о блокчейне Ethereum. Адрес смарт-контракта Pepsi вот такой 0xa67D63E68715DCF9b65e45e5118b5fcD1e554b5f, вы его можете найти на сайте Pepsi, который был указан выше. Этот адрес нужно вставить в поисковую строку Etherscan. Затем вы увидите следующую страницу:

Нажав кнопку Contract, вы увидите 14 файлов. Однако нам нужен только первый файл, PepsiMicDrop.sol. Этот файл содержит контракт Pepsi NFT. Остальные — это контракты ERC-721 от Open Zeppelin, которые мы не будем рассматривать.

Советую скопировать код контракта в какой-нибудь редактор, например VS Code и смотреть его параллельно со статьей.

NFT в контракте

Прежде чем погрузиться в код, давайте сначала разберемся, как смарт-контракты определяют NFT. Под капотом у NFT есть две части информации: (1) идентификатор (2) URI.

В соответствии со стандартом ERC-721 каждый NFT уникален. Как? Контракт присваивает уникальный идентификатор каждому NFT, что обеспечивает уникальность. В контракте на основе ERC-721 вы не найдете двух разных NFT с одинаковым идентификатором.

Тогда где же изображение (это может быть и видео, документ и т.д.)? Вот где URI вступает в игру. URI означает универсальный идентификатор ресурса. Думайте об этом как об URL-адресе, через который вы можете получить все метаданные, связанные с NFT. Метаданные могут быть URL-адресом изображения, описанием, атрибутами и т. д. Самый популярный в настоящее время рынок NFT OpenSea имеет свой стандарт метаданных. Вы можете найти полный список метаданных.

Теперь вы можете спросить: обеспечивают ли URI и Id уникальность NFT?

В идеале NFT на основе ERC-721 будет иметь свое уникальное изображение или метаданные, поэтому они не взаимозаменяемы. Однако вы можете назначить один и тот же URI другому идентификатору, создав таким образом два NFT, которые на первый взгляд выглядят одинаково. Однако это не является целью ERC-721. Существует еще один стандарт, ERC-1155, который поддерживает частично взаимозаменяемый NFT. Вы можете узнать больше здесь.

Кроме того, вы можете задаться вопросом: почему метаданные не сохраняются в контракте?

Потому что хранить данные в блокчейне очень дорого, особенно изображения или видео. Тем не менее, вы по-прежнему можете хранить метаданные в сети и платить высокую плату за газ. В некоторых проектах используются изображения в формате SVG, которые значительно уменьшают размер данных, тем самым снижая плату за газ. Однако это выходит за рамки данного руководства.

Структура контракта

Контракт может показаться сложным на первый взгляд, но он хорошо организован. Рис.2 визуализирует структуру этого контракта. Пройдемся по каждому компоненту.

  • Идентификатор лицензии SPDX — это первая строка после комментария. Он указывает, как другие люди могут использовать этот код. (строка 48)
  • Версия Solidity позволяет компилятору правильно перевести код, и тогда EVM сможет его понять. (строка 49)
  • Импорт ERC-721 контракта, после чего контракт Pepsi NFT будет использовать контракт ERC-721 в качестве схемы.
  • PepsiMicDrop — это контракт NFT, о котором мы поговорим в следующем разделе. Он состоит из трех частей: (1) Переменные состояния (2) Конструктор (3) Функции.
  • Переменные состояния — это переменные, значения которых постоянно хранятся в хранилище контракта.
  • Конструктор — это специальная функция, которая выполняется только при создании контракта. Вы можете запустить код инициализации контракта.
  • Функции говорят сами за себя. Большинство функций используются для установки или получения значений состояния.

Контракт PepsiMicDrop

Давайте рассмотрим контракт PepsiMicDrop. Я объясню контракт по его функциональности, каждая функциональность связана с некоторыми функциями и переменными состояния.

(1) Constructor

constructor() ERC721("Pepsi Mic Drop", "PEPSIMICDROP") {
    reserveMicDropsId = 1; // item 1-50
    micDropsId = 51; // item 51-1893
}

Конструктор принимает 2 параметра:

  • "Pepsi Mic Drop" — это название токена NFT.
  • "PEPSIMICDROP" — это символ токена.

Назначение происходит в коде контракта ERC721, который контракт импортирует в строке 51. Вот почему вы не можете найти ничего, связанного с этим телом конструктора. Это красота наследования, и нам не нужно это переделывать.

Внутри конструктора мы видим, как две переменные состояния получают новые значения: backupMicDropsId и micDropsId. Зачем они нужны? В этом выпуске NFT Pepsi оставила себе первые 50 NFT, поэтому общедоступные NFT начинаются с идентификатора 51.

(2) Mint

Теперь поговорим о mint.

function mint(bytes32[] memory proof, bytes32 leaf) public returns (uint256) {
    // merkle tree
    if (merkleEnabled) {
        require(keccak256(abi.encodePacked(msg.sender)) == leaf, "This leaf does not belong to the sender");
        require(proof.verify(merkleRoot, leaf), "You are not in the list");
    }

    require(saleStarted == true, "The sale is paused");
    require(msg.sender != address(0x0), "Public address is not correct");
    require(alreadyMinted[msg.sender] == false, "Address already used");
    require(micDropsId <= maxMint, "Mint limit reached");

    _safeMint(msg.sender, micDropsId++);

    alreadyMinted[msg.sender] = true;

    return micDropsId;
}
Часть 1 — Merkle Proof

Они используются Merkle Proof в строках с 86 по 91. По сути, он проверяет, имеет ли пользователь право создавать NFT. Есть такое понятие, как whitelist. Иногда вам нужно попасть в этот список, чтобы позже иметь возможность минтить NFT.

Часть 2 — Обязательные условия

Следующая часть, строки с 92 по 95, определяет 4 обязательных условия mint. Пройдемся по каждому из них.

(1) Перед началом продажи NFT, для переменной состояния saleStarted установлено значение false. Таким образом, он не пройдет строку проверки 92. Когда начинается продажа, владелец контракта может вызвать функцию startSale(), чтобы изменить значение saleStarted.

require(saleStarted == true, "The sale is paused");

(2) Эта проверка гарантирует, что адрес пользователя не 0x0. 0x0 — это адрес Ethereum genesis, и ни один пользователь не будет его использовать или другими словами это "пустой" адрес.

require(msg.sender != address(0x0), "Public address is not correct");

(3) В Pepsi Drop каждый адрес может чеканить только один NFT. alreadyMinted — это переменная состояния типа mapping, похожая на словарь, которая отслеживает все адреса, отчеканенные NFT.

require(alreadyMinted[msg.sender] == false, "Address already used");=

(4) Имеется ограничение до 1983 NFT. Это проверяет, были ли заявлены все NFT. micDropsId — это уникальный идентификатор токена, о котором мы говорили выше.

require(micDropsId <= maxMint, "Mint limit reached");

Легко, верно? И мы почти закончили.

Часть 3 — Собственно сам процесс mint

Вот где на самом деле происходит mint. Хорошая новость заключается в том, что нам не нужно это реализовывать, потому что ERC-721 уже сделал это.

_safeMint(msg.sender, micDropsId++);

Для чеканки мы вызываем функцию _safemint() с адресом кошелька пользователя и уникальным идентификатором токена, и все. Под капотом есть переменная состояния (типа словаря), которая отслеживает принадлежность каждого токена. Вызывая функцию _safemint(), мы обновляем эту переменную состояния, назначаем или меняем владельца соответствующего токена.

Одно примечание: переменная состояния micDropId представляет идентификатор токена и увеличивается на 1 сразу после каждой чеканки (mint).

Часть 4 — Обновить mint адрес

Как упоминалось в части 2, каждый адрес может чеканить только один NFT.

alreadyMinted[msg.sender] = true;

Эта строка гарантирует, что тот, кто успешно создал NFT, будет зарегистрирован.

Часть 5 — Return

После чеканки идентификатор токена возвращается во frontend.

(3) Обновить URI

Последняя часть, которую нам нужно обсудить, — это функция, которая обновляет URI.

function setBaseURI(string memory _baseUri) public onlyOwner {
    baseURI = _baseUri;
}

Как вы уже знаете, каждый NFT имеет свой URI. И это функция, используемая для изменения базового URI.

Базовый URI является общей частью URI каждого NFT. По умолчанию используется URI baseURI/tokenId. Причина, по которой мы устанавливаем baseURI, заключается в том, что это экономит плату за газ. Представьте, что вы устанавливаете URI для каждого NFT, что очень дорого.

Вы можете изменить способ объединения baseURI и tokenId, переопределив функцию tokenURI, определенную в контракте ERC-721. Например, вы можете сделать что-то вроде baseURI/tokenId + ‘.json’.

Вы можете задаться вопросом, что такое public и onlyOwner. Это модификаторы функций, которые определяют условие запуска функции. public означает «внутри и вне контракта», доступ ко всем. После деплоя мы взаимодействуем с контрактом через сайт (точнее, JavaScript). onlyOwner означает, что только владелец контракта может вызывать эту функцию. Конечно, мы хотим, чтобы владелец контракта имел возможность изменить URI токена.

(4) Другие части кода

Остальной код — это просто функции для получения или установки переменных состояния, я уверен, что тут объяснение не нужно.

Конец

Итак, это все. Спасибо, что прочитали эту статью. Я надеюсь, что вы найдете это полезным.

3
Сегодня
День улёта