Ф'ючерси
Сотні безстрокових контрактів
TradFi
Золото
Одна платформа для світових активів
Опціони
Hot
Торгівля ванільними опціонами європейського зразка
Єдиний рахунок
Максимізуйте ефективність вашого капіталу
Демо торгівля
Вступ до ф'ючерсної торгівлі
Підготуйтеся до ф’ючерсної торгівлі
Ф'ючерсні події
Заробляйте, беручи участь в подіях
Демо торгівля
Використовуйте віртуальні кошти для безризикової торгівлі
Запуск
CandyDrop
Збирайте цукерки, щоб заробити аірдропи
Launchpool
Швидкий стейкінг, заробляйте нові токени
HODLer Airdrop
Утримуйте GT і отримуйте масові аірдропи безкоштовно
Launchpad
Будьте першими в наступному великому проекту токенів
Alpha Поінти
Ончейн-торгівля та аірдропи
Ф'ючерсні бали
Заробляйте фʼючерсні бали та отримуйте аірдроп-винагороди
Інвестиції
Simple Earn
Заробляйте відсотки за допомогою неактивних токенів
Автоінвестування
Автоматичне інвестування на регулярній основі
Подвійні інвестиції
Прибуток від волатильності ринку
Soft Staking
Earn rewards with flexible staking
Криптопозика
0 Fees
Заставте одну криптовалюту, щоб позичити іншу
Центр кредитування
Єдиний центр кредитування
Центр багатства VIP
Преміальні плани зростання капіталу
Управління приватним капіталом
Розподіл преміальних активів
Квантовий фонд
Квантові стратегії найвищого рівня
Стейкінг
Стейкайте криптовалюту, щоб заробляти на продуктах PoS
Розумне кредитне плече
New
Кредитне плече без ліквідації
Випуск GUSD
Мінтинг GUSD для прибутку RWA
Вразливість Reentrancy: Як Виявити, Використати та Запобігти
У світі смарт-контрактів, reentrancy вважається однією з найнебезпечніших вразливостей. Ця стаття допоможе вам не лише зрозуміти, що таке атака reentrancy, а й ефективно захиститися від неї. Від базових технік до просунутих рішень — ми дослідимо способи захисту всього вашого проекту.
Як працює Reentrancy: Механізм базової атаки
Щоб зрозуміти reentrancy, спершу потрібно засвоїти основну концепцію: смарт-контракт може викликати інший контракт, і тоді другий контракт може викликати назад перший, поки він ще виконується.
Уявіть, у вас є два контракти: ContractA з 10 Ether і ContractB, який надіслав туди 1 Ether. Коли ContractB викликає функцію зняття, він перевіряє баланс. Якщо достатньо — Ether повертається назад у ContractB. Тут, без належних заходів захисту, саме цей момент стає вразливим для зловмисника.
У типовій атаці reentrancy зловмисник використовує дві функції: attack() для запуску атаки і fallback() — для повторних викликів. Функція fallback — особлива у Solidity: вона не має імені, параметрів і викликається автоматично, коли на контракт надходить Ether без додаткових даних.
Послідовність атаки reentrancy
Розглянемо процес по кроках. Зловмисник викликає attack() у своєму контракті. В цій функції він викликає withdraw() з ContractA.
Коли ContractA отримує цей виклик, він перевіряє баланс ContractB. Оскільки там 1 Ether, перевірка проходить. Тоді ContractA відправляє 1 Ether назад у ContractB, активуючи його fallback(). На цей момент ContractA має 9 Ether, але баланс ContractB у реєстрі ще не оновлений до 0.
Це — вразливий момент: fallback() знову викликає withdraw() з ContractA. Перевірка балансу показує, що там ще 1 Ether! Чому? Тому що рядок balance[msg.sender] = 0 ще не виконався — він йде після відправки Ether.
Цикл повторюється: виклик withdraw() — перевірка балансу — відправка Ether — fallback() — виклик withdraw() знову і так далі, доки всі кошти ContractA не будуть виведені.
Аналіз коду: коли reentrancy стає реальністю
Контракт EtherStore — класичний приклад уразливого контракту. Він має deposit() для внесення балансу і withdrawAll() для зняття всіх коштів. Проблема у тому, що withdrawAll() спочатку перевіряє умови, потім відправляє Ether, і лише потім оновлює баланс.
Зловмисник створює Attack, передаючи адресу EtherStore у конструктор. Його fallback() викликає повторно withdrawAll() щоразу, коли Ether надходить. attack() починає з першого внеску — 1 Ether — щоб пройти початкову перевірку.
В результаті, весь фонд EtherStore знімається за один транзакцій.
Три стратегії захисту від reentrancy
Щоб захистити смарт-контракти, існує три рівні протидії — від простого до комплексного.
Модель noReentrant: базове рішення
Найпростіший спосіб — використання модифікатора noReentrant(). Це особливий тип функції в Solidity, який дозволяє змінювати поведінку інших функцій без їх переписування.
Ідея: коли функція захищена noReentrant(), вона блокує контракт під час виконання. Будь-який повторний виклик цієї функції буде провалений через стан блокування. Після завершення функції і зняття блокування — інші виклики знову можливі.
Це ефективно для захисту однієї функції, але не підходить для складних сценаріїв.
Модель Check-Effect-Interaction: запобігання багатофункціональним reentrancy
Другий, більш потужний метод — застосування шаблону Check-Effect-Interaction. Замість захисту однієї функції, цей підхід змінює логіку її написання.
Принцип: спочатку перевіряємо умови (Check), одразу оновлюємо стан (Effect), і лише потім взаємодіємо з зовнішніми контрактами (Interaction). Це унеможливлює повторний виклик, бо баланс вже оновлений до 0.
Замість оновлення balance[msg.sender] = 0 після відправки Ether, його потрібно зробити перед цим. Тоді, навіть якщо fallback() викликає знову, перевірка балансів не пройде — вони вже оновлені.
Цей підхід захищає контракт від reentrancy у всіх функціях зняття.
GlobalReentrancyGuard: комплексний захист у масштабі проекту
Для великих проектів з багатьма контрактами потрібен більш глобальний підхід — GlobalReentrancyGuard. Це контракт, що зберігає глобальний стан блокування і всі інші контракти в проекті посилаються до нього.
Уявіть сценарій: зловмисник викликає функцію ScheduledTransfer, яка проходить перевірки і надсилає Ether. Потім AttackTransfer викликає fallback() і намагається повторно викликати ScheduledTransfer. Але через глобальний замок, цей виклик блокується.
Такий підхід особливо корисний для великих систем, де reentrancy може виникнути між різними контрактами.
Вибір відповідної техніки для вашого проекту
Вибір залежить від складності вашого проекту. Якщо у вас мало функцій взаємодії — достатньо noReentrant(). Якщо багато функцій зняття — застосовуйте Check-Effect-Interaction. Для масштабних систем з багатьма контрактами — GlobalReentrancyGuard.
Головне — розуміти, як працює reentrancy, щоб вміти його виявляти і запобігати заздалегідь.
Щоб щодня бути в курсі безпеки смарт-контрактів, слідкуйте за джерелами з актуальними кодами та новинами у сфері Web3 і Solidity безпеки.