Ф'ючерси
Сотні безстрокових контрактів
TradFi
Золото
Одна платформа для світових активів
Опціони
Hot
Торгівля ванільними опціонами європейського зразка
Єдиний рахунок
Максимізуйте ефективність вашого капіталу
Демо торгівля
Вступ до ф'ючерсної торгівлі
Підготуйтеся до ф’ючерсної торгівлі
Ф'ючерсні події
Заробляйте, беручи участь в подіях
Демо торгівля
Використовуйте віртуальні кошти для безризикової торгівлі
Запуск
CandyDrop
Збирайте цукерки, щоб заробити аірдропи
Launchpool
Швидкий стейкінг, заробляйте нові токени
HODLer Airdrop
Утримуйте GT і отримуйте масові аірдропи безкоштовно
Launchpad
Будьте першими в наступному великому проекту токенів
Alpha Поінти
Ончейн-торгівля та аірдропи
Ф'ючерсні бали
Заробляйте фʼючерсні бали та отримуйте аірдроп-винагороди
Інвестиції
Simple Earn
Заробляйте відсотки за допомогою неактивних токенів
Автоінвестування
Автоматичне інвестування на регулярній основі
Подвійні інвестиції
Прибуток від волатильності ринку
Soft Staking
Earn rewards with flexible staking
Криптопозика
0 Fees
Заставте одну криптовалюту, щоб позичити іншу
Центр кредитування
Єдиний центр кредитування
Центр багатства VIP
Преміальні плани зростання капіталу
Управління приватним капіталом
Розподіл преміальних активів
Квантовий фонд
Квантові стратегії найвищого рівня
Стейкінг
Стейкайте криптовалюту, щоб заробляти на продуктах PoS
Розумне кредитне плече
Кредитне плече без ліквідації
Випуск GUSD
Мінтинг GUSD для прибутку RWA
Детальне вивчення атаки Reentrancy та ефективних методів її запобігання
## Що таке атака Reentrancy?
Атака reentrancy — це одна з найпоширеніших уразливостей у смарт-контрактах. Вона виникає, коли функція контракту викликає зовнішній контракт до того, як завершити свій стан. Зловмисник може використати це для багаторазового виклику функції та розкрадання коштів.
## Класична атака Reentrancy
Це відбувається, коли:
1. Контракт A надсилає кошти контракту B
2. Контракт B виконує код (fallback функція)
3. Контракт B знову викликає контракт A перед завершенням першого виклику
4. Баланс контракту A ще не оновлений
## Ефективні методи захисту
### 1. Блокування Mutex (Перевірка стану)
```solidity
bool locked = false;
modifier noReentrancy() {
require(!locked);
locked = true;
_;
locked = false;
}
```
### 2. Перевірка-Ефект-Взаємодія (CEI)
```solidity
// Оновити стан перед зовнішнім викликом
balance[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
```
### 3. OpenZeppelin ReentrancyGuard
```solidity
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
function withdraw() public nonReentrant {
// Безпечний код
}
```
### 4. Pull замість Push
```solidity
// Замість відправлення коштів користувачу
// Дозвольте йому витягти їх
mapping(address => uint256) public balances;
function withdraw() public {
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
```
## Найкращі практики
- Завжди оновлюйте стан перед зовнішніми викликами
- Використовуйте перевірені бібліотеки, такі як OpenZeppelin
- Проводьте аудит безпеки смарт-контрактів
- Обмежуйте привілеї функцій
- Тестуйте сценарії атак
Розуміння та запобігання атакам reentrancy — критично важливо для розробників смарт-контрактів.
Атака повторного виклику (reentrancy) є однією з найсерйозніших загроз безпеці для смарт-контрактів. У цій статті ми розглянемо не лише принцип роботи reentrancy, а й комплексні методи захисту вашого проекту.
Щоб отримати повне уявлення, почнемо з базових понять, проаналізуємо код реальних атак і наостанок розглянемо три доведені техніки запобігання: від modifier nonReentrant() до GlobalReentrancyGuard() і шаблонів перевірки-ефекту-інтеракції.
Що таке атака типу reentrancy?
Уявімо два смарт-контракти, що взаємодіють. ContractA і ContractB можуть викликати один одного. Це здається нормальним, але саме так можна створити вразливість, яку зловмисник може використати.
Основна ідея reentrancy: смарт-контракт може викликати інший контракт, що ще виконується. Це може спричинити нескінченний цикл, якщо не контролювати його належним чином.
Наприклад, ContractA тримає 10 Ether, а ContractB вже надіслав туди 1 Ether. Зазвичай, при запиті на виведення, контракт перевіряє баланс (>0), відправляє Ether і оновлює баланс на 0. Але за допомогою reentrancy цей процес можна повторювати багато разів до оновлення балансу.
Як працює атака reentrancy
Зловмисник використовує два елементи: функцію attack() і fallback().
Функція fallback — це спеціальна функція в Solidity, яка виконується автоматично, якщо:
Послідовність атаки:
Крок 1: Зловмисник викликає attack(), яка в свою чергу викликає в ContractA функцію виведення.
Крок 2: ContractA перевіряє баланс ContractB, якщо >0, відправляє 1 Ether і активує fallback().
Крок 3: У цей момент баланс ще не оновлено — контракт все ще виконує функцію виведення.
Крок 4: Fallback викликає знову функцію виведення ContractA.
Крок 5: ContractA знову виконує перевірку — баланс ContractB ще 1 Ether, тому знову відправляє Ether і активує fallback().
Цей цикл повторюється, доки ContractA не витратить усі Ether. Саме тому reentrancy є такою небезпечною вразливістю.
Аналіз конкретного коду атаки
Розглянемо приклад з контрактом EtherStore, що має дві основні функції:
Функція withdrawAll() виконує: перевірка балансу (>0), відправка Ether і оновлення балансу на 0.
Вразливість у тому, що відправка Ether відбувається перед оновленням балансу, що дозволяє зловмиснику викликати повторно цю функцію.
Контракт Attack створений для експлуатації цієї вразливості:
Послідовність атаки:
Три техніки захисту від reentrancy
Техніка 1: Використання модифікатора nonReentrant
Простий спосіб — додати модифікатор nonReentrant до функції, яку потрібно захистити. Це блокуватиме повторні виклики під час виконання.
Як працює:
Недолік: захищає лише одну функцію, не запобігає атакам між різними функціями.
Техніка 2: Модель Check-Effect-Interaction
Більш просунутий підхід — змінити порядок виконання коду:
Приклад:
Техніка 3: GlobalReentrancyGuard
Для складних систем з кількома контрактами створюється глобальний захисник, що контролює reentrancy по всій системі.
Замість окремих змінних у кожному контракті, використовується один централізований захисник, що відслідковує стан системи і запобігає chain-reentrancy.
Приклад: якщо один контракт виконує перекази, а інший намагається викликати повторно функції, GlobalReentrancyGuard зупинить це.
Вибір відповідної техніки захисту
nonReentrant підходить, якщо:
Check-Effect-Interaction — для оптимізації і захисту всього проекту:
GlobalReentrancyGuard — для великих систем з кількома контрактами:
Комбінуйте ці методи залежно від потреб вашого проекту.
Висновок
Атака reentrancy — не неможлива для запобігання, якщо розуміти її механізм і застосовувати правильні техніки. Від простого модифікатора до глобального захисника — кожен інструмент має своє місце у системі безпеки смарт-контрактів.
Пам’ятайте: безпека — не опція, а обов’язок. Зрозумівши атаки reentrancy і застосувавши відповідні заходи, ви зможете створювати безпечні та ефективні смарт-контракти.
Для додаткової інформації про безпеку Web3, Solidity, аудит смарт-контрактів та інше слідкуйте за @TheBlockChainer у Twitter.