Декодирование свопов SCW

С умными кошельками на основе смарт-контрактов (SCW) обмены проходят по совсем другому пути, чем с традиционными кошельками Ethereum/EVM. Эта разница может сбивать с толку, особенно когда что-то идет не так. Но как только вы поймете ключевых участников процесса — и научитесь по шагам читать, что произошло в приложении и на обозревателе блокчейна — всё станет более понятным.

Давайте пройдемся по этому вместе.


От одного нажатия до исполнения в цепочке: что происходит на самом деле

Когда вы нажимаете «Обмен» в приложении, кажется, что это одно действие. На самом деле вы запускаете многоуровневый процесс, построенный поверх абстракции аккаунтов Ethereum (ERC-4337). Ваша транзакция не отправляется напрямую в блокчейн, как при обычном кошельке. Вместо этого она делает обходной путь:

  1. Мы строим маршрут. Мы просим маршрутизатор (например, 1inch) найти лучший путь для вашего обмена и симулируем его, чтобы убедиться, что он работает. Мы оцениваем газ, проверяем, что у вас есть токены, и упаковываем инструкции в специальный формат: UserOperation.

  2. A bundler вступает в дело. Это участник вне цепочки, отвечающий за отправку UserOperations в блокчейн. Он проверяет вашу операцию, убеждается в её корректности и предоплачивает газ за вас (позже ему возмещают).

  3. Ваша UserOp попадает в блокчейн через EntryPoint смарт-контракт. Думайте об EntryPoint как о едином входе, через который проходят все транзакции SCW. EntryPoint выполняет окончательные проверки, и если всё в порядке…

  4. EntryPoint приказывает вашему смарт-контрактному кошельку (SCW) выполнить обмен. Ваш SCW вызывает маршрутизатор (например, 1inch), маршрутизатор обращается к пулу(ам), токены перемещаются, и результирующие токены попадают обратно в ваш кошелек.

Итак, в итоге: вы нажали обмен → мы симулировали → bundler отправил → EntryPoint проверил → ваш SCW выполнил.


Давайте посмотрим на реальный пример

Теперь, когда мы понимаем общий поток, давайте посмотрим, как это выглядит на реальном обмене: сначала в приложении, затем в цепочке:

Вот что мы видим:

  • Мы обменяли 1 USDC на 0.765 KTA.

  • Обмен был выполнен на Base (обратите внимание на иконку Base рядом с символами монет).

  • Мы заплатили:

    • $0.03 за газ (в ETH)

    • 0.22% комиссия за обмен в пользу goodcryptoX

    • 0.05% комиссия маршрутизатора в пользу 1inch

  • Маршрут был простой: 100% через пул Uniswap v4.

  • Bundler: Alchemy (см. Шаг 2 выше для краткого напоминания)

  • Ссылки обозревателя появляются, если транзакция дошла до блокчейна и была записана в блок (даже если она провалилась)

Пока всё выглядит хорошо. Далее давайте кликнем ссылку BaseScan, чтобы посмотреть, как эта транзакция выглядит в цепочке:

От: это не ваш кошелек — это bundler Alchemy. Это ожидаемо, поскольку bundler отправил транзакцию.

Кому: EntryPoint (v0.6.0). Опять же, ожидаемо — все транзакции SCW проходят через него.

Внутренние транзакции: показывает потоки нативных токенов (ETH на Base) внутри транзакции. Вот что мы видим:

  • Наш кошелек (…0A5) отправил ETH в EntryPoint для оплаты газа.

  • EntryPoint возместил bundler фактическую стоимость газа (поскольку bundler предоплатил газ от вашего имени; см. Шаг 2 выше). Любой оставшийся ETH остался в EntryPoint как ваш депозит для будущих транзакций.

ERC-20 переводы: показывает фактические перемещения токенов:

Наш кошелек не отправлял USDC напрямую. Вместо этого контракт токена USDC (…2A8) обработал и осуществил переводы. Это нормально: в EVM-сетях переводы токенов обрабатываются самим контрактом токена после получения инструкции от вашего смарт-контрактного кошелька.

  1. Контракт USDC разделил наш 1 USDC на три перевода:

    • 0.0022 USDC на кошелек комиссии нашего протокола (…608A)

    • 0.0005 USDC на кошелек комиссии 1inch (…1DE5)

    • Оставшиеся 0.9973 USDC к роутеру Uniswap v4 (…Universal Router)

  2. Роутер Uniswap v4 передал их менеджеру пулов Uniswap v4 (единый контракт, обслуживающий все v4 пулы).

  3. Менеджер пулов выполнил обмен: USDC вход → KTA выход.

  4. KTA был пропущен обратно через Aggregation Router 1inch, который направил его в наш кошелек (…0A5).


🧩 Как расшифровать неудачную SCW транзакцию

Теперь, когда мы понимаем, как работают обмены с смарт-контрактными кошельками (SCW) — и прошли успешную сделку — давайте применим те же инструменты, чтобы расшифровать неудачную.

Мы рассмотрим другой реальный случай: обмен ETH → токен на Ethereum, который провалился внутри контракта EntryPoint из‑за того, что не хватило ETH, чтобы покрыть и обмен, и комиссию за газ.

Итак, вы видите «Ошибка» как статус вашего обмена в приложении или получаете push-уведомление о неудаче. Что делать?


Шаг 1 — Проверьте детали заказа в goodcryptoX

Вот что вы видите в этом случае:

Используя разработанную ранее структуру, вы быстро замечаете:

  • Статус обмена — Ошибка (неудачно?)

  • Сообщение об ошибке не показано (это необычно)

  • Есть комиссия за газ (дошло до блокчейна?)

  • Показан маршрут (симуляция прошла успешно?)

  • Есть ссылки на блокчейн-обозреватели (я могу проверить TX в блокчейне!).

Проверим вашу интуицию:

  • Поле Ошибка статус означает, что обмен не удался

  • Должно быть и удобочитаемое сообщение об ошибке (переведённое из сырого), и сырое сообщение. Отсутствие сообщения об ошибке однозначно указывает на то, что произошло что-то необычное

  • Наличие комиссии за газ действительно означает, что транзакция дошла до блокчейна и произошла некоторая он-чейн активность (которая потребила газ)

  • Маршрут подтверждает, что симуляция прошла и выявила явный путь исполнения

  • Ссылки обозревателя подтверждают, что транзакция достигла блокчейна — даже если она провалилась. Обязательно откроем одну из них и исследуем дальше


Шаг 2 – Откройте транзакцию в блокчейн-обозревателе

Вы нажимаете ссылку Etherscan, чтобы увидеть, что произошло:

С первого взгляда всё становится ещё более запутанным:

  • Статус показывает ✅ Успех — подождите, что?!

  • Но мы уже знаем, что обмен не прошёл

  • Под полем «Кому» (EntryPoint) есть небольшое желтое сообщение:

    Хотя одна или несколько ошибок произошли [execution reverted] Выполнение контракта завершено

Так что же на самом деле происходит?

Вспомните поток транзакций SCW, который мы рассмотрели ранее:

  • bundler упаковывает ваш обмен в UserOperation (пакет данных с логикой вашего обмена)

  • затем отправляет его в смарт‑контракт EntryPoint

  • EntryPoint валидирует его (проверяя ваш баланс, подпись и nonce)

  • если всё в порядке, он выполняет ваше намерение — вызывает роутеры, пулы и перемещает токены.

С точки зрения блокчейна всё это выглядит просто как «bundler отправил данные в EntryPoint».

В терминах SCW этот шаг называется внешней транзакцией.

И эта транзакция действительно завершилась успешно: данные были доставлены, и EntryPoint начал выполнять свою внутреннюю логику. Отсюда ✅ Успех вверху.


Но обозреватель, будучи вежливым, всё же сообщает, что внутри EntryPoint что‑то не сработало с помощью той маленькой желтой заметки. Для обозревателя это внутренняя ошибка недостаточна, чтобы пометить всю транзакцию как провалившуюся.

Теперь на вкладке Overview бросается в глаза ещё одна деталь:

  • Примерно $6 стоимости ETH было отправлено из вашего кошелька в EntryPoint (предоплата газа).

  • Только $2.3 стоимости ETH было возмещено bundler.

  • А показанная сверху комиссия за транзакцию ещё ниже — примерно $2.15.

На первый взгляд эти числа не сходятся. Давайте разберём это сначала, прежде чем продолжить расследование


Шаг 3 – Понимание расхождения по газу

Вот разбор:

  • SCW → EntryPoint (~$6): Это предоплата газа. EntryPoint всегда собирает чуть больше, чем нужно, чтобы гарантировать выполнение вашей UserOp.

  • EntryPoint → Bundler (~$2.3): Это фактическое возмещение газа. Это реальная сумма, которую вы заплатили за эту неудачную попытку.

  • Комиссия за транзакцию (~$2.15): Это то, что bundler потратил, чтобы отправить вашу UserOp в EntryPoint. Она ниже, потому что сам EntryPoint использовал дополнительный газ при валидации и возмещении bundler — эту дополнительную стоимость заплатили вы.

Правило простое:

👉 Ваша истинная стоимость газа всегда равна возмещению EntryPoint ➜ Bundler (а не «Комиссии за транзакцию», показанной вверху)

А разница между тем, что вы предоплатили (~$6), и тем, что было возмещено (~$2.3), не исчезла. Она осталась в EntryPoint как ваш депозит, который автоматически будет применён к вашей следующей транзакции.


Шаг 4 – Проверьте вкладку AA Transactions

В обозревателе вы видите вкладку AA Transactions (AA = Account Abstraction). Здесь отображается активность смарт-контрактных кошельков, поскольку SCW работают на Account Abstraction (ERC-4337).

Давайте переключимся на эту вкладку из Overview:

Здесь вы наконец видите нашу UserOperation, перечисленную как отдельную запись внутри внешней транзакции bundler:

  • Поле "От" теперь показывает адрес нашего кошелька— подтверждая, что это наша операция.

  • У каждой такой записи есть отдельный AA Txn Hash, отличный от хэша внешней транзакции. Почему?

    • Внешний Txn Hash принадлежит транзакции Bundler->EntryPoint, которая содержала вашу UserOp (и могла включать несколько UserOp от разных пользователей).

    • AA Txn Hash — это уникальный идентификатор для вашей UserOperation внутри этого пакета.

Это ключевая идея пакетирования:

  • Bundler может упаковать вместе много UserOp в одну транзакцию.

  • Каждой UserOp присваивается свой AA Txn Hash, чтобы её можно было отслеживать отдельно внутри пакета.

  • В нашем случае, поскольку это старая транзакция (более 400 дней назад), SCW всё ещё были редкостью и пакет содержал только нашу UserOp — поэтому вкладка показывает «AA Transactions (1)». В более новых транзакциях вы часто увидите несколько UserOp, сгруппированных в одном пакете.

В этом представлении вы также заметите (!) значок рядом с вашим AA Txn Hash — подтверждение того, что ваш обмен не выполнился.

Следующий шаг — кликнуть AA Txn Hash. Это откроет отдельную страницу UserOperation, где вы увидите полные детали нашей попытки обмена — комиссию, переводы и место, где всё провалилось.


Шаг 5 – Откройте страницу с деталями AA Transaction

Клик по AA Txn Hash переводит вас на отдельную страницу с подробностями вашей UserOperation:

Здесь вы наконец увидите нашу реальную попытку обмена, ясно изложенную:

  • Статус: x Неудача (на этот раз без двусмысленности)

  • От: адрес вашего смарт-контрактного кошелька

  • Комиссия AA Transaction: ~0.00231 ETH ($2.31). Это реальная стоимость газа, которую вы заплатили — возмещение, отправленное bundler.

  • Внутренняя транзакция: один перевод ~0.00145 ETH (~$6.36) от вашего SCW в EntryPoint (предоплата газа). Других переводов не было, что подтверждает, что сам обмен не был выполнен.

  • Bundle Txn Hash: также показан, с ссылкой на внешнюю транзакцию bundler.

Эта страница наконец соответствует вашей интуиции: это реальная транзакция — UserOperation, которая представляла вашу попытку обмена.

Это почти завершает наше расследование. Но раз уж мы зашли так далеко, давайте также кликнем Internal Txns.


Шаг 6 – Проверьте вкладку Internal Transactions

Переключитесь на вкладку Internal Txns внутри представления AA Transaction:

Здесь вы видите поэтапные действия, которые EntryPoint пытался выполнить от вашего имени:

  1. ✅ Перевод от вашего SCW → EntryPoint (~0.00145 ETH, ~$6.36) = предоплата газа. Это успешно.

  2. ❌ Выполнение от вашего SCW → Uniswap Universal Router (~0.002 ETH) = попытка обмена. Это не удалось.

Этот разбор объясняет причину сбоя:

  • Вы успешно отправили ETH в EntryPoint как предоплату газа.

  • Но когда EntryPoint попытался переслать ETH в Uniswap для обмена, попытка провалилась.

Для наиболее подробного разбора откройте вкладку Logs.


Шаг 7 – Просмотрите вкладку Logs

Нажмите на Logs (3):

Здесь вы найдете три ключевых события:

  • Deposited → подтверждает, что ваша предоплата газа была получена EntryPoint.

  • BeforeExecution → показывает, что EntryPoint начал обрабатывать вашу UserOperation.

  • UserOperationEvent success: False — каноническая он-чейн запись о том, что ваша UserOp провалилась.


Что на самом деле произошло (сводка)

Этот тип ошибки характерен для обменов с SCW на EVM, где входной монетой является нативный токен (ETH, BNB, MATIC…).

  • Разрыв в логике: ни bundler, ни EntryPoint не проверяют, достаточно ли у вас именно нативного токена чтобы покрыть одновременно и предоплату газа, и сам обмен. Они проверяют это по отдельности — «достаточно ли для газа?» и «достаточно ли для обмена?». Именно поэтому симуляция прошла успешно.

  • Мы встроили в приложение предохранитель для таких случаев и предупредили вас в интерфейсе, что газа может не хватить. Но поскольку симуляция выглядела хорошо, вы могли всё равно подтвердить действие.

  • После вашего подтверждения bundler отправил вашу UserOperation в EntryPoint.

  • EntryPoint забрал примерно $6 в ETH как предоплату.

  • Когда он попытался выполнить обмен, не осталось достаточно ETH, чтобы одновременно покрыть и обмен и предоплату.

  • Вызов обмена отменился (reverted) внутри EntryPoint.

  • Вы всё равно заплатили примерно $2.3 за газ (возмещение bundler).

  • Неиспользованные ~ $3.7 остались в EntryPoint как ваш депозит, который будет автоматически использован при следующей вашей транзакции.

Последнее обновление