Базовый обзор того, как написать и протестировать смарт-контракт с использованием среды Hardhat и библиотеки Ethers.js.

Hardhat — это среда разработки Ethereum, такая же, как Truffle, которую мы будем использовать для разработки нашего контракта и развертывания его в нашей локальной сети, а EthersJs — это библиотека для взаимодействия с блокчейном Ethereum, которую мы будем использовать в наших тестовых костюмах. для взаимодействия с развернутым контрактом.

Установка и настройка

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

Итак, давайте запустим следующую команду

npm install --save-dev hardhat && npx hardhat

Это установит пакет и запустит интерактивный интерфейс для создания проекта. Мы выберем > Create an advanced sample project that uses TypeScript и продолжим.

Hardhat сгенерирует пару файлов и папок, но нас интересуют только некоторые из них.

В папке contracts будет размещен наш смарт-контракт, в папке test — наш тест, а в папке hardhat.config.ts — сгенерированная конфигурация из каски, для чего нам нужно убедиться, что определенная здесь версия Solidity соответствует указанной версии нашего контракта.

Написание смарт-контракта

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

Давайте продолжим и создадим файл с именем LockSave.sol в папке с контрактами.

Для этого простого контракта нам нужны три основные функции:

  1. Функция сохранения ETH на минимальную дату вывода
  2. Функция для вывода после того, как указанная дата прошла
  3. Функция извлечения всех сбережений с адреса владельца

Мы не будем заострять внимание на особенностях контракта, но вот как он выглядит.

Во-первых, нам нужно определить форму наших сбережений.

Далее нам нужно объявить пару переменных, которые помогут хранить и сопоставлять сохранения с отметками времени их создания, а владельцев — с отметками времени сохранения. Этот вид сопоставления помогает манипулировать нашими данными и получать к ним доступ.

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

Функция сохранения

Функция сохранения принимает временную метку вывода, добавляет новое сохранение к сохранению адреса и возвращает данные. Мы используем модификатор isValidSaving для проверки суммы и времени вывода.

Функция вывода

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

Но перед выводом мы сначала проверяем, есть ли на адресе накопления, а также время вывода и передаем эти модификаторы в функцию withdraw выше.

Наконец, мы добавим еще одну функцию для получения всех сбережений, принадлежащих запрашивающему адресу.

Тестирование смарт-контракта

Как упоминалось выше, мы создадим файл внутри папки test как index.ts, а затем импортируем из chai, ethers и hardhat.

Затем мы объявим наш тестовый костюм и развернем наш контракт в beforeEach. Это будет развертывать новый контракт каждый раз, когда мы запускаем новый тестовый пример, чтобы у нас всегда был пустой контракт для работы.

Сохранение и получение сохранения

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

Мы используем ethers.getSigners для получения адресов подписантов и извлекаем первый адрес [sender], который является адресом по умолчанию, используемым Hardhat.

ethers.utils.parseEther — это служебная функция для преобразования значения из ETH в WEI, которое является значением, которое мы хотим отправить в контракт при вызове метода оплаты save.

Ответ от контракта возвращается EthersJs в виде итератора, и, выполнив savings.value().next().value, мы можем получить доступ к значениям в виде массива.

И, наконец, используйте expect из chai, чтобы сделать утверждения.

Снятие сбережений

Для следующего теста мы сначала делаем сохранение, затем делаем вывод и, наконец, вызываем метод getSavings, чтобы подтвердить, что сумма была успешно снята.

Это будет все для наших тестовых случаев, но можно сделать больше утверждений для неудачных путей, таких как попытка уйти до того, как дата прошла, или сохранение на дату, которая уже прошла.

Для справки, я разместил два файла, смарт-контракт и тест, на GithubGist.