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

Следующие пару дней мы посвятим теме invariant тестов. Сейчас о них много, кто говорит, но крайне мало команд используют в своей работе. А все из-за того, что этот паттерн, возможно, для некоторых разработчиков несколько сложен для понимания и написания.

Для начала поговорим о том, что вообще такое инварианты.

Я сам, давно, потратил некоторое время, пытаясь усвоить это определение. И то, что практически в каждом описании, которое я встречал, было "ивариант - это некоторое условие, которое всегда должно оставаться неизменным..." не давало мне полного представления.

Ну вот есть у нас переменные, есть константы, есть immutables, а как установить инвариант? Как его прописать в коде?

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

Попробую объяснить, что такое инвариант на простом популярном примере.

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

Это такое условие в нашем коде, которое всегда должно оставаться одинаковым. Вне зависимости от действий пользователя: перевода, сжигания и т.д.

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

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

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

Теперь давайте поговорим об инвариант тестах в Foundry на простом примере. У нас есть небольшой контракт:

contract InvariantIntro {
bool public flag;

function func_1() external {}
function func_2() external {}
function func_3() external {}
function func_4() external {}

function func_5() external {
flag = true;
}
}


Представим, что переменная flag всегда должна оставаться false не смотря ни на что.

И небольшой тест к нему:

contract IntroInvariantTest is Test {
InvariantIntro private target;

function setUp() public {
target = new InvariantIntro();
}

function invariant_flag_is_always_false() public {
assertEq(target.flag(), false);
}
}


Мы как обычно создаем переменную объекта нашего контракта и в setUp() подключаем его. А вот дальше...

Помните перед каждым тестом нам требовалось прописывать название, начиная с test..., например testIncrement(), testBlaBlaBla() и т.д.?

С инвариант тестами теперь нужно писать ключевое слово invariant. Это покажет Foundry, что мы переходим на другой вид тестов.

Как вообще работают инвариант тесты?

Если в обычных тестах (unit test) мы хотели сделать проверку конкретной части кода, например, require, то перед каждым конкретным тестом выполнялась функция setUp() и разворачивался новый контракт и его состояние памяти обнулялось.

Каждый тест мы проводили "с чистого листа".

Также и в случае с фаззингом. Каждый отдельный тест - это обнуленное состояние контракта. Поэтому, в случае unit и fuzz тестов, можно встретить определение - stateless tests.

Инвариант тесты - это уже stateful tests, когда состояние контракта не обнуляется, а наоборот, запоминается для каждого последующего вызова функции.

Смотрите, что получается:

function invariant_flag_is_always_false() public {
assertEq(target.flag(), false);
}


В этот тесте через assertEq мы проверяем нашу переменную, которая всегда должна держать состояние false.
  • 👍 2
  • ❤ 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 →