Аналіз смарт-контрактів
29.01.2024

Самостійний аудит смарт-контрактів за допомогою ChatGPT

Під час проведення аудиту смарт-контрактів необхідно охопити широкий спектр питань, щоб упевнитися в безпеці коду. Ці питання охоплюють різні аспекти, зокрема контроль доступу, управління активами, управління даними, допущення, залежності та контрольні списки безпеки. Нижче ми наводимо детальний чек-лист та інструкцію щодо запитів до ChatGPT, які допоможуть вам у процесі аудиту смарт-контракту.

Якщо ви хочете самостійно вивчити смарт-контракт на предмет вразливостей і прихованих методів скаму, то першим кроком буде коректно складений запит (prompt) у ChatGPT.

Корисним запитом для ChatGPT буде така команда:

Надай вичерпний список усіх проблем і вразливостей у наступному смарт-контракті. Детально опиши проблеми та можливі уразливості. Наведи по одному сценарію використання кожної уразливості. Висновок зроби у вигляді коректної таблиці у форматі markdown зі списком об'єктів, кожен з яких має стовпці 'description', 'action', 'severity', 'actors', 'scenario', 'type' і 'line'. 'type' де може бути 'usability', 'vulnerability', 'optimization' або 'suggestion'. 'actors' - це список задіяних суб'єктів. 'серйозність' може бути "низька", "середня" або "висока". 'рядок' - це номер рядка проблеми. Переконайтеся, що всі поля таблиці заповнені.

Далі використовуйте такі запитання, щоб більш глибоко вивчити смарт-контракт.

Сценарії використання:

  1. Хто є дійовими особами системи?

  2. Якими діями володіє система?

  3. Які обмеження існують у системі?

  4. Які існують потенційні способи зламати систему?

  5. Який захист використовується для протидії атакам?

  6. Опиши, виходячи з обмежень, зміни стану кожної функції.

  7. Надай інформацію про використовувані шаблони Solidity і DeFi.

  8. Напиши позитивні та негативні аксіоми, ґрунтуючись на інформації про систему.

  9. Перелічи способи оптимізації та зміни коду для підвищення його надійності (із фрагментами коду).

  10. Перерахуй приховані методи скаму, що використовуються в коді (з фрагментами коду).

Порада: Візуальне представлення даних часто дає чіткіше розуміння роботи системи. Під час роботи з ChatGPT рекомендується запитувати візуалізацію вихідних даних, наприклад, модифікації станів у вигляді діаграм символів ASCII. Хоча не всі візуалізації можуть мати сенс, деякі з них можуть дати дуже цінне уявлення про роботу смарт-контракту.

По суті, хоча ChatGPT не може замінити людину-аудитора, він істотно доповнює процес аудиту, забезпечуючи більш чітке розуміння переходів між станами протоколу, обмежень, інваріантів і сумісності. Цей інструмент особливо ефективний для розуміння переходів стану протоколу та обмежень.

Порада: Перед початком аудиту надання чату документації щодо протоколу, що перевіряється, може значно підвищити точність і релевантність відповідей. Досить просто згадати: "Це документація, що забезпечує найкращий контекст для "назва_протоколу", який я перевіряю", - і вставити документ.

Можна сказати, що ChatGPT є потужним помічником для аудиторів, забезпечуючи структурований і глибокий підхід до аудиту смарт-контрактів. Однак, варто враховувати, що ChatGTP (і йому подібні сервіси) є лише складними інтерпретаціями машинного аналізу, що працює з імовірностями, тому часто видає помилки та неточності. Відповідно, повністю покладатися на результат ChatGPT не можна - це лише хороший інструмент у правильних руках і "відправна точка" в дослідженні смарт-контракту.

Тому, щоб убезпечити себе від можливих ризиків, необхідно більш ретельніше вивчати смарт-контракти на предмет можливих вразливостей і шахрайських схем.

common tips

Як провести поглиблений аудит смарт-контракту? ТОП-100 запитів до ChatGPT

Вище ми розглянули загальний запит (prompt) до ChatGPT, з якого можна почати аналіз смарт-контракту. Але, зрозуміло, детальний аналіз не обмежується вступним запитом.

Шахраї постійно вдосконалюють свою тактику, тому необхідно бути поінформованим і проявляти обережність у багатьох аспектах - це найважливіші стратегії захисту ваших інвестицій у токени.

Давайте розглянемо список ТОП-100 запитів, які дадуть вам змогу професійно підійти до аудиту смарт-контракту:

  1. Чи успішно компілюється код?
  2. Яка версія Solidity використовується в коді? Це актуальна стабільна версія?
  3. Чи присутні зрозумілі коментарі, що пояснюють призначення функцій і змінних?
  4. Чи використовується в контракті схема "Ownable"? Якщо так, то для яких функцій?
  5. Чи коректно розподілено змінні стану (state variables) за допомогою за допомогою модифікаторів видимості?
  6. Чи використовуються події (events) для правильного логування?
  7. Чи надаються зручні для користувача повідомлення про помилки?
  8. Чи перевіряється повернуте значення низькорівневих викликів (low-level calls)?
  9. Чи існують сценарії, в яких власник може авторизувати себе, що може призвести до rug-pulling?
  10. Хто має контроль над привілейованими обліковими записами та які є механізми контролю?
  11. Які механізми управління (governance mechanisms) існують у контракті, і чи є управління повністю відкритим або обмеженим?
  12. Чи використовуються в системі інші контракти і які ролі вони виконують (наприклад, proxy-контракт)?
  13. Чи існує механізм блокування за часом, і чи можна його обійти?
  14. Чи існує адекватна документація?
  15. Чи існують у коді потенційні вразливості до атак DoS або реентерабельності (reentrancy)?
  16. Усі функції є внутрішніми (internal), за винятком тих, які явно мають бути загальнодоступними/зовнішніми (public/external)?
  17. У математичних операціях немає арифметичних переповнень/недоповнень (overflows/underflows)?
  18. Чи використовується безпечна бібліотека OpenZeppelin?
  19. Ефір або токени не можуть бути випадково надіслані нуль-адресою (0x0)?
  20. Умови перевіряються за допомогою require перед операціями та зміною стану?
  21. Стан (state) встановлюється до і під час виконання дій?
  22. Чи використовується захист від атак повторного входу (reentry) (A викликає B викликає A)?
  23. Чи правильно реалізовано інтерфейс ERC20?
  24. Чи використовується модифікатор у кількох місцях тільки, якщо це дійсно необхідно?
  25. Усі типи задаються явно (наприклад, використовується uint256 замість uint)?
  26. Усі методи та цикли перебувають у межах максимально допустимого ліміту газу?
  27. У конструкторі відсутні зайві ініціалізації (пам'ятаєте, що значення за замовчуванням задані)?
  28. Наявне повне покриття тестами: тестується кожен метод смарт-контракту і всі можливі типи вхідних даних?
  29. Проведено fuzz-тестування з використанням випадкових входів?
  30. Чи протестовано всі можливі стани, у яких може перебувати контракт?
  31. Суми ефіру і токенів за замовчуванням вказуються в одиницях wei?
  32. Блок/час закінчення краудсейлу (crowdsale) настає після блоку/часу початку (start / enable trading)?
  33. Курс обміну/конвертації токенів краудсейлу встановлено коректно?
  34. Чи встановлено м'який/жорсткий ліміт краудсейлу?
  35. Мінімальний/максимальний допустимий внесок у краудсейл встановлений і протестований?
  36. Функціональність білих списків краудсейлу протестована?
  37. Перевірена логіка повернення коштів із краудсейлу?
  38. Учасники краудсейлу отримують пропорційну кількість токенів чи можуть заявити про свій внесок?
  39. Чи правильно налаштована тривалість кожного етапу краудсейлу (наприклад, передпродаж, публічний продаж)?
  40. Чи вказано, які функції мають контролюватися тільки власником (наприклад, припинення краудсейлу, перехід на іншу стадію краудсейлу, включення розподілу токенів краудсейлу, включення розподілу токенів тощо)?
  41. Логіка наділення краудсейла правами (vesting) перевірена?
  42. Краудсейл має режим відмовостійкості, який у разі ввімкнення власником обмежує виклики функції та вмикає функцію повернення коштів?
  43. У краудсейлі передбачена функція відкату, якщо вона має розумний сенс.
  44. Імпортовані бібліотеки було попередньо перевірено, вони не містять небажаних частин, які можуть бути замінені в майбутніх версіях і можуть бути використані для шкідливих цілей?
  45. Методи передачі токенів (transfer) обгорнуті в require?
  46. Чи коректно використовуються require і assert? Метод assert використовується тільки для того, що ніколи не повинно відбуватися, зазвичай він використовується для перевірки стану після внесення змін.
  47. Чи існує захист від атак рекурсивних викликів (recursive call)?
  48. Чи обмежуються довжини довільних рядків на вході?
  49. По можливості уникається використання масивів (array) і замість них маппінги (mappings)?
  50. Чи не використовуються хеші блоків для роботи з випадковими величинами (майнери можуть впливати на це)?
  51. Ніде не використовує tx.origin?
  52. Елементи масиву зсуваються вниз під час видалення елемента, щоб не залишати пропусків?
  53. Чи використовується revert замість throw?
  54. Функції негайно завершуються, якщо умови не виконуються?
  55. Чи усунуто попередження (warnings) компілятора?
  56. Чи використовується бібліотека SafeMath під час обчислень?
  57. Чи зчитуються якісь слоти пам'яті (storage slots) кілька разів?
  58. Чи використовуються якісь необмежені цикли/масиви, які можуть викликати DoS?
  59. Чи використовується block.timestamp тільки для довгих інтервалів?
  60. Чи не використовується block.number для розрахунку минулого часу?
  61. Чи уникається виклик delegatecall, особливо для зовнішніх (нехай навіть і довірених) контрактів?
  62. Чи не оновлюється довжина масиву під час ітерації по ньому?
  63. Чи захищені підписи від повторного відтворення за допомогою nonce і block.chainid?
  64. Переконайтеся, що всі підписи використовують EIP-712?
  65. Висновок abi.encodePacked() не повинен хешуватися, якщо використовується більше 2 динамічних типів. У загальному випадку краще використовувати abi.encode().
  66. Уважно перевіряйте assembly-вставки коду.
  67. Уникайте недостатньої витрати газу (gas griefing).
  68. Чи є всі приватні дані дійсно приватними?
  69. Оновлення структури/масиву в пам'яті (memory) не змінить його в сховищі (stage)?
  70. Чи затінюються (overshadow) змінні стану (stage variables)?
  71. Обчислення значення змінної на льоту дешевше, ніж його зберігання?
  72. Чи всі змінні стану зчитуються з правильного контракту (майстер проти клона)?
  73. Чи правильно використовуються оператори порівняння (>, <, >=, <=), особливо для запобігання помилок off-by-one?
  74. Чи правильно використовуються логічні оператори (==, !=, &&, ||, !), особливо для запобігання помилок off-by-one?
  75. Чи завжди множення виконується перед діленням (якщо тільки множення не може переповнитися)?
  76. Чи замінюються магічні числа (magic numbers) константою з інтуїтивно зрозумілим ім'ям?
  77. Якщо в одержувача ETH є зворотна (fallback) функція, яка може бути бути скасована (reverted), то чи може це призвести до DoS?
  78. Чи використовується стандарт SafeERC20 і чи перевіряються значення, що повертаються значення безпечним способом?
  79. Чи передбачається, що відправник msg.sender завжди є релевантним користувачем?
  80. Чи не використовується tx.origin для авторизації?
  81. Чи не використовується address.transfer() або address.send() замість .call.value()?
  82. При використанні низькорівневих викликів (low-level calls) переконайтеся, що контракт існує до виклику.
  83. Чи використовується assembly-код для доступу до chainid або коду/розміру/хешу контракту замість синтаксису Solidity?
  84. Чи використовується ключове слово delete під час встановлення змінної в нульове значення (0, false, "" тощо)?
  85. Вирази, що передаються логічним операторам/порівнянням (&&/||/>=/==/etc), не повинні мати побічних ефектів.
  86. Під час роботи з кількома адресами запитайте себе, що станеться, якщо вони будуть однаковими?
  87. Наскільки добре документований код? Чи наводяться коментарі та приклади скрізь, де використовується нестандартний код?
  88. Якщо використовується External Call, переконайтеся, чи дійсно необхідний виклик зовнішнього контракту?
  89. Чи перевіряється результат External Call і чи обробляються помилки?
  90. Що станеться, якщо під час External Call буде використано весь наданий газ?
  91. Якщо External Call викликає певну функцію, переконайтеся, що функція реально існує (фантомні функції).
  92. Переконайтеся, що в модифікаторах (modifiers) не використовуються зовнішні виклики (external calls)
  93. Чи видаються події (event) для кожної функції, що змінює сховище (storage)?
  94. Перевірте свої припущення про те, що роблять і повертають зовнішні контракти, які використовуються в основному.
  95. Слідкуйте за токенами, в яких використовується занадто багато або занадто мало десяткових дробів. Переконайтеся, що максимальне і мінімальне підтримувані значення документовані.
  96. Чи документовані повноваження, пов'язані з ролями?
  97. Які ризики при порушенні прав доступу і як це може вплинути на різні компоненти системи?
  98. Чи може власник маніпулювати токенами і ETH у рамках контракту?
  99. Як встановлюється адреса оракула (Oracle) і який процес за цим стоїть? Чи існують запасні оракули для підстраховки?
  100. Як в інших проєктах реалізовано аналогічні функції, чи враховувалися найкращі практики?

common tips

Цей чек-лист допоможе вам забезпечити проведення ретельного аудиту безпеки смарт-контрактів Solidity. Він охоплює широкий спектр критичних аспектів для виявлення та пом'якшення потенційних вразливостей і ризиків у коді та пов'язаних із ним системах.

 

Сподіваємося, що ці приклади допомогли Вам краще розібратися з методикою аудиту смарт-контрактів.

 

Оскільки вся інформація в блокчейні відкрита (звісно, за умови верифікованого вихідного коду контракту), то озброївшись цими знаннями Ви можете самостійно вивчати смарт-контракти і виявляти різні схеми скаму.

Однак, ми все вже зробили за Вас! Підключайте преміум підписку та відкрийте для себе доступ до ексклюзивних фільтрів за функціями смарт-контрактів та свіжу аналітику. Підвищіть шанси на успішні інвестиції в прибуткові токени.

З повагою, команда Lotus Market.

All posts

Connect to a wallet

Metamask