TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.49K subscribers
Post #940 615
Foundry с 0. Часть 24

При всей важности fuzz тестов все обучающие видео и практические примеры сводятся к двум функциям и паре настроек конфигурации Foundry.

Fuzz тесты, или фаззинг, или нечеткое тестирование, по своей сути, это простой программный подбор таких значений в функции, при которых ее исполнение будет "ломаться".

Возьмём простой пример для наглядности:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Fuzz {
function checkNum(uint8 num) external view returns(bool){
if (num == 100) revert ("EQ 100");
if (num == 0) revert ("EQ 0");
return true;
}
}

Тут у нас простая функция для проверки какого-то вводимого числа. Из возможных 256 вариантов num - два не пройдут проверку. Но писать тест для каждого числа было бы достаточно накладно и долго.

Для этих целей и придумали фаззинг. Посмотрите на простой тест для этой функции.

contract FuzzTest is Test {
Fuzz public fuzz;
function setUp() public {
fuzz = new Fuzz();
}

/// forge-config: default.fuzz.runs = 100
function testFuzz_checkNum(uint8 num) public view {

vm.assume(num != 0);
num = uint8(bound(num, 1, 99));
fuzz.checkNum(num);
}
}


Для начала мы создаем переменную и объект контракта в setUp(), затем пишем простой тест.

Фаззинг отличается от юнит тестов тем, что для функции теста мы оставляем аргументы, которые сам Foundry и будет подбирать.

Вспомните наши предыдущие тесты, где были такие функции как:

function test_IncrementEvent() public {}

в которых нет аргументов, и функцию для фаззинга:

function testFuzz_checkNum(uint8 num) public view {}

Тут мы как бы предлагаем Foundry поработать самому и найти такие числа, которые могут поломать функцию checkNum() в нашем контракте.

Если же упростить тестовую функцию до:

function testFuzz_checkNum(uint8 num) public view {
fuzz.checkNum(num);
}


то при вызове теста, через forge test, мы получим примерно такую запись в терминале:

Running 1 test for test/Counter.t.sol:FuzzTest
[FAIL. Reason: EQ 100 Counterexample: calldata=0x6bee15a90000000000000000000000000000000000000000000000000000000000000064, args=[100]] testFuzz_checkNum(uint8) (runs: 95, μ: 8571, ~: 8571)


Обратите внимание на args=[100] - то значение, которые было найдено через фаззинг, и которое ломало вызов наш вызов.

(runs: 95, μ: 8571, ~: 8571) - runs - означает количество "пробегов" Foundry по нашему тесты до момента, когда он нашел значение "на вылет", μ: 8571 - среднее количество потраченного газа, ~: 8571 - значение по газу, которое потратили на "средний" тест. Например, у нас было проведено 95 прогонов, они были проранжированы по мере потребления газа от 1 до 95, и вот под ~ - будет тест находящийся на 48 позиции, т.е. средний из всех 95.

Но вернемся к записи в терминале. Сейчас у нас тест провалился, поэтому добавим новый читкод vm.assume().

vm.assume(num != 0); - будет означать, что наш тест должен "предполагать", что подставленное значение не должно быть равным нулю. Если такое случается, то тест не проваливается, а продолжает цикл.

num = uint8(bound(num, 1, 99)); - эта запись означает, что мы как бы ставим в рамки num значение от 1 до 99. И все значения, которые будет подбирать Foundry будут преобразовываться в числа в промежутке от 1 до 99.

Также стоит сказать пару слов об inline-config. Это такие настройки, которые мы указываем перед тестом через комментарии.

/// forge-config: default.fuzz.runs = 100

В этом случаем мы устанавливаем "пробег" тестов на количестве 100, в то время, как значение по умолчанию равно 256.

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

Также есть еще одна настройка:

/// forge-config: default.fuzz.max-test-rejects = 500

которая устанавливает количество "fail" теста перед тем, как он может считаться окончательно проваленным.
  • 👍 3
  • 🔥 1
More from @solidityset
  1. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  2. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
  3. Sep 14, 2026Графы повсюду Если вы также следите за новостями в мире ИИ, то наверняка уже все чаще встр…
  4. Sep 10, 2026GTA6, Cyberleek, блокчейн и безопасность Увидел несколько постов (тут и тут) про Cyberleek…
  5. Sep 9, 2026Работа с чистой энергией Дисклеймер Сегодня ава и название канала, наконец, поменялись. Я…
  6. Sep 9, 2026Channel name was changed to «Из Solidity в AI и дальше»
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →