Блокчейн3 мин чтения

Что сделать за две недели до аудита смарт-контракта

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

У аудита фиксированный бюджет внимания аудитора. Каждый час, потраченный на выяснение того, что функция вообще должна делать, — это час, не потраченный на поиск бага внутри неё. Подготовка нужна не для того, чтобы хорошо выглядеть, а чтобы перенаправить это внимание на код, который может потерять деньги.

Вот что имеет смысл сделать за две недели до старта работ.

Заморозьте код

Самое дорогое, что можно сделать, — продолжать коммитить во время аудита. Каждое изменение обесценивает уже проделанную работу и заставляет пересматривать всё, что от него зависит.

Пометьте тегом коммит, который отдаёте. Если критичный баг найдётся в середине аудита, чините его в отдельной ветке и договоритесь с аудитором, когда она вливается. Не пушьте в проверяемую ветку из-за замечания линтера.

Запишите, что система должна делать

Аудиторы находят баги, сравнивая замысел с реализацией. Без изложенного замысла они могут найти только то, что неверно самоочевидно, — реентерабельность, переполнение, отсутствующий контроль доступа. Тонкие баги, где код работает ровно так, как написан, а неверна сама логика, без спецификации не видны.

Что стоит передать:

  • Роли и их полномочия. Каждая привилегированная функция, кто может её вызвать и что произойдёт при компрометации соответствующего ключа.
  • Инварианты. Утверждения, которые обязаны выполняться всегда: сумма долей равна сумме балансов, пул не может выплатить больше, чем в нём лежит, рынок не может закрыться дважды.
  • Пути движения средств. Все способы, которыми ценность входит в систему и выходит из неё, желательно схемой.
  • От чего вы сознательно не защищались. Если вы принимаете риск недобросовестного оракула, потому что оракул — это вы, так и напишите. Иначе аудитор оформит это находкой, и вы оба потратите на неё время.

Список инвариантов — документ с самой высокой отдачей во всём пакете. Он говорит аудитору, что именно пытаться сломать, а его написание обычно само по себе вскрывает пару багов.

Сделайте так, чтобы тесты говорили правду

Процент покрытия почти ничего не значит: тест, который вызывает функцию и ничего не проверяет, считается покрытием. Значение имеет то, кодируют ли тесты инварианты из предыдущего раздела.

До аудита: прогнать весь набор до зелёного, удалить или починить пропускаемые тесты и добавить fuzz- или invariant-тест на каждый инвариант из путей движения средств. Если свойство стоит того, чтобы его сформулировать, оно стоит того, чтобы фаззер какое-то время его ломал.

Уберите очевидные находки сами

В каждом отчёте есть раздел находок низкой критичности, которые поймал бы статический анализатор. Прогоните Slither, включите все предупреждения компилятора и по каждому результату либо почините, либо явно обоснуйте. Вы платите по ставкам senior-инженера — не тратьте их на неиспользуемые импорты и незаэмиченные события.

Подготовьте историю деплоя

Неожиданно большая доля реальных инцидентов приходится на деплой и апгрейд, а не на логику контракта. Держите наготове: точную последовательность деплоя, параметры инициализации, у кого какой ключ, обновляемы ли контракты и как выглядит процедура обновления. Если есть прокси — аудитору нужна раскладка хранилища.

Резолюция — самая сложная часть рынка прогнозов

После получения отчёта

Правьте находки в отдельной ветке и напишите ответ на каждый пункт, включая те, которые не чините. «Принято, риск осознан, вот почему» — legitimate ответ, и выглядит он куда лучше, чем молча проигнорированная находка.

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

Сергей Палий

Основатель, Sepia Software

Обо мне

Читать дальше

Все статьи