Как провести аудит смарт-контракта: Глубокое погружение в процесс работы компании Hacken
В развивающуюся эпоху Web3 невозможно переоценить решающую роль смарт-контрактов в обеспечении работы децентрализованных приложений и экосистем. По мере роста сложности и масштаба этих систем риск ошибок возрастает многократно. Для разработчиков Web3, стремящихся к бесперебойной и безошибочной работе, аудит смарт-контрактов - не просто вариант, а необходимость.
В этой статье мы расскажем вам о проверенном процессе аудита в компании Hacken - методике, которую мы постоянно совершенствовали с момента проведения первого аудита в 2017 году. Примечательно, что благодаря этому подходу нам удалось добиться нулевого количества эксплойтов среди всех проектов, которые мы проверяли в 2022 году, что подтверждает надежность и эффективность наших методов.
Подготовка к аудиту смарт-контрактов.
Невозможно переоценить значение тщательной подготовки и тщательного документирования. Это способствует ясности, экономии ресурсов и повышению эффективности всего процесса.
Чтобы получить максимальную отдачу от аудита, необходимо выполнить следующие шаги:
- Четко сформулировать функциональные требования к проекту.
- Подготовить подробное техническое описание проекта.
- Создать среду разработки для проекта.
- Разработать комплексные модульные тесты.
- Убедиться, что код соответствует лучшим практикам и стандартам безопасности.
Соблюдение этих критериев позволит нам провести глубокую экспертизу проекта и точно оценить код на соответствие спецификациям. Этот уровень подготовки необходим даже в том случае, если вы не планируете проводить внешний аудит.
Пункт 1: Функциональные требования
Функциональные требования служат для аудиторов "дорожной картой", позволяющей понять конкретные цели проекта. Они должны быть четкими, лаконичными и лишенными двусмысленности.
❌ Двусмысленное требование: Пользователи должны иметь возможность зарабатывать токены.
✅ Конкретное требование: Контракт должен позволять пользователям делать ставки токенами ABC и зарабатывать токены XYZ в качестве вознаграждения.
Предоставление как можно большего количества функциональных деталей может помочь аудиторам убедиться в том, что код работает так, как задумано.
Приведем еще несколько примеров хорошо сформулированных функциональных требований:
Контракт должен позволять пользователям делать ставки токенами HAI и получать другие токены в качестве вознаграждения.
Общая сумма вознаграждения должна распределяться между всеми пользователями в соответствии с их процентной долей в общем объеме заблокированных HAI.
Пользователи должны иметь возможность снимать свои средства и вознаграждения в удобное для них время.
Общий заблокированный баланс должен пересчитываться каждый раз, когда пользователь выводит свои токены.
Хотя код смарт-контракта может быть безопасным, он может не соответствовать поставленным целям. Это еще одна причина, по которой полезно получить внешнее заключение, чтобы убедиться, что приложение функционирует так, как задумано.
Как аудиторы могут проверить функциональность и что-то гарантировать, если они не понимают, о чем идет речь в приложении? Именно так! Четкие и полные функциональные требования служат мерилом успеха. Только так можно получить реальную пользу от внешнего обзора.
Всестороннее техническое описание играет важную роль в подготовке к аудиту. Основное внимание следует уделить следующему:
- Используемые языки программирования и технологии.
- Инструкции по развертыванию.
- Инструкции по тестированию.
- Любые соответствующие нефункциональные требования.
Эта информация поможет нам ориентироваться в коде, особенно если ваши смарт-контракты сложны и взаимосвязаны. Еще раз отметим, что документирование важных аспектов кода полезно даже в том случае, если вы не планируете привлекать внешних специалистов
На этом важнейшем этапе аудита проявляются достоинства нашей уникальной методики.
До этого момента наши аудиторы проводили свои исследования независимо друг от друга, что позволило им непредвзято изучить и глубоко проанализировать код с их точки зрения.Теперь же они впервые собрались вместе и под руководством ведущего аудитора провели совместное обсуждение своих индивидуальных идей и открытий. Мы изучаем, обсуждаем и даже спорим о выявленных проблемах в открытом диалоге, что способствует более глубокому пониманию потенциальных уязвимостей вашего проекта.
Кроме того, команда составляет внутренний документ с указанием ключевых аспектов и возможных слабых мест проекта, а также подробный консультационный отчет с предложениями по усилению безопасности проекта и повышению его аудиторской оценки.
Ведущий аудитор тщательно проверяет все материалы на предмет их полноты, точности и достоверности выводов коллективного аудита. После окончательной проверки сводный отчет о результатах аудита передается Вам и служит надежной оценкой уровня безопасности Вашего проекта.
После интенсивного перекрестного анализа полученных результатов наша команда составляет подробный итоговый отчет, в котором отражены основные проблемы, уязвимости и выполненные тесты.
Резюме в отчете об аудите содержит краткое описание основных выводов и общую оценку. В разделе "Проверенные элементы" перечислены все проверенные элементы, в разделе "Выводы" подробно рассмотрены выявленные проблемы и рекомендации по их устранению. А в разделе "Отказ от ответственности" разъясняется область применения аудита.
По сути, отчет представляет собой всесторонний обзор аудита, позволяющий получить проверенную информацию для укрепления безопасности и надежности смарт-контракта.
Внешние пользователи. Заключительный отчет об аудите также является бесценным ресурсом для внешних заинтересованных сторон, таких как члены сообщества и инвесторы. Они изучают его, чтобы принять взвешенное решение при рассмотрении вопроса о размещении средств/инвестировании в ваш проект.
Оценка аудита. Мы также выставляем итоговую оценку по результатам аудита, основываясь на трех критериях:
Качество документации (D) - 1,0
Качество кода (C) - 2,0
Уровень безопасности (S) - 7,0
Эта оценка позволяет внешним и нетехническим пользователям получить представление о жизнеспособности вашего проекта.
В некоторых охранных компаниях может использоваться оптимизированный штат, когда все обязанности выполняют всего 1-2 сотрудника. Хотя это и позволяет сократить расходы на оплату труда, но чревато снижением качества и чрезмерной нагрузкой на этих нескольких сотрудников. В компании "Хакен" мы придерживаемся более целенаправленной стратегии, когда каждый специалист занимается отдельной ключевой задачей. Мы выступаем за специализацию ролей, поскольку это позволяет нам уделять больше времени решению текущих проблем.
Предварительный аудитор: Аудитор, назначенный на начальный этап, отвечающий за изучение требований к проекту, подтверждение его масштабов и развертывание автоматизированных инструментов.
Аудиторы: Основные аудиторы, которые проводят углубленную построчную проверку, устраняют все несоответствия и предоставляют все необходимые материалы ведущему аудитору.
Ведущий аудитор: Старший аудитор, который проверяет все материалы, подготовленные аудиторами, и следит за тем, чтобы не были упущены какие-либо проблемы безопасности.
Корректор: Сотрудник, которому поручено следить за тем, чтобы итоговый отчет не содержал ошибок и соответствовал установленной структуре.
Менеджер по доставке: Ответственный за поддержание прямой связи между нашими командами, следящий за тем, чтобы все замечания и предложения были учтены.
Безусловно, этот метод требует больших затрат человеческих ресурсов, но со временем мы убедились, что долгосрочные преимущества как для нас, так и для наших клиентов оправдывают себя.
На данный момент будет проведен аудит смарт контракта одного из Dapp, которое находится на стадии зарождения в тестовой сети Goerli. Считайте это подарком от меня и кто дочитает до этого момента вот ссылка на группу наших разработчиков из etherlock — https://t.me/+6qgEJ4Gz81ZmNmFh. На данный момент они пускают только инфлуенсеров, но так и так если вам интересно что будет в зк стучитесь!
Разберем смарт контракт нфт, которое они сделали. Cам код:
Давайте разберем поэтапно что мы тут видим. Начнем с поверхностного аудита:
- Сначала они импортируют несколько необходимых библиотек, таких как
Counters
из OpenZeppelin для работы с счетчиками,Ownable
для установки владельца контракта,SafeMath
для выполнения безопасных математических операций иERC721Enumerable
для создания неотъемлемого токена ERC721. - Затем контракт
Nft
наследуется отERC721Enumerable
иOwnable
, что означает, что он будет иметь функциональность стандарта ERC721 с возможностью перечисления токенов и будет иметь владельца, который может выполнять определенные действия. - Они определяют несколько константных переменных, таких как
MAX_SUPPLY
(максимальное количество NFT, которые можно создать),PRICE
(цена одного NFT в эфире) иMAX_PER_MINT
(максимальное количество NFT, которые можно купить за одну транзакцию). - Также у нас есть переменная
baseTokenURI
, которая представляет базовый URI для метаданных токенов. - Конструктор контракта принимает
baseURI
в качестве параметра и устанавливает его как базовый URI для метаданных токенов. - Мы имеем функцию
reserveNFTs
, которая может быть вызвана только владельцем контракта для резервирования 10 NFT. Она проверяет, есть ли еще достаточное количество NFT для резервирования, и затем вызывает приватную функцию_mintSingleNFT
, чтобы создать каждый NFT. - Функция
_baseURI
переопределяет виртуальную функцию из ERC721, возвращаяbaseTokenURI
. - Функция
setBaseURI
позволяет только владельцу контракта обновлятьbaseTokenURI
. - Функция
mintNFTs
используется для покупки NFT. Она принимает количество NFT, которые нужно создать, и проверяет доступность NFT, достаточно ли эфира для оплаты и не превышает ли запрашиваемое количество максимальное. Затем она вызывает_mintSingleNFT
для создания каждого NFT. - Приватная функция
_mintSingleNFT
создает новый токен NFT и увеличивает счетчик_tokenIds
.
Для поверхностного начала пока хватит. В принципе понятно, давайте разберем важные функции более бодробо и выведем критические моменты.
1) Начнем с того что не хватает проверки наличия NFT перед их резервированием. Это может привести к тому, что NFT будут зарезервированы, даже если их больше не осталось. Рекомендуется добавить проверку наличия NFT перед резервированием.
2) Нет проверки на максимальное количество NFT, которое можно купить за одну транзакцию. Это означает, что пользователи могут попытаться купить более, чем максимально допустимое количество NFT за один раз. Рекомендуется добавить проверку на максимальное количество NFT, которое можно купить за одну транзакцию.
3) Нет защиты от переполнения стека при попытке многократного вызова функции _mintSingleNFT(). Рекомендуется добавить защиту от переполнения стека при попытке многократного вызова функции _mintSingleNFT().
4) Добавить функцию для изменения максимального количества зарезервированных NFT.
5) Добавить функцию для изменения максимального общего количества создаваемых NFT.
6) Добавить функцию для изменения базового URI после создания контракта.
Далее осталось только написать грамотный отчет и добавить туда файл с unit тестами. Спасибо команде ETHERLOCK За предоставленный смарт контракт и помощт в написании поста. Если что ребята предоставили мне стартовый контракт, уверен что они исправили все что с ним связано! Как мы видим критическиз ошибок нет, кроме переполнения стека, так что переживать о безопасности Dapp не стоит. Еще важный момент мы удалили группу для общения, так как будем сотрудничать с ребятами из ETHERLOCK, поэтому в будущем будет отдельный форум. Спасибо за прочтение! До скорого!