ГЛАВНАЯ / ИНСТРУКЦИИ / CROSS-FUNCTION REENTRANCY: КАК ПОВТОРНЫЙ ВХОД ЗАТРАГИВАЕТ ОБЩИЕ ИНВАРИАНТЫ
Cross-function reentrancy: как повторный вход затрагивает общие инварианты
При reentrancy атакующий контракт возвращается во время незавершённого внешнего вызова. Повторно он может вызвать не ту же функцию, а другой публичный метод, связанный с тем же балансом, лимитом или учётом залога. Поэтому анализировать нужно инвариант и весь набор entrypoint, а не только одну функцию вывода.
Внешний вызов может вернуть управление до завершения функции
Когда контракт вызывает другой контракт или отправляет ему Ether, выполнение внешнего адресата может начаться до того, как исходная функция закончит свою работу. Если адресат способен выполнить callback, он может повторно обратиться к публичной функции исходного контракта в том же общем сценарии транзакции.
При обычной reentrancy повторно вызывается исходный entrypoint. При cross-function варианте callback обращается к другой функции, которая использует те же balances, shares, collateral, limits или статус операции. Условие риска – не само наличие callback, а возможность воспользоваться промежуточным состоянием, пока инвариант ещё не восстановлен.
- callback запускается до завершения внешней функции
- повторный вход может выбрать другой entrypoint
- возможность callback подтверждена поведением вызываемого адреса
Рисуйте граф вызовов и отмечайте состояние до callback
Для каждой внешней операции выпишите вызывающий метод, целевой адрес и параметры передачи управления. Затем перечислите функции, доступные этому адресу при callback, и отмечайте чтение или запись общих переменных. Отдельно рассмотрите вложенную цепочку: вызываемый контракт может сам обратиться к третьему протоколу, который прочитает состояние исходного контракта.
Тест должен включать адрес-получатель с контролируемым callback и попытки входа во все связанные функции. Проверьте не только итоговый баланс, но и инварианты после каждого доступного шага. Один unit-тест прямого вызова функции не показывает, что происходит при возврате управления от внешнего кода.
Внешний вызов сам по себе не означает успешную атаку
Для эксплуатации должны совпасть доступный путь callback, промежуточное состояние, полезный эффект и условия допуска функции. Модификатор доступа, проверка статуса или уже обновлённое состояние могут закрыть путь. И наоборот, защита только одной функции может не закрыть повторный вход в соседний метод.
Не считайте view-функцию автоматически безвредной: её чтение может быть использовано другим контрактом в той же составной операции, если возвращаемое значение отражает промежуточное состояние. При этом конкретный путь и возможность получить выгоду нужно доказать trace и моделью протокола, а не одним названием класса уязвимости.
Частые вопросы
Cross-function reentrancy повторно вызывает ту же функцию?
Не обязательно. Callback может обратиться к другой функции, использующей связанное состояние.
Для reentrancy нужен перевод ETH?
Нет. Риск может возникнуть при других внешних вызовах и интеграционных callback, если управление возвращается к уязвимому состоянию.
Достаточно проверить одну функцию withdraw?
Нет. Нужно перечислить связанные entrypoint и общий инвариант.
Если функция помечена view, риска нет?
Её чтение может иметь значение для другой функции или контракта, если состояние временно несогласовано.
Внешний вызов всегда означает уязвимость?
Нет. Нужно показать достижимый callback и конкретное нарушение инварианта.
Чек-лист: cross-function reentrancy: как повторный вход затрагивает общие инварианты
- внешние вызовы перечислены;
- доступные callback entrypoint найдены;
- общие переменные и инварианты записаны;
- порядок чтения и записи проверен;
- вложенные контракты учтены;
- тесты проверяют разные entrypoint и состояние после callback;
- защита распространяется на связанную операцию.
Материал подготовлен редакцией сайта и проверен 2 ноября 2026 года. Условия бирж, кошельков и блокчейн-сетей могут меняться. Перед операцией сверяйте данные в интерфейсе выбранного сервиса.