Предкомпилированные контракты (precompiles) в Ethereum — это набор «встроенных» контрактов по фиксированным адресам, которые выполняются не байткодом EVM, а нативной реализацией в клиенте. Их задача — выполнять тяжёлые операции (обычно криптографические) намного дешевле и быстрее, чем если бы их реализовали как обычный смарт-контракт.
Precompiles:
- вызываются через CALL / STATICCALL как обычные контракты;
- живут по заранее зарезервированным адресам (0x01, 0x02, …);
- имеют чётко заданную формулу газа и поведение, описанное в спеках.
По сути, это «escape hatch» EVM: то, что теоретически можно сделать опкодами, но было бы слишком медленно или дорого по газу.
Чем precompiles отличаются от обычных контрактов
С точки зрения EVM precompile выглядит как обычный контракт:
- ему передаётся calldata;
- он потребляет газ;
- возвращает return data или вызывает ошибку.
Но есть важные отличия:
- у precompiles нет байткода в состоянии — логика зашита в реализацию клиента (geth, Nethermind, Besu и т.д.);
- код и газ-формулы определены в спецификации протокола и меняются только хардфорком;
- адреса фиксированы и одинаковы для всех сетей, которые следуют Ethereum Mainnet-spec.
Это промежуточный уровень между:
- опкодами (опкоды EVM) — очень примитивные операции;
- обычными контрактами — произвольная логика на байткоде.
Precompiles позволяют встроить сложную криптографию или спец-функции, не увеличивая набор опкодов и не добавляя новый байткод в состояние.
Список precompiles в Ethereum (Mainnet)
На Ethereum Mainnet (после Byzantium, Istanbul и Cancun/Dencun) определены следующие precompiles по низким адресам:
- 0x01 — ecRecover
Восстановление публичного ключа (и адреса) по ECDSA-подписи. Используется, например, в ecrecover(...) в Solidity.
- 0x02 — SHA2-256
Вычисление SHA-256 от входных данных (стандартный SHA-2, в отличие от Keccak-256).
- 0x03 — RIPEMD-160
Криптографический хеш-функция RIPEMD-160.
- 0x04 — identity
Тривиальная функция «как есть»: возвращает то же, что получила. Полезна как базовая примитивная операция над данными.
- 0x05 — modexp (модульная экспонентация)
Добавлен хардфорком Byzantium. Выполняет дорогую операцию base^exponent mod modulus c газом, зависящим от размеров аргументов.
- 0x06, 0x07, 0x08 — операции на эллиптической кривой alt_bn128 (EIP-196/197):
- 0x06 — ecAdd
- 0x07 — ecMul
- 0x08 — ecPairing
Активно используются в zk-SNARK-схемах и протоколах, которым нужны парные проверки.
- 0x09 — BLAKE2 F precompile (EIP-152, Istanbul)
Реализует компрессионную функцию F для BLAKE2b — помогает протоколам и проектам, где BLAKE2 основная хеш-функция.
- 0x0A — KZG point evaluation precompile (Cancun/Dencun, EIP-4844)
Нужен для верификации KZG-коммитментов в рамках протоданкшардинга и блоб-данных (данных L2). Без него rollup’ам приходилось бы использовать гораздо более дорогие по газу схемы.
Важно: этот набор относится именно к Ethereum Mainnet после Dencun. Другие EVM-совместимые сети (L2, sidechain’ы) могут:
- поддерживать тот же набор;
- добавлять дополнительные precompiles;
- реализовывать «system contracts» или «predeploys» с похожими целями, но в другой форме.
Как вызываются precompiles и как считается газ
Вызов precompile на уровне EVM ничем не отличается от обычного контракта:
- используется опкод CALL или STATICCALL;
- указывается адрес от 0x01 до 0x0A;
- передаётся calldata и лимит газа.
Дальше клиент:
- смотрит, что адрес относится к precompile;
- применяет описанную в спецификации функцию;
- снимает газ по формуле, зависящей от размера и содержимого входных данных;
- возвращает результат как return data.
Особенности:
- газ-формула для каждой precompile задаётся в соответствующем EIP и, как правило, масштабируется с размером входа;
- некоторые precompiles исторически «дешевели» (например, alt_bn128 в EIP-1108), чтобы сделать zk-примитивы доступнее;
- если газа не хватило, результатом будет Out-of-Gas аналогично обычному контракту.
Зачем разработчику знать про precompiles
Понимание precompiles полезно в нескольких сценариях:
- Криптография и zk-примитивы
Если протокол требует сложных криптоопераций (подписи, zk-доказательства, коммитменты), зачастую выгоднее опираться на уже существующие precompiles, а не реализовывать всё в «чистом» EVM.
- Оптимизация газа
Операции через precompiles почти всегда дешевле, чем ту же математику описывать на байткоде — меньше опкодов, меньше рисков ошибиться с безопасностью, предсказуемые газ-формулы.
- Кросс-чейн и L2-совместимость
Многие L2-решения позиционируют себя как «полностью EVM-эквивалентные», что включает не только опкоды, но и поддержку precompiles. При проектировании протокола стоит понимать, на какие precompiles вы завязаны (это влияет на переносимость и поддержку в других сетях).
