Самостоятельный аудит смарт-контрактов с помощью ChatGPT
При проведении аудита смарт-контрактов необходимо охватить широкий спектр вопросов, чтобы удостовериться в безопасности кода. Эти вопросы охватывают различные аспекты, включая контроль доступа, управление активами, управление данными, допущения, зависимости и контрольные списки безопасности. Ниже мы приводим подробный чек-лист и инструкцию по запросам к ChatGPT, которые помогут вам в процессе аудита смарт-контракта.
Если вы хотите самостоятельно изучить смарт-контракт на предмет уязвимостей и скрытых методов скама, то первым шагом будет корректно составленный запрос (prompt) в ChatGPT.
Полезным запросом для ChatGPT будет следующая команда:
Предоставь исчерпывающий список всех проблем и уязвимостей в следующем смарт-контракте. Подробно опиши проблемы и возможные уязвимости. Приведи по одному сценарию использования каждой уязвимости. Вывод сделай в виде корректной таблицы в формате markdown со списком объектов, каждый из которых имеет столбцы 'description', 'action', 'severity', 'actors', 'scenario', 'type' и 'line'. 'type' где может быть 'usability', 'vulnerability', 'optimization' или 'suggestion'. 'actors' - это список задействованных субъектов. 'серьезность' может быть "низкая", "средняя" или "высокая". 'строка' - это номер строки проблемы. Убедись, что все поля таблицы заполнены.
Далее используйте следующие вопросы, чтобы более глубоко изучить смарт-контракт.
Сценарии использования:
- Кто является действующими лицами системы?
- Какими действиями обладает система?
- Какие ограничения существуют в системе?
- Какие существуют потенциальные способы сломать систему?
- Какая защита используется для противодействия атакам?
- Опиши, исходя из ограничений, изменения состояния каждой функции.
- Предоставь информацию об используемых шаблонах Solidity и DeFi.
- Напиши положительные и отрицательные аксиомы, основываясь на информации о системе.
- Перечисли способы оптимизации и изменения кода для повышения его надежности (с фрагментами кода).
- Перечисли скрытые методы скама, используемые в коде (с фрагментами кода).
Совет: Визуальное представление данных часто дает более четкое понимание работы системы. При работе с ChatGPT рекомендуется запрашивать визуализацию выходных данных, например, модификации состояний в виде диаграмм символов ASCII. Хотя не все визуализации могут иметь смысл, некоторые из них могут дать очень ценное представление о работе смарт-контракта.
По сути, хотя ChatGPT не может заменить человека-аудитора, он существенно дополняет процесс аудита, обеспечивая более четкое понимание переходов между состояниями протокола, ограничений, инвариантов и совместимости. Этот инструмент особенно эффективен для понимания переходов состояния протокола и ограничений.
Совет: Перед началом аудита предоставление чату документации по проверяемому протоколу может значительно повысить точность и релевантность ответов. Достаточно просто упомянуть: "Это документация, обеспечивающая лучший контекст для «название_протокола», который я проверяю", - и вставить документ.
Можно сказать, что ChatGPT является мощным помощником для аудиторов, обеспечивая структурированный и глубокий подход к аудиту смарт-контрактов. Однако, стоит учитывать, что ChatGTP (и ему подобные сервисы) являются лишь сложными интерпретациями машинного анализа, работающего с вероятностями, поэтому часто выдает ошибки и неточности. Соответственно, полностью полагаться на результат ChatGPT нельзя - это лишь хороший инструмент в правильных руках и "отправная точка" в исследовании смарт-контракта.
Поэтому, чтобы обезопасить себя от возможных рисков необходимо более тщательно изучать смарт-контракты на предмет возможных уязвимостей и мошеннических схем.
Как провести углубленный аудит смарт-контракта? ТОП-100 запросов к ChatGPT
Выше мы рассмотрели общий запрос (prompt) к ChatGPT, с которого можно начать анализ смарт-контракта. Но, разумеется, подробный анализ не ограничивается вводным запросом.
Мошенники постоянно совершенствуют свою тактику, поэтому необходимо быть информированным и проявлять осторожность во многих аспектах - это важнейшие стратегии защиты ваших инвестиций в токены.
Давайте рассмотрим список ТОП-100 запросов, которые позволят вам профессионально подойти к аудиту смарт-контракта:
- Успешно ли компилируется код?
- Какая версия Solidity используется в коде? Это актуальная стабильная версия?
- Присутствуют ли понятные комментарии, объясняющие назначение функций и переменных?
- Используется ли в контракте схема "Ownable"? Если да, то для каких функций?
- Корректно ли распределены переменные состояния (state variables) с помощью модификаторов видимости?
- Используются ли события (events) для правильного логирования?
- Предоставляются ли удобные для пользователя сообщения об ошибках?
- Проверяется ли возвращаемое значение низкоуровневых вызовов (low-level calls)?
- Существуют ли сценарии, в которых владелец может авторизовать себя, что может привести к rug-pulling?
- Кто имеет контроль над привилегированными учетными записями и каковы механизмы контроля?
- Какие механизмы управления (governance mechanisms) существуют в контракте, и является ли управление полностью открытым или ограниченным?
- Используются ли в системе другие контракты и какие роли они выполняют (например, proxy-контракт)?
- Существует ли механизм блокировки по времени, и можно ли его обойти?
- Существует ли адекватная документация?
- Существуют ли в коде потенциальные уязвимости к атакам DoS или реентерабельности (reentrancy)?
- Все функции являются внутренними (internal), за исключением тех, которые явно должны быть общедоступными/внешними (public/external)?
- В математических операциях нет арифметических переполнений/недополнений (overflows/underflows)?
- Используется ли безопасная библиотека OpenZeppelin?
- Эфир или токены не могут быть случайно отправлены нуль-адресу (0x0)?
- Условия проверяются с помощью require перед операциями и изменением состояния?
- Состояние (state) устанавливается до и во время выполнения действий?
- Используется ли защита от атак повторного входа (reentry) (A вызывает B вызывает A)?
- Правильно ли реализован интерфейс ERC20?
- Используется ли модификатор в нескольких местах только, если это действительно необходимо?
- Все типы задаются явно (например, используется uint256 вместо uint)?
- Все методы и циклы находятся в пределах максимально допустимого лимита газа?
- В конструкторе отсутствуют лишние инициализации (помните, что значения по умолчанию заданы)?
- Имеется полное покрытие тестами: тестируется каждый метод смарт-контракта и все возможные типы входных данных?
- Проведено fuzz-тестирование с использованием случайных входов?
- Протестированы ли все возможные состояния, в которых может находиться контракт?
- Суммы эфира и токенов по умолчанию указываются в единицах wei?
- Блок/время окончания краудсейла (crowdsale) наступает после блока/времени начала (start / enable trading)?
- Курс обмена/конвертации токенов краудсейла установлен корректно?
- Установлен ли мягкий/жесткий лимит краудсейла?
- Минимальный/максимальный допустимый вклад в краудсейл установлен и протестирован?
- Функциональность белых списков краудсейла протестирована?
- Проверена логика возврата средств с краудсейла?
- Участники краудсейла получают пропорциональное количество токенов или могут заявить о своем вкладе?
- Правильно ли настроена продолжительность каждого этапа краудсейла (например, предпродажа, публичная продажа)?
- Указано ли, какие функции должны контролироваться только владельцем (например, приостановка краудсейла, переход на другую стадию краудсейла, включение распределения токенов и т. д.)?
- Логика наделения краудсейла правами (vesting) проверена?
- Краудсейл имеет режим отказоустойчивости, который при включении владельцем ограничивает вызовы функции и включает функцию возврата средств?
- В краудсейле предусмотрена функция отката, если она имеет разумный смысл.
- Импортируемые библиотеки были предварительно проверены и не содержат нежелательных частей, которые могут быть заменены в будущих версиях и могут быть использованы для вредоносных целей?
- Методы передачи токенов (transfer) обернуты в require?
- Корректно ли используются require и assert? Метод assert используется только для того, что никогда не должно происходить, обычно он используется для проверки состояния после внесения изменений.
- Существует ли защита от атак рекурсивных вызовов (recursive call)?
- Ограничиваются ли длины произвольных строк на входе?
- По возможности избегается использование массивов (array) и вместо них маппинги (mappings)?
- Не используются ли хэши блоков для работы со случайными величинами (майнеры могут влиять на это)?
- Нигде не использует tx.origin?
- Элементы массива сдвигаются вниз при удалении элемента, чтобы не оставлять пробелов?
- Используется ли revert вместо throw?
- Функции немедленно завершаются, если условия не выполняются?
- Устранены ли предупреждения (warnings) компилятора?
- Используется ли библиотека SafeMath при вычислениях?
- Считываются ли какие-либо слоты памяти (storage slots) несколько раз?
- Используются ли какие-либо неограниченные циклы/массивы, которые могут вызвать DoS?
- Используется ли block.timestamp только для длинных интервалов?
- Не используется block.number для расчета прошедшего времени?
- Избегается ли вызов delegatecall, особенно для внешних (пусть даже и доверенных) контрактов?
- Не обновляется ли длина массива во время итерации по нему?
- Защищены ли подписи от повторного воспроизведения с помощью nonce и block.chainid?
- Убедитесь, что все ли подписи используют EIP-712?
- Вывод abi.encodePacked() не должен хэшироваться, если используется более 2 динамических типов. В общем случае предпочтительнее использовать abi.encode().
- Внимательно проверяйте assembly-вставки кода.
- Избегайте недостаточного расхода газа (gas griefing).
- Являются ли все приватные данные действительно приватными?
- Обновление структуры/массива в памяти (memory) не изменит его в хранилище (stage)?
- Затеняются (overshadow) ли переменные состояния (stage variables)?
- Вычисление значения переменно на лету дешевле, чем его хранение?
- Все ли переменные состояния считываются из правильного контракта (мастер против клона)?
- Правильно ли используются операторы сравнения (>, <, >=, <=), особенно для предотвращения ошибок off-by-one?
- Правильно ли используются логические операторы (==, !=, &&, ||, !), особенно для предотвращения ошибок off-by-one?
- Всегда ли умножение выполняется перед делением (если только умножение не может переполниться)?
- Заменяются ли магические числа (magic numbers) константой с интуитивно понятным именем?
- Если у получателя ETH есть обратная (fallback ) функция, которая может быть отменена (reverted), то может ли это привести к DoS?
- Используется ли стандарт SafeERC20 и проверяются ли возвращаемые значения безопасным способом?
- Предполагается ли, что отправитель msg.sender всегда является релевантным пользователем?
- Не используется ли tx.origin для авторизации?
- Не используется ли address.transfer() или address.send() вместо .call.value()?
- При использовании низкоуровневых вызовов (low-level calls) убедитесь, что контракт существует до вызова.
- Используется ли assembly-код для доступа к chainid или коду/размеру/хэшу контракта вместо синтаксиса Solidity?
- Используется ли ключевое слово delete при установке переменной в нулевое значение (0, false, "" и т. д.)?
- Выражения, передаваемые логическим операторам/сравнениям (&&/||/>=/==/etc), не должны иметь побочных эффектов.
- При работе с несколькими адресами спросите себя, что произойдет, если они будут одинаковыми?
- Насколько хорошо документирован код? Приводятся ли комментарии и примеры везде, где используется нестандартный код?
- Если используется External Call, убедитесь действительно ли необходим вызов внешнего контракта?
- Проверяется ли результат External Call и обрабатываются ли ошибки?
- Что произойдет, если при External Call будет использован весь предоставленный газ?
- Если External Call вызывает определенную функцию, убедитесь, что функция реально существует (фантомные функции).
- Убедитесь, что в модификаторах (modifiers) не используются внешние вызовы (external calls)
- Выдаются ли события (event) для каждой функции, изменяющей хранилище (storage)?
- Проверьте свои предположения о том, что делают и возвращают внешние контракты, используемые в основном.
- Следите за токенами, в которых используется слишком много или слишком мало десятичных дробей. Убедитесь, что максимальное и минимальное поддерживаемые значения документированы.
- Документированы ли полномочия, связанные с ролями?
- Каковы риски при нарушении прав доступа и как это может повлиять на различные компоненты системы?
- Может ли владелец манипулировать токенами и ETH в рамках контракта?
- Как устанавливается адрес оракула (Oracle) и какой процесс за этим стоит? Существуют ли запасные оракулы для подстраховки?
- Как в других проектах реализованы аналогичные функции, учитывались ли лучшие практики?
Этот чек-лист поможет вам обеспечить проведение тщательного аудита безопасности смарт-контрактов Solidity. Он охватывают широкий спектр критических аспектов для выявления и смягчения потенциальных уязвимостей и рисков в коде и связанных с ним системах.
Надеемся, что эти примеры помогли Вам лучше разобраться с методикой аудита смарт-контрактов.
Поскольку вся информация в блокчейне открыта (конечно, при условии верифицированного исходного кода контракта), то вооружившись этими знаниями Вы можете самостоятельно изучать смарт-контракты и выявлять различные схемы скама.
Однако, мы все уже сделали за Вас! Подключайте премиум подписку и откройте для себя доступ к эксклюзивным фильтрам по функциям смарт-контрактов и свежую аналитику. Повысьте шансы на успешные инвестиции в прибыльные токены.
С уважением, команда Lotus Market.
All posts