В этом уроке мы рассмотрим, как с помощью Foundry разработать смарт-контракт, написать для него тесты и развернуть наш смарт-контракт на блокчейне с помощью thirdweb deploy.
Инструменты и технологический стек, которые мы будем использовать:
- Solidity
- Foundry
- Thirdweb Deploy
Примечание: Обратитесь к этому репозиторию для получения ссылок на код.
Почему Foundry?
Hardhat, безусловно, хорошая среда разработки Ethereum, но у Foundry есть еще несколько преимуществ.
- В отличие от Hardhat, Foundry позволяет нам писать тесты и скрипты на Solidity.
- Foundry поставляется с библиотекой Forge Standard, которая позволяет использовать
Dappsys Test
для утверждения значений. - Мы можем просто регистрировать значения, используя
emit_log(string)
,emit_int(int_value)
,emit_uint(uint_value)
,emit_address(address_value)
и т.д. для регистрации значений различных типов данных. - Чтобы получить более подробную информацию о тестах, можно просто использовать флаг
-v
после команды test. Большее количествоv
даст нам более подробную информацию. Пример:forge test -vvv
. Мы можем добавить до пяти флаговv
. - Мы можем подшутить над пользователем (или можно сказать над аккаунтом), используя
.prank
и.startPrank
. - Мы можем установить nounce, номер блока и временную метку для учетной записи.
- Foundry предоставляет нам подробный газовый отчет для наших тестов, выполнив следующую команду.
forge test --gas-report
- Foundry предоставляет нам Fuzzing, который позволяет нам определить параметры для нашей тестовой функции, и он будет заполнять значения этих параметров во время выполнения.
Почему именно thirdweb deploy?
- Thirdweb deploy предоставляет нам
thirdweb-cli
, который позволяет развернуть наш смарт-контракт на блокчейн без использования закрытого ключа нашего аккаунта. - После развертывания контракта он предоставляет нам красивую приборную панель для взаимодействия с развернутым контрактом.
- Он поставляется с некоторыми стандартными предварительно созданными контрактами, такими как ERC-20, ERC-721 и т.д., так что мы можем напрямую развернуть и использовать его с их приборной панели.
- Поддерживается развертывание на нескольких цепочках.
- Имеет мощные SDK для наших смарт-контрактов с поддержкой многих языков и фреймворков.
Начало работы
Чтобы начать работу, нам сначала нужно установить Foundry. Чтобы установить и запустить Foundry локально, следуйте их документации здесь.
После того как Foundry будет запущен локально, создайте новый проект, выполнив следующую команду в терминале, а затем cd
в директории проекта. Для этого руководства я назвал свой проект learn-foundry
, вы можете назвать его как угодно.
forge init learn-foundry
cd learn-foundry
В терминале вы должны увидеть следующий вывод
Давайте разберемся, как выглядит структура проекта этого вновь созданного проекта.
$ tree . -d -L 1
.
├── lib
├── src
└── test
3 directories
Стартовый набор состоит из предустановленной библиотеки Forge Standard Library. Это предпочтительная библиотека тестирования, используемая для проектов Foundry. Кроме того, шаблон также поставляется с пустым стартовым контрактом и простым тестом.
Давайте напишем наш собственный простой контракт и тест для него. Для этого откройте этот проект в редакторе кода и перейдите к файлу Contract.sol
в папке src
в корневом каталоге. Вставьте приведенный ниже код в файл Contract.sol
. В этом уроке мы будем использовать простой контракт, который отслеживает счетчик и позволяет нам увеличивать, уменьшать и получать значение счетчика.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract CountContract {
uint public count;
constructor (uint _count) {
count = _count;
}
function setCount (uint _count) public {
count = _count;
}
function increment() public {
count++;
}
function decrement() public {
count--;
}
}
Пояснения к контракту
Я добавил constructor
, который будет выполняться при развертывании контракта, и в этой функции я инициализирую значение нашей переменной count
, принимая ввод от пользователя.
После этого setCount
позволяет нам установить значение нашей переменной count
. Аналогично, функции increment
и decrement
увеличивают и уменьшают значение нашей переменной count
.
Написание тестов
Поскольку наш контракт готов, перейдите к файлу Contract.t.sol
в папке test
и давайте напишем тесты для нашего контракта. У нас уже есть контракт ContractTest
, инициированный литейным заводом, внутри этого контракта вставьте приведенный ниже код.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "src/Contract.sol";
contract ContractTest is Test {
CountContract countContract;
function setUp() public {
countContract = new CountContract(10);
}
function testIncrement() public {
countContract.increment();
assertEq(countContract.count(), 11);
}
function testDecrement() public {
countContract.decrement();
assertEq(countContract.count(), 9);
}
function testSetCount() public {
countContract.setCount(20);
assertEq(countContract.count(), 20);
}
}
Пояснения к контракту ContractTest
В первой строке контракта мы определяем переменную countContract
типа CountContract
.
После этого мы определили функцию setUp
, которая является необязательной функцией, вызываемой перед запуском каждого тестового случая. В ней мы создаем новый экземпляр нашего смарт-контракта CountContract
и передаем 10 в качестве аргумента. Таким образом, мы инициализируем переменную count
в нашем смарт-контракте значением 10.
После этого у нас есть функция testIncrement
, в которой мы проверяем увеличение нашей переменной count
. Здесь мы утверждаем значение, используя функцию assertEq
, которую мы получаем из стандартного Test.sol
Forge.
Аналогично, у нас есть testDecrement
и testSetCount
, которые тестируют decrement
и setCount
соответственно. Мы использовали CountContract
в наших тестах, поэтому нам также необходимо импортировать его, добавив следующий оператор import над нашим тестовым контрактом.
import "src/Contract.sol";
Примечание: Любые функции с префиксом
test
запускаются как тестовые случаи.
Теперь давайте запустим наши тесты и посмотрим, работает ли наш контракт так, как ожидалось, или нет.
forge test
В терминале вы должны увидеть следующий вывод
Развертывание
Поскольку наши тесты пройдены, давайте развернем наш смарт-контракт на тестовой сети Rinkeby. Для развертывания мы будем использовать thirdweb-cli
из thirdweb deploy. Для этого выполните следующую команду для обнаружения контрактов или расширений в нашем проекте.
npx thirdweb detect
Разрешите установить пакет thirdweb
локально, когда появится запрос. В терминале вы должны увидеть следующий вывод
Теперь у нас все готово, поэтому давайте развернем наш смарт-контракт, выполнив следующую команду.
npx thirdweb deploy
Эта команда скомпилирует наш смарт-контракт, загрузит результат и откроет в вашем браузере панель thirdweb, как показано ниже. Если она не открывается, то откройте ссылку вручную из терминала.
Мы должны передать параметр начального счета, так как мы требовали его в нашем конструкторе. Передайте любое число по вашему выбору и выберите []Rinkeby из выпадающего списка Network. Подключите свой кошелек к приборной панели thirdweb и убедитесь, что вы находитесь в тестовой сети Rinkeby. После подключения нажмите на кнопку Развернуть сейчас. Откроются 2 всплывающих окна MetaMasks, подтвердите обе транзакции. Как только транзакции будут выполнены, появится приборная панель, как показано ниже.
Вот и все! Вы успешно развернули свой контракт, не подвергая риску свой закрытый ключ. Теперь вы можете использовать эту приборную панель для работы с вашим контрактом.
Некоторые полезные ресурсы по Foundry
- Учебник по Foundry
- Шпаргалка по Foundry