Это пятый пост из серии «Мой первый смарт-контракт», цель которой — научить за семь недель некоторым концепциям solidity, пока мы не создадим токен на основе ERC-20 с некоторыми модульными тестами.
В этом посте мы разберемся, что такое hardhat, и узнаем, как загрузить наш контракт в тестовую сеть, используя Alchemy, которая поможет нам в этой части.
Инструменты
В этом посте мы будем использовать VS Code для редактирования кода, Node.js для установки и запуска кода, Alchemy для загрузки нашего контракта в тестовую сеть и Metamask для управления портфолио.
Hardhat
Hardhat — это среда разработки для программного обеспечения Ethereum. Он состоит из различных компонентов для редактирования, компиляции, отладки и развертывания ваших смарт-контрактов и dApps, которые работают вместе, создавая полноценную среду разработки.
Hardhat Runner — это основной компонент, с которым вы взаимодействуете при использовании Hardhat. Это гибкая и расширяемая программа для выполнения задач, которая помогает вам управлять и автоматизировать повторяющиеся задачи, присущие разработке смарт-контрактов и dApps.
Если вы хотите узнать больше о Hardhat, нажмите здесь — это учебник по Hardhat для начинающих.
Установка
По завершении работы над VS Code:
1 — Создадим package.json
с базовой конфигурацией:
npm init -y
2 — Установим hardhat
в качестве зависимости для разработки:
npm install --save-dev hardhat
3 — Давайте создадим новый проект:
npx hardhat
3.1 — Эта команда задаст вам несколько вопросов, чтобы узнать, какой проект вы хотите создать, давайте создадим проект JavaScript:
What do you want to do?
┗ Create a JavaScript project
3.2 — Где вы хотите создать проект hardhat:
Hardhat project root:
┗ Enter
3.3 — Если вы хотите создать файл .gitignore
:
Do you want to add a .gitignore?
┗ Y
3.4 — Если вы хотите поделиться информацией о своем проекте с Hardhat:
Help us improve Hardhat with anonymous crash reports & basic usage data?
┗ N
3.5 — Если вы хотите уже установить зависимости проекта:
Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)?
┗ Y
После выполнения этих команд hardhat создаст базовый проект, с которым нам предстоит работать.
Давайте посмотрим на файлы, созданные hardhat, и разберем каждый из них.
Контракты
Внутри папки contracts
находится место, где мы создаем наши смарт-контракты, давайте рассмотрим контракт Lock
.
Замок
Этот контракт, созданный hardhat в качестве примера, позволяет нам заблокировать определенное количество эфира на определенное время в рамках нашего контракта, и по истечении этого времени мы сможем снять это количество эфира.
Давайте изменим несколько вещей, чтобы следовать той же схеме, которую мы использовали в предыдущих постах.
Внутри файла Lock.sol
мы изменим лицензию контракта на GLP-3.0
.
// SPDX-License-Identifier: GPL-3.0
Контракт импортирует файл hardhat/console.sol
, который является файлом, содержащим некоторые функции, позволяющие нам использовать консоль для отладки нашего контракта, встроенная Solidity не имеет поддержки консоли, поэтому мы импортируем файл hardhat/console.sol
, чтобы мы могли использовать консоль.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.9;
// Import this file to use console.log
import "hardhat/console.sol";
Если вы хотите узнать немного больше об импорте других контрактов, нажмите здесь
Переменные
Наш контракт имеет две переменные: одна для сохранения владельца контракта owner
и другая для сохранения времени, на которое будет заблокировано количество эфира unlockTime
.
uint public unlockTime;
address payable public owner;
Событие
У нас есть событие для отправки информации на наш front-end, когда мы выполняем вывод эфира из контракта.
event Withdrawal(uint amount, uint when);
Конструктор
В конструкторе мы выполняем проверку на то, что _unlockTime
больше, чем block.timestamp
, если он больше, чем timestamp блока, то мы сохраняем время, когда блок будет разблокирован, и владельца контракта.
constructor(uint _unlockTime) payable {
require(
block.timestamp < _unlockTime,
"Unlock time should be in the future"
);
unlockTime = _unlockTime;
owner = payable(msg.sender);
}
Контрактный баланс
Для облегчения понимания в дальнейшем мы создадим функцию balanceOf
, которая возвращает баланс контракта.
function balanceOf() public view returns(uint){
return address(this).balance;
}
Удалить эфиры
Перед удалением эфиров из контракта проверяется, что контракт разблокирован и что тот, кто вызвал функцию, является владельцем контракта.
Если он проходит проверку, то происходит удаление Эфиров из контракта.
function withdraw() public {
// Uncomment this line to print a log in your terminal
console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); // {1}
require(block.timestamp >= unlockTime, "You can't withdraw yet");
require(msg.sender == owner, "You aren't the owner");
emit Withdrawal(address(this).balance, block.timestamp);
owner.transfer(address(this).balance);
}
В строке {1} мы можем откомментировать эту строку, чтобы проверить timestamp
, когда контракт будет разблокирован, и текущий timestamp
.
Скрипты
Внутри папки scripts
находится место, где мы можем написать сценарии для компиляции наших контрактов и развертывания их в активной или тестовой сети.
Развернуть
Deploy означает развертывать, это означает, что когда мы делаем deploy, мы загружаем наш контракт в блокчейн, чтобы другие люди могли видеть наш контракт и взаимодействовать с ним.
Давайте посмотрим на файл deploy.js
, который является файлом, содержащим всю информацию для загрузки нашего контракта в блокчейн.
В переменной hre
мы выполняем импорт функций из hardhat
с помощью require
, который является встроенным оператором node.js
и чаще всего используется для включения модулей из других отдельных файлов, вкратце это более или менее то же самое, что и import
, который мы видели ранее.
const hre = require("hardhat");
Hardhat создал асинхронную функцию main
, когда мы вызываем асинхронную функцию, она возвращает обещание, которое при разрешении возвращает нужное нам значение или ошибку, если таковая возникает.
Внутри функции main
мы используем функцию round
из библиотеки JavaScript Math
, она берет десятичное число и округляет его вниз, а внутри нее мы берем наше текущее время, делим на 1000, чтобы получить время в миллисекундах, и сохраняем все это в переменной currentTimestampInSeconds
.
const currentTimestampInSeconds = Math.round(Date.now() / 1000);
После этого есть переменная ONE_YEAR_IN_SECS
, которая представляет собой время, на которое контракт будет разблокирован в секундах. Давайте изменим эту переменную так, чтобы контракт разблокировался за более короткое время.
const ONE_YEAR_IN_SECS = 5 * 60;
Если вы хотите, чтобы имя переменной менялось в соответствии с операцией, которая ей назначается, вы можете изменить ее имя на
FIVE_MINUTES_IN_SECS
.
И в конце мы сложим значение currentTimestampInSeconds
+ FIVE_MINUTES_IN_SECS
и присвоим этот результат переменной unlockTime
.
const currentTimestampInSeconds = Math.round(Date.now() / 1000);
const FIVE_MINUTES_IN_SECS = 5 * 60;
const unlockTime = currentTimestampInSeconds + FIVE_MINUTES_IN_SECS;
Теперь изменим переменную lockedAmount
, которая теперь будет передавать контракту 0.01 Ether, нам нужно изменить количество эфиров, которое будет передано контракту, чтобы иметь возможность загрузить контракт в блокчейн.
const lockedAmount = hre.ethers.utils.parseEther("0.01");
В переменной Lock
мы подключаемся к нашему контракту, а в переменной lock
мы развертываем контракт, передавая время, на которое контракт будет заблокирован, и количество Эфиров, которое будет заблокировано.
const Lock = await hre.ethers.getContractFactory("Lock");
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
Подождем, пока контракт будет развернут, и после этого напишем в консоли адрес контракта, который поднялся в блокчейн.
await lock.deployed();
console.log("Lock with 1 ETH deployed to:", lock.address);
Hardhat создал эту функцию, чтобы мы могли использовать async/await
везде в файле и показывать ошибку на консоли, если она произойдет.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Тест
Внутри папки test
находится место, где мы можем написать тесты для наших контрактов.
В следующих нескольких постах мы более подробно остановимся на тестах.
Артефакты
Когда смарт-контракт успешно скомпилирован, для него создается JSON-файл, который сохраняется в папке artifacts
. Этот JSON содержит важную информацию о контракте в упорядоченном виде, такую как байткод, ABI, данные о развертывании, версия, среди прочего.
Мы смогли использовать JSON для взаимодействия с некоторыми библиотеками и, например, установить связь между фронтендом и контрактом.
Кэш
Каталог, используемый Hardhat для кэширования своих внутренних элементов.
Node_modules
Внутри папки node_modules
находится каталог, созданный npm
он служит для хранения всех файлов зависимостей, которые мы устанавливаем в нашем проекте.
Файлы
Загрузка контракта в блокчейн
Чтобы иметь возможность загрузить контракт в блокчейн, мы должны сначала сделать несколько вещей.
Dotenv
Откройте терминал в папке нашего проекта и выполните следующую команду.
npm install --save-dev dotenv
С помощью dotenv мы можем создавать переменные среды для каждой среды в нашем приложении.
Создайте файл .env
, внутри него мы создадим несколько переменных окружения, сделайте это потому, что нам придется использовать некоторые ключи приложения, которые не могут выходить в интернет.
Алхимия
На сайте Alchemy, после создания учетной записи и входа в систему, внутри приборной панели нажмите кнопку «Создать приложение».
Напишите название вашего приложения, напишите описание, выберите цепочку «Ethereum», сеть «Goerli» и нажмите «Create App».
Нажав на название проекта, мы попадем на экран приложения, где можно получить дополнительную информацию об использовании приложения
Нажмите на «Просмотр ключа» и скопируйте ключ «HTTPS
БУДЬТЕ ОСТОРОЖНЫ И НЕ ДЕЛИТЕСЬ ЭТОЙ ИНФОРМАЦИЕЙ С ДРУГИМИ ЛЮДЬМИ.
Внутри файла .env
введем наш ключ «HTTPS»
STAGING_ALCHEMY_KEY="COLE AQUI SUA CHAVE HTTPS"
Метамаска
Если вы еще не установили Metamask, посмотрите это видео, в котором рассказывается, как установить и настроить MetaMask.
Настроив Metamask, щелкните по своей фотографии и перейдите к настройкам.
Нажмите «Дополнительно».
Прокрутите страницу вниз, пока не найдете опцию «Показать тестовые сети» и активируйте эту опцию
После включения этой функции мы сможем видеть не только сети Mainnet, но и сети Testnet.
Теперь нажмите на «Ethereum Mainnet» и измените его на «Goerli Test Network».
Чтобы иметь возможность загрузить наши контракты в blockchain нам понадобятся деньги для оплаты GAS транзакции, но не стоит беспокоиться, так как мы используем тестовую сеть все там лежит даже деньги, для этого есть валютные краны зайдите на этот сайт Goerli faucet, скопируйте адрес своего кошелька.
Введите свой адрес и нажмите «Send Me ETH».
Теперь нам нужно взять информацию из нашего кошелька, давайте нажмем на три точки и кликнем на «Детали счета».
Нажмите на кнопку «Экспортировать закрытый ключ».
Введите пароль для вашего кошелька.
После этого он загрузит ключ нашего кошелька.
БУДЬТЕ ОСТОРОЖНЫ С ЭТИМ КЛЮЧОМ, НИКОГДА НЕ ОТПРАВЛЯЙТЕ И НЕ КЛАДИТЕ ЕГО КУДА-ЛИБО В ИНТЕРНЕТ, С ЭТИМ КЛЮЧОМ ЛЮБОЙ МОЖЕТ ПЕРЕДАТЬ ВАШ КОШЕЛЕК, НЕ ТРЕБУЯ ВАШЕГО ПАРОЛЯ.
Внутри файла .env
введем наш «PRIVATE_KEY
STAGING_ALCHEMY_KEY="COLE AQUI SUA CHAVE HTTPS"
PRIVATE_KEY="COLE AQUI SUA PRIVATE KEY"
Внутри файла hardhat.config.js
мы добавим некоторую информацию из наших сетей, используя переменные окружения, которые мы создали ранее, и импортируем файлы из dotenv
.
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url: process.env.STAGING_ALCHEMY_KEY,
accounts: [process.env.PRIVATE_KEY],
},
},
};
В терминале в папке нашего проекта выполним следующую команду:
npx hardhat run scripts/deploy.js --network goerli
Если все правильно, эта команда выполнит развертывание нашего контракта для blockchain и вернет адрес нашего контракта.
Скопировав этот адрес и войдя в Goerli Etherscan, мы можем увидеть наш контракт на блокчейне.
Нажмите здесь, чтобы увидеть контракт, который мы загрузили в блокчейн в этом посте.
Заключение
Это был пятый пост из серии постов «Мой первый смарт-контракт».
Если все прошло успешно, теперь на вашей машине настроен hardhat для развертывания смарт-контрактов на блокчейне, и у вас есть первый смарт-контракт, запущенный на тестовой сети Goerli под управлением Alchemy.
Если вам понравился этот материал и он вам чем-то помог, оставьте лайк, чтобы помочь контенту охватить больше людей.
Ссылка на репозиторий
https://github.com/viniblack/meu-primeiro-smart-contract
Давайте обменяемся идеями?
Не стесняйтесь звонить мне, чтобы обменяться идеями, вот мои контакты.
https://www.linkedin.com/in/viniblack/