Поля call frame отвечают на разные вопросы
ПолеЧто показываетЧего не доказывает
typeCALL, STATICCALL, DELEGATECALL, CREATE или другой тип кадраЧто интерфейс правильно понял бизнес-операцию
from / toНепосредственную границу вызоваЛичность владельца адреса
input / outputCalldata и возвращённые bytesСмысл без точного ABI этой версии
valueNative value, переданное этому frameERC-20 transfer или цену актива
gas / gasUsedЛимит и расход внутри модели tracerОтдельную сетевую комиссию дочернего вызова
callsВложенные call framesСамостоятельные подписанные транзакции
Поля call frame отвечают на разные вопросы
Поле
type
Что показывает
CALL, STATICCALL, DELEGATECALL, CREATE или другой тип кадра
Чего не доказывает
Что интерфейс правильно понял бизнес-операцию
Поле
from / to
Что показывает
Непосредственную границу вызова
Чего не доказывает
Личность владельца адреса
Поле
input / output
Что показывает
Calldata и возвращённые bytes
Чего не доказывает
Смысл без точного ABI этой версии
Поле
value
Что показывает
Native value, переданное этому frame
Чего не доказывает
ERC-20 transfer или цену актива
Поле
gas / gasUsed
Что показывает
Лимит и расход внутри модели tracer
Чего не доказывает
Отдельную сетевую комиссию дочернего вызова
Поле
calls
Что показывает
Вложенные call frames
Чего не доказывает
Самостоятельные подписанные транзакции

Receipt фиксирует итог, trace объясняет путь исполнения

Сначала зафиксируйте chain ID, block hash, transaction hash и верхнеуровневые from/to/input/value. Receipt нужен как якорь включения и результата. Trace создаётся execution client отдельно: Geth debug_traceTransaction повторяет транзакцию так, как она исполнялась, при необходимости переисполняя предыдущие блоки для восстановления historical state. Поэтому два сервиса могут по-разному ограничивать глубину, timeout или доступную историю, хотя исходная транзакция одна.

Воспроизводимый запрос к Geth

  1. 1
    Закрепите контекст

    Сохраните сеть, block number и hash, полный transaction hash и версию execution client. Не начинайте со скриншота эксплорера.

  2. 2
    Запросите callTracer

    Передайте transaction hash в debug_traceTransaction с tracer=callTracer. onlyTopCall должен быть false или отсутствовать, иначе вложенные frames не появятся.

  3. 3
    Зафиксируйте настройки

    Сохраните tracerConfig, timeout и reexec. Ошибка historical state — это ограничение узла, а не доказательство отсутствия вызовов.

  4. 4
    Разверните дерево

    Читайте от корня к children, сохраняя depth, type, from, to, value, input, gasUsed, error и вложенность.

  5. 5
    Декодируйте после адреса

    Применяйте ABI только после проверки code address, proxy implementation и блока, на котором выполнялась транзакция.

Тип вызова определяет, чей код и чьё состояние вы видите

Короткая карта EVM call types
ТипКодСостояние и ограниченияДиагностический вопрос
CALLКод адреса toКонтекст и storage адреса to; может передаваться native valueКого непосредственно вызвал текущий frame?
STATICCALLКод адреса toСтатический контекст запрещает изменение состоянияПытался ли путь только читать?
DELEGATECALLКод адреса toStorage и адресный контекст caller; msg.sender и msg.value сохраняютсяКакой implementation-код менял состояние proxy?
CREATE / CREATE2Init code нового контрактаНовый адрес появляется только при успешном созданииГде возник дочерний контракт?
Короткая карта EVM call types
Тип
CALL
Код
Код адреса to
Состояние и ограничения
Контекст и storage адреса to; может передаваться native value
Диагностический вопрос
Кого непосредственно вызвал текущий frame?
Тип
STATICCALL
Код
Код адреса to
Состояние и ограничения
Статический контекст запрещает изменение состояния
Диагностический вопрос
Пытался ли путь только читать?
Тип
DELEGATECALL
Код
Код адреса to
Состояние и ограничения
Storage и адресный контекст caller; msg.sender и msg.value сохраняются
Диагностический вопрос
Какой implementation-код менял состояние proxy?
Тип
CREATE / CREATE2
Код
Init code нового контракта
Состояние и ограничения
Новый адрес появляется только при успешном создании
Диагностический вопрос
Где возник дочерний контракт?

Internal transaction — удобный ярлык, а не второй transaction object

Externally owned account подписывает верхнеуровневую транзакцию и расходует свой nonce. Во время исполнения смарт-контракт создаёт CALL-подобные frames без новой пользовательской подписи и без отдельного nonce. Эксплорер может превратить часть дерева в плоский список value transfers, но его строки остаются производным представлением. Для аудита сохраняйте путь вроде root.calls[1].calls[0], а не выдуманный дочерний transaction hash.

Диагностика расхождений
НаблюдениеВероятная причинаСледующее действие
В эксплорере есть internal transfer, в callTracer нет отдельной строкиИнтерфейс агрегировал value/state effectИскать исходный frame и правила конкретного эксплорера
Trace обрывается ошибкой historical stateУзел не восстановил нужное состояние в пределах reexecПовторить на архивном или более полном узле, сохранив настройки
to знакомый, decoded method бессмысленНеверный ABI, proxy version или selector collisionПроверить bytecode и implementation на этом блоке
Дочерний frame имеет errorОшибка возникла на этой веткеПроверить, была ли она перехвачена вызывающим кодом; не переносить её автоматически на итог всей транзакции
Два клиента дают разную формуTrace API и tracer не стандартизуют единый displayСравнить client/version/config и доказуемые EVM effects
Диагностика расхождений
Наблюдение
В эксплорере есть internal transfer, в callTracer нет отдельной строки
Вероятная причина
Интерфейс агрегировал value/state effect
Следующее действие
Искать исходный frame и правила конкретного эксплорера
Наблюдение
Trace обрывается ошибкой historical state
Вероятная причина
Узел не восстановил нужное состояние в пределах reexec
Следующее действие
Повторить на архивном или более полном узле, сохранив настройки
Наблюдение
to знакомый, decoded method бессмыслен
Вероятная причина
Неверный ABI, proxy version или selector collision
Следующее действие
Проверить bytecode и implementation на этом блоке
Наблюдение
Дочерний frame имеет error
Вероятная причина
Ошибка возникла на этой ветке
Следующее действие
Проверить, была ли она перехвачена вызывающим кодом; не переносить её автоматически на итог всей транзакции
Наблюдение
Два клиента дают разную форму
Вероятная причина
Trace API и tracer не стандартизуют единый display
Следующее действие
Сравнить client/version/config и доказуемые EVM effects

Проверка заканчивается воспроизводимым путём, а не красивой диаграммой

Результат можно передать другому аналитику, если у него есть chain, block hash, transaction hash, Geth version, точный trace request и путь до нужного frame. Добавьте проверенный ABI и объясните, почему выбран CALL или DELEGATECALL context. Если узел не может восстановить state, адрес implementation неизвестен или разные клиенты расходятся в существенном эффекте, остановите вывод и сохраните raw responses. Причину верхнеуровневого revert разбирайте отдельно: call tree показывает место исполнения, но не заменяет проверку receipt, error data и gas.

Источники

Мы используем прямые ссылки и фиксируем дату проверки. Полный текст чужих материалов не перепечатывается.

  1. Geth — debug namespace: debug_traceTransaction go-ethereum · Проверено 21 августа 2026 г. в 22:03 GMT+5
  2. Geth — Built-in tracers: callTracer go-ethereum · Проверено 21 августа 2026 г. в 22:03 GMT+5
  3. Solidity — Delegatecall and libraries Solidity Project · Проверено 21 августа 2026 г. в 22:03 GMT+5
Материал носит информационный характер и не является индивидуальной рекомендацией. Криптоактивы связаны с риском волатильности, технических сбоев, хищения и полной потери средств.