Что такое журнал событий?
Журнал событий (лог) — это запись, которую EVM-контракт создаёт при выполнении опкодов LOG0–LOG4 (emit в Solidity). Каждая запись содержит адрес контракта, создавшего событие, до четырёх 32-байтовых topics и поле data произвольной длины. Декодировать лог — значит сопоставить topics[0] с сигнатурой события, прочитать indexed-параметры из остальных topics и ABI-декодировать неиндексированные параметры из data. Обозреватели делают это по верифицированному исходному коду; эта страница — только по сигнатуре для более чем сорока распространённых событий или по любому вставленному вами ABI.
Как кодируется лог
| Поле | Содержимое | Пример (ERC-20 Transfer) |
|---|---|---|
| address | Контракт, создавший событие | 0xdAC17F958D2ee523a2206206994597C13D831ec7 (USDT) |
| topics[0] | keccak256 канонической сигнатуры | 0xddf252ad… = keccak256("Transfer(address,address,uint256)") |
| topics[1] | Первый индексированный параметр, дополненный слева до 32 байт | адрес from |
| topics[2] | Второй индексированный параметр | адрес to |
| data | ABI-кодирование всех неиндексированных параметров | 32-байтовое value |
Индексированные параметры статического типа (address, целые числа, bool, bytes1–32) хранятся в топике напрямую. Индексированные параметры динамического типа (string, bytes, массивы, структуры) заменяются хешем Keccak-256 их кодирования, как описано в разделе о событиях спецификации Solidity ABI; декодер помечает их как хешированные.
Разбор примера: перевод USDT
Нажмите «ERC-20 Transfer» выше. topics[0] совпадает с сигнатурой Transfer, и поскольку topics ровно три, выбирается раскладка ERC-20 (два индексированных адреса), а не ERC-721 (три индексированных параметра). topics[1] декодируется в from = 0xd8dA6BF2…96045, topics[2] — в to = 0x1111…1111, а единственное слово data 0x17d7840 — это value = 25000000, что при шести десятичных знаках USDT составляет 25 USDT. Тот же механизм декодирует Uniswap V2 Swap (два индексированных адреса, четыре суммы в data) или ERC-1155 TransferBatch, поле data которого содержит два динамических массива со смещениями и длинами.
События, распознаваемые без ABI
Таблица ниже генерируется на странице из того же списка сигнатур, который использует декодер, поэтому каждое значение topics[0] служит самопроверкой реализации Keccak. Она охватывает Transfer и Approval для ERC-20 и ERC-721, ApprovalForAll, ERC-1155 TransferSingle, TransferBatch и URI, WETH Deposit и Withdrawal, Uniswap V2 Swap, Sync, Mint, Burn и PairCreated, Uniswap V3 Swap, Mint, Burn, Collect и PoolCreated, OwnershipTransferred, EIP-1967 Upgraded, AdminChanged и BeaconUpgraded, события Initializable, Pausable и AccessControl, Permit2 Approval, Permit, NonceInvalidation и Lockdown, ERC-4626 Deposit и Withdraw, а также Safe ExecutionSuccess, ExecutionFailure, SafeMultiSigTransaction, изменения владельцев и порога, SafeSetup и ProxyCreation.
Поддерживаемые входные данные
- Один объект лога
{"address","topics","data"}, скопированный из обозревателя, viem, ethers или web3.py. - Массив логов,
resultвызоваeth_getLogsили весь ответ JSON-RPC. - Receipt транзакции: каждая запись его массива
logsдекодируется по порядку, с номером блока, индексом лога и хешем транзакции. - Topics, вставленные по одному на строку, плюс data в hex — для логов, скопированных из трассировки или отладчика; метки вроде «topics[1]:» игнорируются.
- Необязательный ABI: JSON-массив фрагментов, объект с ключом
abi(артефакты Hardhat и Foundry) или человекочитаемые строкиevent …. События из ABI имеют приоритет над встроенной таблицей.
См. также: вычислите хеш топика по любой сигнатуре в калькуляторе селекторов и топиков, декодируйте calldata транзакции в ABI-декодере или изучите сырую транзакцию в декодере транзакций Ethereum.