Hands-On Hardhat Часть-3 (Запись собственного жетона)


Ручная работа с Hardhat часть-3

В предыдущих частях мы создали проект, написали и развернули наш первый контракт. В этой части мы изучим стандарт ERC-20 и напишем свой токен стандарта ERC-20.

EIP

Чтобы понять ERC, мы должны сначала понять EIP (Ethereum Improvement Proposals). Как вы знаете, Ethereum и другие блокчейн-сети основаны на сообществе. На данный момент любой, кто хочет улучшить сеть, может представить свое предложение. Например, если Виталик Бутерин хочет что-то сделать для сети Ethereum, он представляет предложение, или если вы хотите что-то сделать для сети Ethereum, вы должны представить предложение. Таким образом, это похоже на предложения по улучшению Биткойна (BIP). Проще говоря, EIP — это проекты идей новых возможностей или функций дизайна, выдвигаемые любым членом сообщества для рассмотрения заинтересованными сторонами экосистемы Ethereum.

Однако эти предложения имеют фундаментальные стандарты, и вы должны четко изложить их; Abstract, Motivation, Specification, Rationale, Backwards Compatibility, Test Cases, Reference Implementation, Security Considerations.
Сейчас я не буду подробно описывать их все, я просто приведу пример предложения.

А также EIPs имеют 3 типа:

  1. Standards Track EIP
    • Ядро
    • Сетевой
    • Интерфейс
    • ERC
  2. Мета ЭИП
  3. Информационный ЭИП

более подробную информацию вы можете найти здесь

Другими словами, после того, как вы подготовили необходимую документацию, вы можете представить свое предложение. Но не все происходит сразу, потому что у ЭИП есть свои процессы.

Жизненный цикл ЭИП включает в себя определенные этапы. Сначала «идея» должна быть «составлена», что позволяет редактору ЭИП внести предложение в репозиторий ЭИП. Затем предложение переходит на стадию «рецензирования», во время которой автор запрашивает дату проведения экспертной оценки. Редактор присваивает предложению статус «последний звонок», по окончании которого оно должно получить статус «окончательный», как правило, через 14 дней.
Любая EIP может быть переведена в состояние «застой», если она остается без продвижения в течение шести месяцев. Для подачи EIP требуется высокий уровень технической компетенции, а успешный ERC — это тот, который не только перешел в состояние «окончательный», но и используется в проектах.

Процесс ЭИП

ERC20

ERC расшифровывается как «Ethereum Request for Comments», это специализированный подтип EIP, относящийся к изменениям на уровне приложений, которые не затрагивают сам протокол Ethereum.

Он был введен Фабианом Фогельштеллером в 2015-11-19 годах. Ему был присвоен номер 20 на GitHub и название «ERC20». ERC20 — это предложение, целью которого является стандартизация того, как должен быть определен контракт на токены, как мы взаимодействуем с таким контрактом на токены и как эти контракты взаимодействуют друг с другом.

→ Стандарт ERC20 предназначен для сменных токенов, созданных с использованием блокчейна Ethereum.
→ Сменный токен — это токен, который взаимозаменяем с другим токеном.
→ Этот стандартный интерфейс позволяет повторно использовать любые токены на Ethereum другими приложениями: от кошельков до децентрализованных бирж.

Существует множество ERC, таких как ERC721 и ERC1155, я не буду объяснять их все, чтобы увидеть все ERC, пожалуйста, загляните сюда.

Как я уже говорил, у каждого предложения есть фундаментальные стандарты, и вы должны их четко сформулировать, так, согласно документации EIP-20, спецификация токена ERC20 должна обеспечивать как минимум следующие функции и события:

Перед кодированием позвольте мне объяснить несколько вещей, на данный момент я не собираюсь реализовывать ERC20Interface. Потому что я не хочу изобретать колесо. Возможно, моя реализация будет иметь некоторые уязвимости и не будет экономить газ. Так что есть несколько реализаций от различных команд, я имею в виду, что я просто собираюсь использовать колесо, на сегодня я буду продолжать с Openzeppelin.

OpenZeppelin

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

Теперь приступим к кодированию;

Во-первых, нам нужно добавить зависимость openzeppelin, чтобы добавить эту зависимость, откройте терминал и запустите эту командную строку;

npm install @openzeppelin/contracts
Войти в полноэкранный режим Выйти из полноэкранного режима

Во-вторых, в структуре проекта откройте пакет contracts, создайте файл с именем MyOwnToken.sol и импортируйте контракт openzeppelin ERC20.

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
Войти в полноэкранный режим Выйдите из полноэкранного режима

Наконец, напишите свой MyOwnToken и унаследуйте его от ERC20.

Ваш код должен выглядеть следующим образом;

Ваш конструктор принимает именованный параметр initialSupply и наследует контракт ERC20, который принимает 2 параметра token name и token symbol. А также в области видимости конструктора есть функция _mint(), которая устанавливает, сколько токенов будет майнить. Теперь, возможно, некоторые из вас запутались, почему мы сделали именно так? Когда вы откроете файл ERC20.sol, вы увидите, что он унаследован от интерфейса IERC20, который, как я упоминал выше, является стандартом ERC20, все коды, которые мы должны написать, приходят от openzeppelin. Если бы мы не унаследовали MyOwnToken от ERC20, нам пришлось бы писать функции, которые есть у ERC20. И, вероятно, коды, которые мы написали, не были бы эффективными и безопасными, как коды openzeppelin.

Вот и все, мы написали свой собственный токен.

Далее, перед написанием тестов и развертыванием нашего смарт-контракта есть еще одна вещь, о которой я хочу упомянуть. Например, вы хотите, чтобы ваш токен был сгораемым или имел некоторые элементы контроля доступа и т.д., и вы затрудняетесь их написать, есть openzeppelin playground, вы выбираете опции и код вашего токена пишется автоматически, только не для ERC20, также существуют ERC721 и ERC1155. Чтобы ознакомиться с плейграундом, посетите здесь.

Теперь давайте развернем и напишем наш контрактный тест.
Сначала откройте терминал и напишите командную строку compile;

npx hardhat compile
Войти в полноэкранный режим Выйти из полноэкранного режима

После компиляции (я предполагаю, что вы не получили никаких ошибок), создайте файл deployMyOwnToken.js внутри пакета scripts и напишите коды скрипта для развертывания;

После написания скрипта откройте 2 терминала, один из которых предназначен для запуска node, а другой — для развертывания.

В первом терминале напишите

npx hardhat node
Войти в полноэкранный режим Выйти из полноэкранного режима

в другом терминале напишите;

npx hardhat run ./scripts/deployMyOwnToken.js --network localhost
Войти в полноэкранный режим Выйти из полноэкранного режима

Пока все хорошо.

Давайте напишем модульные тесты. Создадим файл с именем my-own-token-test.js внутри пакета test и код файлов будет выглядеть следующим образом;

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("MyOwnToken", function () {
  let totalSupply = "10000000000000000000000"; // 10000 * 1e18
  let MyOwnToken, myOwnToken, owner, address1, address2, address3;

  beforeEach(async function () {
    /**
     * A ContractFactory in ethers.js is an abstraction used to deploy new smart contracts,
     * so MyOwnToken here is a factory for instances of our token contract.
     */
    MyOwnToken = await ethers.getContractFactory("MyOwnToken");

    /** A Signer in ethers.js is an object that represents an Ethereum account.
     * It's used to send transactions to contracts and other accounts.
     * */
    [owner, address1, address2, ...address3] = await ethers.getSigners();

    myOwnToken = await MyOwnToken.deploy(totalSupply);
  });

  describe("Deployment", function () {
    it("Should assign the total supply of tokens to the owner", async function () {
      const ownerBalance = await myOwnToken.balanceOf(owner.address);
      expect(await myOwnToken.totalSupply()).to.equal(ownerBalance);
    });
  });

  describe("Transactions", function () {
    it("Should transfer tokens between accounts", async function () {
      const ownerBalance = await myOwnToken.balanceOf(owner.address);

      // Transfer 2000 tokens from owner to addr1
      await myOwnToken.transfer(address1.address, 2000);
      const address1Balance = await myOwnToken.balanceOf(address1.address);
      expect(address1Balance).to.equal(2000);

      // Transfer 2000 tokens from address1 to address2
      // We use .connect(signer) to send a transaction from another account
      await myOwnToken.connect(address1).transfer(address2.address, 2000);
      const address2Balance = await myOwnToken.balanceOf(address2.address);
      expect(address2Balance).to.equal(2000);
    });

    it("Should fail if sender doesn’t have enough tokens", async function () {
      const initialOwnerBalance = await myOwnToken.balanceOf(owner.address);

      // Try to send 1 token from address1 (0 tokens) to owner (1000000 tokens).
      // `require` will evaluate false and revert the transaction.
      await expect(
        myOwnToken.connect(address1).transfer(owner.address, 1)
      ).to.be.revertedWith("ERC20: transfer amount exceeds balance");

      // Owner balance shouldn't have changed.
      expect(await myOwnToken.balanceOf(owner.address)).to.equal(
        initialOwnerBalance
      );
    });
  });
});
Вход в полноэкранный режим Выйти из полноэкранного режима

укажите папку test и запустите тест в командной строке;

npx hardhat test ./test/my-own-token-test.js
Войти в полноэкранный режим Выйти из полноэкранного режима

Ну, вот и все, до встречи в следующих частях.

Ссылки:
https://eips.ethereum.org/EIPS/eip-1
https://eips.ethereum.org/EIPS/eip-20
https://dev.to/yakult/a-concise-hardhat-tutorial-part-2-writing-erc20-2jpm

Подключайтесь ко мне в социальных сетях: Twitter && LinkedIn && Github

Оцените статью
devanswers.ru
Добавить комментарий