ERC 4337: абстракция адресов (AA) без изменения протокола Ethereum

ERC 4337: абстракция адресов (AA) без изменения протокола Ethereum

@Ghost_In_The_Block

Сообщество разработчиков Ethereum уже давно мечтает об aбстракции адресов (AA - account abstraction).

Вместо того, чтобы использовать код EVM только для реализации логики приложений, его можно было бы использовать и для реализации логики проверки (элемент nonce, подписи...) кошельков отдельных пользователей.

Это открыло бы новые возможности для творческих решений в вопросах разработки кошельков, что в свою очередь открывает некоторые важные функции:
  • Мульти-подписи и social recovery кошельки
  • Более эффективные и простые алгоритмы подписи (например, Schnorr, BLS)
  • Пост-квантовые безопасные алгоритмы подписи (например, Lamport, Winternitz).
  • Возможность модернизации

Сегодня все это можно сделать с помощью смарт-контракт кошельков, но тот факт, что сам протокол Ethereum требует, чтобы все операции были упакованы в транзакцию, исходящую от защищенного внешнего адреса (EOA) = делает реализацию очень сложной.

Каждая операция пользователя должна быть “обернута” транзакцией от EOA, что увеличивает дополнительные расходы за проведение транзакции (gas) на 21000.

Пользователю нужно либо иметь ETH в отдельном EOA для оплаты” газа” и управлять балансами на двух счетах, либо полагаться на систему ретрансляции, которая обычно является централизованной.


EIP 2938 - это один из путей исправления ситуации, предусматривающий внесение некоторых изменений в протокол Ethereum, которые позволят транзакциям верхнего уровня Ethereum начинаться с контракта, а не с EOA.

Сам контракт будет содержать логику проверки и выплаты вознаграждения, которую будут проверять майнеры.

Однако это требует значительных изменений протокола, а [на данный момент] разработчики протокола приоритезируют вопросы слияния и масштабируемости.


В нашем новом предложении (ERC 4337), мы предлагаем способ достижения тех же преимуществ без изменений протокола на уровне консенсуса.

Как работает это предложение?

Вместо того, чтобы изменять логику самого уровня консенсуса, мы воспроизводим функциональность мемпула транзакций в системе более высокого уровня.

Пользователи посылают объекты UserOperation, которые “упаковывают” намерения пользователя вместе с подписями и другими данными для проверки.

Майнеры или бандлеры, использующие такие сервисы, как Flashbots, могут упаковать набор объектов UserOperation в одну "пакетную транзакцию", которая затем включается в блок Ethereum.



Бандлер оплачивает комиссию за перевод пакета в ETH и получает компенсацию в виде комиссий, выплачиваемых в рамках выполнения всех отдельных UserOperation.

Бандлеры будут выбирать, какие объекты UserOperation включить в транзакцию, основываясь на логике приоритетов оплаты, схожей с тем, как майнеры работают в существующем мемпуле транзакций.

UserOperation выглядит как транзакция; это ABI-кодированная структура, включающая такие поля, как:
  • Отправитель: кошелек, выполняющий операцию
  • Элемент nonce и signature: параметры, передаваемые в функцию проверки кошелька, чтобы кошелек мог проверить операцию
  • initCode: код инициации для создания кошелька, если кошелек еще не существует
  • callData: данные для вызова кошелька на этапе выполнения операции

Остальные поля ответственны за управление “газом” и комиссиями; полный список полей можно найти в спецификации ERC 4337.


Кошелек - это смарт-контракт, который должен иметь две функции:
  • validateUserOp, которая принимает UserOperation в качестве входных данных:

Эта функция должна верифицировать подпись и элемент nonce в UserOperation, выплатить вознаграждение и увеличить nonce, если проверка прошла успешно, или выдать исключение, если проверка не прошла.

  • Функция выполнения операций, которая интерпретирует calldata как инструкцию для кошелька, чтобы тот начал выполнение действий.

Как эта функция интерпретирует calldata и что она делает в результате - вопрос совершенно открытый, но мы ожидаем, что наиболее распространенным поведением будет разбор calldata как инструкции для кошелька выполнить один или несколько вызовов.

Чтобы упростить логику работы кошелька, большая часть сложной магии смарт-контракта, необходимая для обеспечения безопасности, выполняется не в самом кошельке, а в глобальном контракте, называемом точкой входа.

Предполагается, что функции validateUserOp и функции выполнения будут закрыты с помощью require(msg.sender == ENTRY_POINT), поэтому только доверенная точка входа может заставить кошелек выполнять какие-либо действия или платить комиссию.

Точка входа делает произвольный вызов кошелька только после того, как validateUserOp с UserOperation, несущей эти calldata, уже завершился успешно, поэтому этого достаточно для защиты кошельков от атак.

Точка входа также отвечает за создание кошелька с помощью предоставленного initCode, если кошелек еще не существует.



Схема управления точкой входа при выполнении handleOps

Существуют некоторые ограничения, которые узлы mempool и бандлеры должны соблюдать в отношении того, что может делать validateUserOp:

В частности, выполнение validateUserOp:

  1. Не может считывать или записывать данные из хранилища других контрактов.
  2. Не может использовать опкоды среды, такие как TIMESTAMP.
  3. Не может вызывать другие контракты, если только эти контракты [верифицированно] не способны к самоуничтожению.

Это необходимо для того, чтобы симулированное выполнение validateUserOp, используемое бандлерами и узлами мемпула UserOperation для проверки того, что данную UserOperation можно включить или переслать, имело тот же эффект, как если бы она действительно была бы включена в будущий блок.

Если проверка UserOperation была смоделирована успешно, UserOperation гарантированно будет доступна к включению = до тех пор, пока на счете отправителя не произойдет какое-либо другое изменение внутреннего состояния

Из-за другой UserOperation с тем же отправителем или другого контракта, вызывающего отправителя;

Однако, в любом случае, для запуска этого условия для одного счета требуется потратить 7500+ “газа” в блокчейне.

Кроме того, UserOperation указывает лимит “газа” для шага validateUserOp, и узлы mempool и бандлеры будут отклонять его, если этот лимит газа очень мал (например, менее 200000).

Эти ограничения обладают ключевыми свойствами существующих транзакций Ethereum, которые защищают mempool от DoS-атак.

Бандлеры и ноды mempool могут использовать логику, аналогичную актуальной логике обработки транзакций Ethereum, чтобы определить, стоит ли включать или пересылать UserOperation или нет.



Сохраняемые свойства:
  • Нет централизованных участников; все делается через пир-ту-пир (peer-to-peer) мемпул
  • DoS-безопасность (UserOperation, которая успешно прошла смоделированную проверку, гарантированно будет доступна к включению:

До тех пор, пока на счете отправителя не произойдет какое-либо другое изменение внутреннего состояния, что потребует от злоумышленника 7500+ “газа” за каждого отправителя.

  • Простой процесс создания кошелька на стороне пользователя

Пользователям не нужно думать о том, был ли контракт их кошелька "уже опубликован"; кошельки существуют по детерминированным адресам CREATE2, и если кошелек еще не существует, первая UserOperation создает его автоматически

  • Полная поддержка EIP 1559:

Включая простоту установки платы = пользователи могут установить фиксированную оплату премии и высокую максимальную общую плату и ожидать, что их быстро включат в систему и справедливо возьмут плату.

  • Возможность замены оплаты, отправка новой UserOperation со значительно более высокой премией, чем у предыдущей [чтобы заменить операцию или быстрее включить ее в список].
Новые преимущества:
  • Гибкость логики верификации: функция validateUserOp может добавлять произвольную логику верификации подписей и элемента nonce (новые схемы подписи, мультиподпись..).
  • Достаточная технологичность, чтобы сделать уровень исполнения квантово-безопасным: если это предложение будет в целом принято, то для обеспечения квантовой безопасности не потребуется дальнейшей работы над уровнем исполнения.

Пользователи могут в индивидуальном порядке обновить свои кошельки до квантово-безопасных. Даже обёрнутые транзакции (wrapper transaction) = безопасны, так как майнер может использовать новые свежесозданные и, следовательно, защищенный хэшем EOA для каждой обёрнутой транзакции и не публиковать транзакцию до ее добавления в блок.

  • Возможность обновления кошелька: логика проверки кошелька может быть изменяемой, поэтому кошельки могут менять свои открытые ключи или (если они публикуются с помощью DELEGATECALL) полностью обновлять свой код.
  • Гибкость логики выполнения: кошельки могут добавлять пользовательскую логику на этапе выполнения, например, выполнять атомарные мультиоперации (ключевая цель EIP 3074).
Слабые стороны:
  • Немного повышенная DoS-уязвимость, несмотря на все усилия протокола, просто потому, что логика проверки может быть несколько сложнее, чем статус-кво одной проверки ECDSA.
  • Увеличение расходов “газа”: несколько большие расходы “газа” по сравнению с обычными транзакциями (хотя в некоторых случаях это компенсируется поддержкой нескольких операций).
  • Одна транзакция за раз: учетные записи не могут выстраивать очередь и отправлять несколько транзакций в mempool.

Однако возможность выполнять атомарные мультиоперации делает этот функционал гораздо менее необходимым.


Спонсируемые транзакции имеют множество ключевых сценариев использования.

Наиболее часто упоминаются следующие желаемые сценарии использования:
  1. Предоставление разработчикам приложений возможности оплачивать комиссии от имени своих пользователей
  2. Предоставление пользователям возможности оплачивать взносы в токенах ERC20, при этом контракт выступает в качестве посредника для сбора ERC20 и оплаты в ETH.

Данное предложение может поддерживать эту функциональность с помощью встроенного механизма paymaster.

UserOperation может установить другой адрес в качестве своего paymaster.

Если paymaster установлен (т.е. ненулевой), то во время шага верификации точка входа также вызывает paymaster, чтобы проверить, готов ли он заплатить за UserOperation.

Если он готов, то плата взимается не с кошелька, а с ETH, размещенных в точке входа [с задержкой вывода для безопасности].

На этапе выполнения кошелек вызывается с помощью calldata в UserOperation как обычно, но после этого - paymaster вызывается с помощью postOp.

Примерами рабочих процессов для двух вышеуказанных случаев использования являются:
  • Paymaster проверяет, содержит ли paymasterData подпись от спонсора, подтверждающую, что спонсор готов заплатить за UserOperation.

Если подпись действительна, paymaster принимает предложение, и плата за UserOperation выплачивается из ставки спонсора.

  • Paymaster проверяет, достаточно ли на кошельке отправителя средств ERC20 для оплаты UserOperation.

Если достаточно, paymaster принимает и оплачивает комиссию в ETH, а затем требует токены ERC20 в качестве компенсации в postOp

Следует учитывать, что, если postOp провалится из-за того, что UserOperation истощила баланс ERC20, выполнение отменяется и postOp вызывается снова, так что paymaster всегда получает деньги.

Обратите внимание, что [пока] это можно сделать только в том случае, если ERC20 - это wrapper-token, управляемый самим paymaster.

Также имейте ввиду, что во втором случае paymaster может быть неактивен, возможно, за исключением периодической ребалансировки и переустановки параметров.

Это радикальное улучшение по сравнению с существующими попытками реализации спонсорства, которые требовали, чтобы paymaster был постоянно онлайн для активного “обертывания” отдельных транзакций.



С проектом ERC 4337 можно ознакомиться здесь.

Реализация находится в процессе - смотрите здесь.

В ближайшее время ожидается появление альфа-версии для разработчиков, после чего следующим шагом станет уточнение окончательных деталей и проведение аудита для подтверждения безопасности схемы.

Мы ожидаем, что совсем скоро разработчики смогут начать экспериментировать с абстрагированными адресами.


Напоминаем, что оригинал находится здесь.

Переведено и адаптировано командой Telegram-канала

@Ghost_In_The_Block


Report Page