ГЛАВНАЯ / ИНСТРУКЦИИ / REVERT, CUSTOM ERROR И PANIC: КАК ЧИТАТЬ ДАННЫЕ ОБ ОШИБКЕ EVM
revert, custom error и Panic: как читать данные об ошибке EVM
Revert означает откат состояния текущего вызова, но причина может быть представлена строкой, custom error, Panic или вообще пустыми данными. Обозреватель показывает текст только при наличии подходящего ABI или декодера. Чтобы понять отказ, сопоставьте raw returndata с frame trace и интерфейсом именно той версии контракта.
Состояние frame откатывается, но уже потраченный gas не исчезает
При revert EVM отменяет изменения состояния, сделанные текущим frame и его вложенными вызовами. Ошибка может пройти вверх по цепочке вызовов или быть перехвачена через try/catch либо обработана низкоуровневым вызовом. На уровне транзакции важно отдельно посмотреть receipt и status.
Откат не означает бесплатное исполнение: вычислительная работа до ошибки всё равно потребляет ресурсы. Если вызывающий контракт перехватывает неуспешный ответ, верхний frame может продолжить работу. Поэтому сообщение revert, внутренний trace и финальный статус транзакции отвечают на разные вопросы.
Error, Panic и custom error отличаются кодированием
Error(string) – встроенный формат для обычного описания отказа, например сообщения require. Panic(uint256) обозначает ошибку, которая обычно не должна происходить в корректной логике; код помогает классифицировать условие, например неверное assert или арифметический overflow в проверяемом Solidity-коде. Custom error задаёт разработчик и может содержать типизированные параметры.
Для ABI-декодируемой ошибки первые четыре байта обычно являются selector, а следующие данные кодируют аргументы по ABI. Но revert data может быть пустым, повреждённым или возвращённым внутренним вызовом. Наличие читаемого имени ошибки зависит от интерфейса, с которым работает обозреватель или клиент.
- Error(string) несёт текстовую причину
- Panic(uint256) содержит встроенный код
- custom error определяется ABI конкретного проекта
| Данные | Что обычно сообщают | Что сверить |
|---|---|---|
| Error(string) | Сообщение require или revert | Полный ABI-кодированный payload |
| Panic(uint256) | Класс внутреннего или проверочного сбоя | Код panic и точный frame |
| Custom error | Имя и аргументы ошибки проекта | Selector, ABI и версия контракта |
| Пустой ответ | Причина не представлена в returndata | Вызов, trace и условия функции |
Raw error data нужно проверять вместе с ABI контракта
Сохраните байты ответа до декодирования. Определите, какой контракт сформировал их на конкретном уровне trace, найдите верифицированный ABI этой версии и сопоставьте selector с объявлением ошибки. Для proxy учитывайте, что код implementation исполняется через proxy-контекст, а обновлённая реализация может иметь другой набор ошибок.
Не считайте человекочитаемую подпись в интерфейсе официальным доказательством источника. ABI-декодирование интерпретирует байты по схеме; оно не подтверждает, что контракт действительно создал это сообщение или что ошибка объясняет весь отказ. Внутренний вызов может передать наружу данные, похожие на ошибку вызывающего контракта.
- returndata сохранена до декодирования
- ABI соответствует коду на выбранном блоке
- selector не принят за удостоверение источника
Проверяйте bool результата и returndata отдельно
Низкоуровневые call, delegatecall и staticcall обычно возвращают success и bytes returndata вместо автоматического bubbling ошибки. Если код игнорирует success, функция может продолжить исполнение после неудачного вызова. Если он проверяет bool, но не сохраняет данные, причина отказа может потеряться.
Обратный случай тоже возможен: низкоуровневый вызов несуществующего аккаунта может вернуть success, поэтому при необходимости проверьте наличие кода адреса отдельно. При диагностике объедините параметры calldata, адрес цели, opcode, returndata и верхнеуровневый receipt. Не принимайте строку ошибки за единственную причину.
Частые вопросы
Revert возвращает исходный баланс и не требует комиссии?
Изменения состояния откатываются, но gas за исполнение до отказа может быть потрачен.
Panic и custom error – одно и то же?
Нет. Panic – встроенный формат для определённых сбоев; custom error объявляется контрактом.
Можно определить автора ошибки по тексту?
Нет. Декодирование показывает соответствие ABI, но не подтверждает происхождение payload.
Почему обозреватель показывает неизвестную ошибку?
У него может не быть ABI нужной версии или selector может быть неизвестен.
Если внутренний вызов завершился revert, вся транзакция всегда неуспешна?
Не обязательно. Низкоуровневый вызов или try/catch может обработать отказ; проверьте верхний receipt.
Чек-лист: revert, custom error и panic: как читать данные об ошибке evm
- receipt и frame отказа найдены;
- raw returndata сохранён;
- формат Error/Panic/custom/empty определён;
- ABI соответствует коду на блоке;
- selector и параметры сверены;
- low-level success проверен отдельно;
- текст ошибки не принят за доказательство источника.
Материал подготовлен редакцией сайта и проверен 2 ноября 2026 года. Условия бирж, кошельков и блокчейн-сетей могут меняться. Перед операцией сверяйте данные в интерфейсе выбранного сервиса.