Часть III · Глава 15 из 43 · Constantinople

EIP-1052: снять отпечаток контракта одним опкодом

Чтобы проверить, выполняет ли другой адрес именно тот байткод, который вы ожидаете, раньше приходилось копировать весь его код в память и хешировать его самостоятельно — операция O(размер кода) только ради 32-байтного отпечатка. EIP-1052 добавляет EXTCODEHASH, который возвращает этот хеш напрямую, за константное время.

Обновлено 2 июл. 2026 г. · 7 мин
Предполагается
  • аккаунты и код (EXTCODECOPY)
  • хеширование keccak256

Constantinople, февраль 2019. Контракту часто нужно знать, из чего сделан другой аккаунт. Это адрес контракта или обычного кошелька? Выполняет ли он ровно тот байткод, который я аудировал, или что-то незнакомое? Самый чистый способ ответить — с помощью отпечатка: хеша кода аккаунта, который можно сравнить с известным значением. EVM уже умела хешировать и уже умела читать код чужих аккаунтов, но не было способа получить этот отпечаток дёшево: приходилось тащить весь код в память и хешировать его самостоятельно. EIP-1052 добавляет тот единственный опкод, который пропускает эту перевозку. Давайте выведем его.

1 шаг Скопировать, затем хешировать

Проблема: чтобы захешировать код, сначала приходилось копировать его целиком

До EIP-1052 инструментами EVM для изучения кода чужого аккаунта были EXTCODESIZE Возвращает длину в байтах кода по данному адресу. Полезно, но длина — это не идентичность: два разных контракта могут иметь одинаковый размер. (его длина) и EXTCODECOPY Копирует диапазон кода другого аккаунта в память вызывающего. Чтобы получить отпечаток кода, приходилось скопировать его целиком, а затем захешировать копию — стоимость пропорциональна размеру кода, плюс газ на расширение памяти. (его байты). Ни один из них не даёт отпечаток напрямую. Так что для получения keccak256 кода контракта — того, что вам на самом деле нужно для проверки идентичности, — приходилось делать EXTCODECOPY всего кода в собственную память, а затем запускать KECCAK256 над ним. Стоимость масштабируется с размером кода и сверху добавляет газ на расширение памяти — всё ради единственного 32-байтного значения. Для крупного контракта это большая работа ради простого сравнения.

нужно: 32-байтный отпечаток кода другого контракта код другого контракта (может быть огромным) EXTCODECOPY скопировать всё → память KECCAK256 32-байтный хеш O(размер кода) + память лишь чтобы получить 32 байта дорого и расточительно для простой проверки идентичности
До EIP-1052 снятие отпечатка с кода другого контракта означало EXTCODECOPY всего кода в память и последующий KECCAK256 копии — стоимость пропорциональна размеру кода плюс расширение памяти, и всё ради 32-байтной идентичности. Дорого и расточительно ради простой проверки.

→ Шаг 2: раскрываем хеш кода отдельным опкодом.

2 шаг Добавляем EXTCODEHASH

EIP-1052: EXTCODEHASH возвращает хеш напрямую

Исправление добавляет EXTCODEHASH Опкод 0x3f. Получив адрес, возвращает keccak256 кода этого аккаунта за константное время — без копирования. Узел может отдать его напрямую, поскольку хеш кода — часть хранимого представления аккаунта. (0x3f): дайте ему адрес, получите обратно keccak256 кода этого аккаунта одной инструкцией за константное время — без копирования, без расширения памяти. Но с ним идут острые углы, которые нужно учитывать, и все они об отсутствии кода. non-existent account Адрес, к которому никогда не прикасались, — ни баланса, ни nonce, ни кода. EXTCODEHASH возвращает для него 0, отличая «здесь ничего нет» от «есть, но без кода». (несуществующий аккаунт) возвращает 0. Аккаунт, который существует, но не имеет кода, — обычный EOA или контракт в процессе конструирования — возвращает empty-code hash keccak256 пустой байтовой строки (0xc5d2460186…) — хеш кода любого существующего аккаунта без развёрнутого кода. EXTCODEHASH возвращает его для EOA, и это отличается от 0, возвращаемого для несуществующих аккаунтов. (хеш пустого кода), keccak256(""). Два разных ответа «нет кода», и правильное использование опкода означает уметь их различать.

EXTCODEHASH(addr): хеш кода за один опкод addr keccak256(code) — O(1), без копирования несуществующий аккаунт → 0 существует, но без кода (EOA) → хеш пустой строки два случая «без кода» — легко перепутать
EXTCODEHASH(addr) возвращает keccak256 кода аккаунта одним опкодом за константное время — без копирования. Острые углы: несуществующий аккаунт возвращает 0, а существующий аккаунт без кода (EOA) возвращает хеш пустой строки. Два случая «нет кода», которые нужно аккуратно различать.

→ Шаг 3: что открывает дешёвый отпечаток.

3 шаг Дешёвые проверки идентичности

Выигрыш: проверка того, с кем вы разговариваете

Хеш кода за константное время делает практичным целое семейство проверок. Контракт может подтвердить, что контрагент выполняет ровно тот заведомо безопасный байткод, который он ожидает, — прежде чем ему довериться. Он может отличить контракты от EOA (с учётом оговорок про пустой код и конструктор). И это естественно сочетается с CREATE2: развернув контракт по детерминированному адресу, можно вызвать EXTCODEHASH, чтобы подтвердить, что развёрнутый код — именно тот, что задумывался, — реальная проверка безопасности для фабрик и паттернов обновления. То, что раньше было операцией «скопировать и захешировать» за O(размер кода), теперь — один опкод за O(1), достаточно дешёвый, чтобы делать его прямо на горячем пути.

дешёвые проверки идентичности кода тот ли контрагент — известный безопасный байткод? контракт или EOA? (учти пустой код и стадию создания) проверка, что CREATE2-деплой соответствует ожидаемому коду операция O(размер кода) становится O(1)
EXTCODEHASH делает проверки идентичности кода дешёвыми: тот ли контрагент, что и заведомо безопасный байткод? контракт это или EOA? совпадает ли развёртывание через CREATE2 с ожидаемым кодом? Операция «скопировать и захешировать» за O(размер кода) становится опкодом за O(1), который можно позволить себе на горячем пути.
04 Глубже Куда двигаться дальше