Foundry пришёл в экосистему Solidity как инструмент, который умеет многое и делает это быстро. В этой статье я подробно объясню, как начать работать с Foundry, какие у него ключевые возможности и на что стоит обращать внимание при написании тестов.
Что такое Foundry и почему он нужен
Foundry — это набор инструментов для разработки и тестирования смарт-контрактов на Solidity. В него входят forge для компиляции и запуска тестов, anvil как локальный тестовый узел и cast для взаимодействия с сетью из командной строки.
Главное преимущество в скорости и удобстве рабочего процесса: компиляция и тесты выполняются заметно быстрее, чем в традиционных окружениях на базе JavaScript. Кроме того, встроенные «cheatcodes» дают контроль над окружением теста — можно изменять время, баланс адресов и симулировать поведение транзакций без написания сложных вспомогательных скриптов.
Установка и базовая настройка
Установка — простой шаг. На официальном сайте Foundry есть скрипт для быстрого развёртывания, но в CI предпочтительнее использовать официальные actions или пакеты в менеджерах системы.
После установки достаточно инициализировать проект командой forge init внутри папки проекта. Эта команда создаёт минимальную структуру: папку src для контрактов и folder test для тестов, а также файл foundry.toml с конфигурацией.
Примеры команд
Ниже приведён набор основных команд, с которыми вы будете регулярно работать. Они помогают компилировать, тестировать и запускать локальную ноду.
| Команда | Назначение |
|---|---|
| forge build | Компиляция контрактов |
| forge test | Запуск тестов |
| anvil | Локальная нода для тестирования и форкинга сети |
| cast | Отправка транзакций и вызовов через CLI |
Структура тестов и шаблонный пример
В Foundry тесты обычно пишут на Solidity и организуют в файлах внутри каталога test. Тестовые контракты наследуются от Test из пакета forge-std, который предоставляет удобные утилиты и доступ к vm — интерфейсу для управления окружением.
Ниже простой пример теста. Он демонстрирует setUp, создание экземпляра контракта и использование assertEq для проверки состояния.
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../src/MyContract.sol";
contract MyContractTest is Test {
MyContract c;
function setUp() public {
c = new MyContract();
}
function testInitialValue() public {
assertEq(c.value(), 0);
}
}
Этот подход делает тесты компактными и читаемыми: вся логика и проверки находятся в Solidity, без перехода на JavaScript. Благодаря этому легче поддерживать соответствие между контрактами и их тестами.
Cheatcodes и работа с окружением
Одно из самых полезных свойств Foundry — наличие cheatcodes. Через vm можно подменять адрес отправителя, изменять время и баланс, ожидать revert и многое другое. Это снижает количество подготовительного кода.
Примеры часто используемых функций: vm.prank(address) для эмуляции транзакции от другого адреса, vm.warp(timestamp) для изменения времени в блокчейне и vm.deal(address, amount) для пополнения баланса тестового адреса. Они упрощают проверку сценариев, зависящих от внешних условий.
Пример с cheatcodes
Ниже небольшой фрагмент, иллюстрирующий использование vm.prank и vm.expectRevert при тестировании проверок доступа.
function testOnlyOwner() public {
vm.prank(address(0xBEEF));
vm.expectRevert("Ownable: caller is not the owner");
c.restrictedAction();
}
Такие приёмы сокращают объём вспомогательного кода и делают тесты более нацеленными на конкретные поведения контракта.
Fuzzing, форкинг и другие продвинутые возможности
Foundry поддерживает fuzz-тестирование из коробки. Достаточно объявить параметры функции теста, и runner будет генерировать случайные значения. Это мощный способ находить граничные случаи, которые сложно предусмотреть вручную.
Для контроля генерации можно использовать vm.assume, чтобы отбрасывать недопустимые значения. В случае провала Foundry пытается «сжать» входные данные до минимального примера, что облегчает отладку.
Форкинг mainnet и анализ взаимодействий
Анвил позволяет форкать mainnet и запускать тесты против реального состояния сети. Это удобно, когда нужно проверить взаимодействие с популярными протоколами или контрактами сторонних авторов.
Команда для запуска тестов с форком выглядит примерно так: forge test —fork-url . При работе с форком стоит учитывать лимиты провайдера RPC и следить за приватными ключами при использовании в CI.
Интеграция в CI и рекомендации по рабочему процессу
Включение Foundry в CI повышает уверенность в релизах. Базовый сценарий включает установку Foundry на агенте, запуск forge test и, при необходимости, использование anvil для тестов с форком.
Для GitHub Actions существует официальный action, который упрощает установку. Важно кэшировать папки с кэшем сборки и артефактами компиляции, чтобы уменьшить время выполнения пайплайнов.
# Пример шага для GitHub Actions
- name: Setup Foundry
uses: foundry-rs/setup-foundry@v1
- name: Run tests
run: forge test --fork-url ${{ secrets.RPC_URL }}
Практические советы и типичные ошибки
Одна из частых ошибок — неправильные remappings для импортов, особенно при использовании внешних библиотек. Проверяйте foundry.toml и корректно указывайте пути, чтобы компилятор находил зависимости.
Ещё одна ловушка — тесты, зависящие от глобального состояния. Если тесты не изолированы, они могут становиться флакy — вести себя по-разному при повторных запусках. Решение простое: восстанавливайте состояние в setUp и используйте отдельные экземпляры контрактов.
Также стоит следить за версиями Solidity. Даже незначительные изменения в компиляторе могут повлиять на поведение, поэтому фиксируйте версию в pragma и в конфигурации проекта.
Мой опыт: как Foundry поменял подход к тестированию
В нескольких проектах я заметил, что переход на Foundry резко сократил время на обратную связь. Тесты, которые раньше выполнялись минуты, теперь проходят за секунды. Это стимулирует писать больше проверок и чаще запускать их локально.
Особенно помогли cheatcodes: тесты, для которых раньше требовалось развертывание сложного окружения, стали простыми и устойчивыми. Форкинг mainnet упростил проверку интеграций с DeFi-протоколами без необходимости развертывать моки.
Когнитивная экономия: как писать тесты, которые почти не ломаются
Пиши тесты небольшими и явными. Каждая функция теста должна проверять одну поведение. Если в тесте много шагов, при ошибке сложнее понять причину и восстановить минимальный пример.
Используй invariants и property-based подходы для контроля общих свойств контракта. Это часто даёт больше пользы, чем множество частных кейсов, поскольку ловит неожиданные нарушения логики при изменениях кода.
Заключительная мысль
Foundry — это не просто ещё один инструмент в наборе разработчика, это платформа, которая меняет рабочий цикл разработки смарт-контрактов. Быстрая компиляция, удобные cheatcodes, встроенный fuzzing и простая интеграция в CI делают его отличным выбором для серьезных проектов.
Если вы ещё не пробовали работать с ним, начните с небольшого тестового репозитория: инициализируйте проект, напишите пару тестов и оцените скорость обратной связи. Через несколько итераций вы заметите, как подход к качеству кода становится более практичным и предсказуемым.

