Кошелёк пишет, что подтверждено. На странице обозревателя стоит зелёная галочка. А токенов на счёте нет. Ничто не застряло и ничего не нужно отправлять заново: поле статуса ответило на более узкий вопрос, чем тот, который вы задавали. Ниже разобрано, что именно удостоверяет это поле, что оно оставляет за скобками и где записан ответ, который вам на самом деле нужен.
Что на самом деле удостоверяет успешный статус
EIP-658 поместил в квитанцию транзакции код статуса и определил два его значения одной строкой: 0 означает неуспех, вызванный любой операцией, из-за которой транзакция или верхнеуровневый вызов может откатиться, а 1 означает успех. Блокчейн-эксплорер превращает эту единицу в галочку.
Важна область действия этого определения. Код описывает верхнеуровневый вызов. Он сообщает, что самая внешняя часть выполнения завершилась без отката, и не сообщает ничего сверх этого: ни что изменился баланс конкретного токена, ни что переместилась та сумма, которую вы имели в виду, ни что вызванный контракт сделал то, о чём вы его просили. Квитанция со статусом 0 — это то, что обозреватель помечает как reverted. Квитанция со статусом 1 исключает этот случай и на этом останавливается.
Каждый случай ниже живёт именно в этом зазоре. Цепь записала происходящее полностью. А сводка из одного слова наверху страницы отвечала на другой вопрос.
| Вопрос, который вы задаёте | Где записан ответ |
|---|---|
| Попала ли она в блок | Номер блока в квитанции |
| Обошёлся ли внешний вызов без отката | Код статуса в квитанции |
| Изменился ли баланс этого токена | События перевода в журналах |
| Сделала ли моя пользовательская операция свою работу | Флаг успеха в её собственном событии |
Почему перевод токенов может не пройти без отката
Стандарт токена ERC-20 объявляет transfer функцией, возвращающей булево значение, и о последствиях говорит жёстко: вызывающая сторона обязана обрабатывать false из returns bool success, и вызывающая сторона не должна считать, что false никогда не возвращается. Неуспеху разрешено приходить в виде возвращаемого значения, а не в виде отката.
Когда токен сообщает о неуспехе именно так, исход зависит от контракта, который его вызвал. Вызывающая сторона, проверяющая булево значение, может откатиться на false, и квитанция вернётся со статусом 0. Вызывающая сторона, отбросившая это значение, идёт дальше, самый внешний вызов завершается, квитанция говорит об успехе, а баланс так и не сдвинулся.
Возвращаемые значения различаются и вторым способом. Библиотека SafeERC20 от OpenZeppelin описывает себя как обёртки над операциями ERC-20, которые выбрасывают исключение при неуспехе, когда контракт токена возвращает false, и добавляет, что токены, не возвращающие значения вовсе, тоже поддерживаются, а вызовы без отката считаются успешными. Библиотека, написанная ради приведения этих возвращаемых значений к единому виду, сама по себе является прямым свидетельством того, что они неоднородны.
Неуспехи, которые контракт проглатывает намеренно
Контракт может вызвать другой контракт и заранее решить не падать вместе с ним. Конструкция try и catch в Solidity, а также низкоуровневый вызов, который отдаёт флаг успеха вместо того, чтобы пробрасывать откат наверх, существуют ровно для того, чтобы выполнение продолжалось после внутреннего неуспеха. Роутеры, батчеры и релееры пользуются этим намеренно: одна нога пакета не проходит, остальные ноги рассчитываются, а транзакция в целом успешна.
Со стороны квитанции это неотличимо от предыдущего случая. Внутренний вызов не прошёл, внешний вызов поглотил этот неуспех, а поле статуса записало внешний результат. Внутренний неуспех по-прежнему в цепи, но он лежит в трассе выполнения и в том, чего в журналах нет, а не в поле статуса.
Недостаточный лимит расходования — один из путей к этой форме. Контракт, который забирает ваши токены через transferFrom, тратит внутри лимита, заданного вами через одобрение токенов. Когда лимит меньше вытягиваемой суммы, внутренний вызов не проходит, а падает ли вместе с ним вся транзакция, решает вызывающая сторона, а не токен.
Когда приходит меньше, чем было отправлено
В третьем случае неуспеха нет вовсе, а арифметика всё равно не сходится. Контракт токена может удерживать часть внутри собственной функции transfer, зачисляя получателю меньше, чем передал отправитель. Отправьте 5 000 единиц токена, который берёт 3% с каждого перевода, и придёт 4 850. Квитанция говорит об успехе, событие перевода на месте, а число внутри него — не то число, которое вы набрали.
Ребейз-токены дают родственное расхождение с противоположной стороны. Их балансы переписываются контрактом, а не перемещаются переводом, поэтому баланс может измениться без всякого события перевода за ним. Сверять показания кошелька с суммами в истории транзакций для такого токена не получится, и при этом ни одно из двух показаний не ошибочно.
Что означает сообщение об ошибке с упоминанием paymaster
При абстракции аккаунтов вы отправляете не транзакцию. ERC-4337 определяет объект UserOperation с собственным мемпулом и бандлера, который упаковывает такие объекты в одну обычную транзакцию к контракту EntryPoint. Paymaster — это контракт, который соглашается заплатить за транзакцию вместо отправителя. Сообщение об ошибке, называющее paymaster, покрывает две ситуации, у которых нет ничего общего, кроме слова «ошибка».
Первая — отклонение во время валидации. ERC-4337 требует: если любой вызов validateUserOp не проходит, handleOps обязан пропустить выполнение как минимум этой пользовательской операции, и требует от бандлеров отклонять недействительные операции из своего мемпула, а не помещать их в цепь. Paymaster, который отказывается спонсировать вызов, у которого слишком мало депозита или который не проходит собственную валидацию, отправляет операцию в эту ветку. Ничего не было включено, ничего не было списано, и искать нечего по хешу, потому что неуспех случился до того, как цепь увидела операцию.
Вторая происходит после включения, и именно она даёт галочку. После прохождения валидации спецификация утверждает, что выполнение произойдёт и произойдёт лишь однажды, а также гарантирует оплату комиссии. Затем EntryPoint выпускает для каждой пользовательской операции событие с флагом успеха, документированным как true, если транзакция отправителя удалась, и false, если она откатилась, рядом с фактически уплаченной аккаунтом или paymaster суммой. Пакетная транзакция успешна, с paymaster списано, а флаг вашей операции равен false. Все три утверждения верны одновременно.
| Где случился неуспех | Попало в блок | Кто заплатил | Что можно посмотреть |
|---|---|---|---|
| Валидация, до включения | Нет | Никто | Ошибка от бандлера или кошелька и никакой записи в цепи |
| Выполнение, после включения | Да | Аккаунт или paymaster | Успешная транзакция, у события пользовательской операции которой флаг успеха равен false |
Куда смотреть вместо поля статуса
Перемещения токенов записываются как события в журналах. Вид с переводами токенов в обозревателе — это отображение этих событий, поэтому если вашего адреса нет ни в одном из них, токен не двигался, что бы ни говорил статус. Проверять надо журналы; статус — это сводка.
Три вопроса делают всю работу. Есть ли вообще событие перевода с вашим адресом или этот раздел страницы пуст? Если оно есть, равна ли его сумма отправленной сумме? И тот ли контракт его выпускает, который вы имели в виду, и в той ли сети.
Четвёртая возможность переживает все три проверки: перевод произошёл ровно так, как было велено, а ищут его не там. Второй адрес, выведенный из той же сид-фразы, тот же адрес в другой сети и токен, который кошелёк не покажет, пока его контракт не добавят вручную, — каждый из них даёт пустой экран рядом с совершенно исправной квитанцией.
Итог
Статус квитанции — это утверждение о самом внешнем вызове и ни о чём больше. Успех означает, что транзакция не откатилась. Он никогда не означал, что токен переместился, что переместилась верная сумма или что контракт сделал с ней то, чего от него хотели. Эти факты живут в журналах событий, а при ERC-4337 — во флаге успеха, отделённом от статуса несущей его транзакции.
Когда перевод пропадает за зелёной галочкой, идите по слоям по порядку: событие перевода, затем его сумма, затем контракт токена и сеть. Чтобы продолжать изучать основы, следите за материалами Bitbase Academy.
Похожие материалы
Другие материалы Bitbase по этой теме:
- Как безопасно сменить RPC-эндпоинт
- Максимальная комиссия за транзакцию превышена: что означает это предупреждение кошелька
- Превышен лимит запросов RPC и что с этим делать
- Глобальная ликвидность, M2 и биткоин: руководство по измерению
Дисклеймер: эта статья — образовательный материал Bitbase Academy, только для информационных целей. Она не является инвестиционным, торговым, налоговым или финансовым советом. Криптоактивы волатильны — оценивайте риски самостоятельно. Написано в сентябре 2026 года; сверяйтесь с актуальной официальной информацией.
Источники
[1] Ethereum Improvement Proposals, EIP-20: Token Standard (функция transfer и её булево возвращаемое значение) eips.ethereum.org
[2] Ethereum Improvement Proposals, EIP-658: Embedding transaction status code in receipts (поле статуса в квитанции транзакции) eips.ethereum.org
[3] Ethereum Improvement Proposals, ERC-4337: Account Abstraction Using Alt Mempool (валидация, бандлеры и paymaster) eips.ethereum.org
[4] eth-infinitism, account-abstraction, contracts/interfaces/IEntryPoint.sol, тег v0.7.0 (объявление UserOperationEvent) raw.githubusercontent.com
[5] OpenZeppelin, openzeppelin-contracts, contracts/token/ERC20/utils/SafeERC20.sol, тег v5.1.0 (документирующий комментарий библиотеки) raw.githubusercontent.com






