ГЛАВНАЯ / ИНСТРУКЦИИ / FALLBACK И RECEIVE В SOLIDITY: КУДА ПОПАДАЕТ ВЫЗОВ БЕЗ ФУНКЦИИ
fallback и receive в Solidity: куда попадает вызов без функции
В Solidity receive предназначена для вызова с пустым calldata, а fallback служит резервным обработчиком, если функция не найдена. Обе функции могут повлиять на приём Ether, но выбор зависит от calldata, наличия receive и payable. По одному факту перевода нельзя понять, какой код выполнился.
Сначала Solidity ищет функцию по selector
При обычном вызове calldata содержит selector функции и закодированные аргументы. Если selector совпадает с известной внешней функцией, выполняется её тело. Если функция не найдена, управление может перейти в fallback. Для пустого calldata отдельная receive имеет приоритет, если она определена.
Receive объявляется как receive() external payable без аргументов и возвращаемого значения. Она предназначена для пустого вызова, в том числе обычной передачи Ether без данных. Наличие этой функции не означает, что контракт принимает любой вызов с value: непустой calldata направляется по другим правилам.
- пустой calldata маршрутизируется отдельно
- receive должна быть external payable
- неизвестный selector передаётся в fallback
Fallback принимает неизвестный вызов, а Ether – только если он payable
Fallback вызывается, когда ни одна объявленная функция не совпала с selector, либо когда calldata пустой и receive отсутствует. Чтобы принять Ether по такому пути, fallback должен быть payable. Если он не payable, вызов с value завершается ошибкой.
Параметрическая форма fallback(bytes calldata input) может принять полный calldata и вернуть bytes. Эта форма применяется в низкоуровневой маршрутизации, например в proxy, но сама по себе не декодирует безопасно любой интерфейс. Сверяйте селектор, получателя и реализацию с ожидаемой схемой; ошибка ABI может отправить вызов в резервный путь.
- fallback проверен на payable
- параметрическая форма обрабатывает полный calldata
- ошибка декодирования не признана безопасным вызовом
| Вход | Если receive есть | Если receive нет |
|---|---|---|
| Пустой calldata, Ether | receive | payable fallback или отказ |
| Пустой calldata, без Ether | receive | fallback |
| Неизвестный selector | fallback | fallback |
| Известная функция | Функция по selector | Функция по selector |
Обработчик не видит каждый способ увеличения баланса
Обычный перевод с пустым calldata вызывает receive или payable fallback согласно правилам dispatch. Но баланс контракта может увеличиться и без обычного вызова, например через предусмотренный протоколом механизм принудительной передачи. Тогда Solidity-функция получателя не исполняется, поэтому внутренний счётчик, обновляемый только в receive, может отличаться от address(this).balance.
Учтите ограничения газа вызывающей операции и не полагайтесь на устаревшее предположение, что send или transfer с жёстким stipend подходят для любой логики получателя. Если функция делает больше простого учёта, изучите актуальные правила вызова и тестируйте при достаточном gas; сам факт объявления receive не гарантирует успешную доставку.
Сопоставьте calldata, value и фактически выбранную функцию
В обозревателе или trace проверьте адрес назначения, длину calldata, первые четыре байта, переданный value и выбранный код. Для прокси выясните, переслал ли fallback вызов через delegatecall и какая реализация была активна на блоке. Ошибка декодирования интерфейса может показать «unknown method», хотя контракт обработал calldata резервной логикой.
Если ожидается простой перевод Ether, убедитесь, что calldata пустой и получатель может принять value выбранным путём. Если ожидалась конкретная операция, проверьте selector и ABI до подписи, а после исполнения – receipt и изменение состояния. Не делайте вывод о поведении только по названию кнопки кошелька.
Частые вопросы
Когда вызывается receive?
При вызове контракта с пустым calldata, если receive объявлена.
Fallback всегда принимает Ether?
Нет. Для приёма Ether он должен быть payable; при наличии receive пустой вызов обрабатывает receive.
Неизвестный selector вызывает receive?
Нет. Он направляется в fallback, если тот есть.
Каждый Ether, поступивший на контракт, вызывает receive?
Нет. Существуют способы увеличения баланса без исполнения функции получателя.
Почему перевод сработал, хотя интерфейс не показал функцию?
Пустой перевод мог быть обработан receive или payable fallback; проверьте код и trace.
Чек-лист: fallback и receive в solidity: куда попадает вызов без функции
- calldata и selector проверены;
- наличие receive/fallback установлено;
- пустой и непустой вызовы различены;
- payable путь подтверждён;
- value и gas условия учтены;
- proxy dispatch и активная реализация проверены;
- receipt и состояние после вызова сверены.
Материал подготовлен редакцией сайта и проверен 2 ноября 2026 года. Условия бирж, кошельков и блокчейн-сетей могут меняться. Перед операцией сверяйте данные в интерфейсе выбранного сервиса.