TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
Из Solidity в AI и дальше

14 Nov 2023, 12:16

Открыть в Telegram Поделиться Пожаловаться

Foundry с 0. Часть 22

Настало время коснуться темы форков в наших тестах. Почему только коснуться? Потому что, когда я искал какие-либо достойные примеры этого тестирования, то чаще всего встречал либо базовые объяснения, либо копипасту.

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

Итак, поехали.

Для начала, что есть вообще форк-тест?

Форк-тест - это такой вид тестов, когда вы проверяете код своего контракта не на локальном блокчейне, тот же anvil, а на реальной сети, типа Ethereum или Optimism. Это бывает очень полезно, когда вы планируете работу своего протокола на разных сетях и хотите удостовериться, что код работает корректно на каждой выбранной сети.

Есть два способа проводить форк-тесты.

Вот простой тест для контракта с использованием WETH:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import "forge-std/console.sol";

interface IWETH {
function balanceOf(address) external view returns (uint256);
function deposit() external payable;
}

contract ForkTest is Test {
IWETH public weth;

function setUp() public {
weth = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
}

function testDeposit() public {
uint256 balBefore = weth.balanceOf(address(this));
console.log("balance before", balBefore);

weth.deposit{value: 100}();

uint256 balAfter = weth.balanceOf(address(this));
console.log("balance after", balAfter);
}
}

Здесь мы проверяем, что после депозита на реальный контракт в сети Ethereum у пользователя действительно повысится баланс.

После этого выполняем команду в терминале:

forge test --fork-url $RPC_LINK --match-contract ForkTest

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

Во втором варианте мы создаем форк не в терминале при помощи --fork-url, а используя читкоды.

И наш тест тогда будет выглядеть так:

function testDeposit() public {
uint256 forkId = vm.createSelectFork("https://mainnet.infura.io/v3/...", blockNumber);

uint256 balBefore = weth.balanceOf(address(this));
console.log("balance before", balBefore);

weth.deposit{value: 100}();

uint256 balAfter = weth.balanceOf(address(this));
console.log("balance after", balAfter);
}

С vm.createSelectFork мы создаем и выбираем сеть для форка. Да, это можно было бы делать двумя различными читкодами - createFork() и selectFork() - но с одним это проще.

Также стоит обратить внимание, что мы можем создать:

1. Просто форк сети с использованием последнего созданного блока:

vm.createSelectFork("https://mainnet.infura.io/v3/...");

2. Форк с использованием конкретного номера блока:

vm.createSelectFork("https://mainnet.infura.io/v3/...", blockNumber);

3. Форк с блоком, в котором есть определенная транзакция:

vm.createSelectFork("https://mainnet.infura.io/v3/...", txBytes32);

при этом перед самим тестом будет проведена эмуляция транзакций в данном блоке.

При этом вам также доступно манипулированием состоянием форк. Например, выполнив определенные действия в тесте на конкретном блоке или транзакции, вы можете "промотать" вперед-назад форк и выполнить другие действия. Сделать это поможет читкод - rollFork(), который принимает те же аргументы, что и его собрат выше.

Более того, необходимо отметить, что в рамках одного теста вы можете менять сети форка с одного на другой. При этом память теста будет обнуляться. Другими словами, если вы указали какие-либо данные в переменных для первой сети, то для второй - они будут обнулены.

Избежать этого поможет читкод - makePersistent(), который сохраняет данные памяти при переходе форков. Чуть подробнее об этом можно прочитать тут:

https://book.getfoundry.sh/cheatcodes/make-persistent

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

#foundry #lesson22

490 0 7 3
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot