| Поле | Что показывает | Чего не доказывает |
|---|---|---|
| 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 | Самостоятельные подписанные транзакции |
- Поле
- 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Закрепите контекст
Сохраните сеть, block number и hash, полный transaction hash и версию execution client. Не начинайте со скриншота эксплорера.
- 2Запросите callTracer
Передайте transaction hash в debug_traceTransaction с tracer=callTracer. onlyTopCall должен быть false или отсутствовать, иначе вложенные frames не появятся.
- 3Зафиксируйте настройки
Сохраните tracerConfig, timeout и reexec. Ошибка historical state — это ограничение узла, а не доказательство отсутствия вызовов.
- 4Разверните дерево
Читайте от корня к children, сохраняя depth, type, from, to, value, input, gasUsed, error и вложенность.
- 5Декодируйте после адреса
Применяйте ABI только после проверки code address, proxy implementation и блока, на котором выполнялась транзакция.
Тип вызова определяет, чей код и чьё состояние вы видите
| Тип | Код | Состояние и ограничения | Диагностический вопрос |
|---|---|---|---|
| CALL | Код адреса to | Контекст и storage адреса to; может передаваться native value | Кого непосредственно вызвал текущий frame? |
| STATICCALL | Код адреса to | Статический контекст запрещает изменение состояния | Пытался ли путь только читать? |
| DELEGATECALL | Код адреса to | Storage и адресный контекст caller; msg.sender и msg.value сохраняются | Какой implementation-код менял состояние proxy? |
| CREATE / CREATE2 | Init code нового контракта | Новый адрес появляется только при успешном создании | Где возник дочерний контракт? |
- Тип
- 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.
Источники
Мы используем прямые ссылки и фиксируем дату проверки. Полный текст чужих материалов не перепечатывается.
- Geth — debug namespace: debug_traceTransaction go-ethereum · Проверено 21 августа 2026 г. в 22:03 GMT+5
- Geth — Built-in tracers: callTracer go-ethereum · Проверено 21 августа 2026 г. в 22:03 GMT+5
- Solidity — Delegatecall and libraries Solidity Project · Проверено 21 августа 2026 г. в 22:03 GMT+5
