Симуляция транзакции – пробное исполнение на выбранном состоянии блокчейна без отправки подписанной операции в сеть. Она помогает заранее увидеть revert, перемещения токенов, выдачу approvals и вложенные вызовы. Но результат является прогнозом для конкретного снимка состояния, а не обещанием того, что произойдёт после включения в блок.
Надёжная проверка начинается не с зелёной надписи «успех», а со сравнения входных данных и ожидаемого результата. Важно понять, что именно симулировалось, на каком блоке, от какого адреса и какие изменения показал инструмент.
Зафиксируйте исходную транзакцию
Перед запуском сохраните chain ID, from, to, value, input, nonce и gas limit. Симулятор должен использовать тот же адрес отправителя: проверки allowance, ролей, whitelist и баланса зависят от msg.sender. Неверный from способен превратить полезный тест в чужой сценарий.
value показывает нативную монету, передаваемую вместе с вызовом. Она не спрятана в calldata. Поле input содержит selector и ABI-кодированные параметры. Перед сложной операцией разберите их по инструкции о расшифровке calldata и сравните recipient, spender, токен, сумму и deadline.
Уточните, к какому блоку относится состояние. eth_call может выполняться для latest, pending или заданного номера. Два сервиса, использующие разные RPC и блоки, способны показать разные результаты без ошибки в коде.
Как запустить базовую проверку
Обычный узел Ethereum поддерживает eth_call. Метод исполняет message call немедленно и возвращает результат, не создавая транзакцию. Передайте точные поля будущей операции и выбранный block tag. Если вызов завершается revert, получите причину, но помните: не все контракты возвращают понятную строку ошибки.
eth_estimateGas решает другую задачу – оценивает gas, необходимый для исполнения. Успешная оценка косвенно показывает, что выбранный путь не упал в текущем состоянии, но не раскрывает все переводы и approvals. Большой gas limit сам по себе не доказывает кражу, а маленькая оценка не доказывает безопасность.
Для сложной операции полезен debug_traceCall или аналогичный call trace. Он показывает дерево CALL, STATICCALL и DELEGATECALL, адреса, value, входные данные, возвраты и ошибки. Такой trace раскрывает действия router и multicall, которые не видны по одному верхнему selector.
Какие изменения нужно увидеть
Составьте собственное ожидание до просмотра результата. Например: списывается один токен, приходит другой, allowance уменьшается или остаётся ограниченным, NFT переходит заданному получателю. Затем сравните с balance changes симулятора по каждому активу и адресу.
Проверьте нативные переводы, ERC-20, ERC-721 и ERC-1155. Нулевое изменение баланса пользователя не означает отсутствие риска: транзакция может выдать безлимитный approval, назначить operator для NFT или изменить роль в другом контракте. Такие изменения могут сработать позднее.
Просмотрите события, но не используйте их как единственное доказательство. Контракт способен emit событие без соответствующего устойчивого состояния, а некоторые изменения вообще не имеют логов. Сопоставление emitter, topics и data описано в материале о чтении событий смарт-контракта.
Красные флаги в результате
- неожиданный recipient или вызов незнакомого контракта;
- approval для другого spender либо сумма заметно выше нужной;
setApprovalForAllдля коллекции NFT;DELEGATECALLв неизвестный implementation;- перевод актива без ожидаемого встречного поступления;
- создание нового контракта или изменение административной роли;
- непонятный multicall, в котором инструмент пропустил часть вложенных данных.
Для proxy найдите текущий implementation и admin. Симуляция выполняет код, который доступен в выбранном состоянии, но владелец обновляемого proxy может заменить его до майнинга. Порядок проверки приведён в статье о proxy и implementation.
Почему реальный результат меняется
Между симуляцией и блоком меняются резервы пула, oracle price, allowance, nonce, timestamp и порядок транзакций. В swap может вмешаться MEV, а другая операция пользователя способна потратить баланс раньше. Если контракт зависит от block.number, времени или состояния внешнего протокола, новый контекст изменит ветку исполнения.
RPC также может применять ограничения или state overrides. Overrides позволяют временно заменить баланс, nonce, код или storage для анализа. Это полезный инструмент разработчика, но результат с подменённым состоянием нельзя выдавать за прогноз реальной сети. Зафиксируйте provider, block number и наличие overrides.
Сложный вредоносный контракт способен показывать безобидное поведение в типичном offchain-тесте и другое – при изменившемся окружении. MetaMask называет такие сценарии red-pill attacks и подчёркивает, что обычные offchain-симуляции не гарантируют совпадение с onchain-исполнением. Подробнее пределы метода разобраны в статье почему симуляция не является гарантией.
Приватность и доверие к сервису
Кошелёк может отправлять неподписанную транзакцию на централизованный сервер симуляции. Тогда оператор видит IP-адрес, аккаунт, адрес назначения и намерение до публикации. Проверьте настройки приватности и не считайте удобный preview локальным вычислением без подтверждения документации.
Полезно повторить важную симуляцию через независимый RPC или другой инструмент. Совпадение результатов повышает уверенность в декодировании, но два сервиса могут зависеть от одного backend. Сравнивайте не цвет предупреждения, а block number, call tree и изменения состояния.
Транзакция и подпись – разные запросы
Typed-data подпись EIP-712 сама по себе не исполняет EVM-вызов. Симулятор транзакций может не показать будущий эффект permit, ордера или сообщения для стороннего relayer. Нужно отдельно проверить domain, chain ID, verifying contract, spender, amount, nonce и deadline.
Если сервис строит будущую транзакцию из подписи, запросите её точную структуру и проверьте возможный onchain-вызов. Практический порядок есть в инструкции по проверке EIP-712 подписи.
Финальный порядок проверки
- сверьте сеть, отправителя,
to,valueи calldata; - зафиксируйте RPC, номер блока и режим
latestилиpending; - проверьте success или revert и причину ошибки;
- сравните все balance changes с собственным ожидаемым результатом;
- изучите approvals, NFT operators, роли и storage changes;
- раскройте call trace, proxy и вложенные multicall;
- при большой сумме повторите тест независимым способом;
- перед подписью ещё раз сравните поля с симулированной версией.
Симуляция полезна как подробная репетиция. Она ловит множество ошибок, но не останавливает время и не фиксирует состояние сети. Правильный вывод звучит не «транзакция безопасна», а «при этих входных данных и этом состоянии наблюдался такой результат, а оставшиеся риски понятны».



