Перейти к основному содержимому
БлокчейнMar 28, 2026

EIP-7702 на практике: создание потоков смарт-аккаунтов после Pectra

OS
Open Soft Team

Engineering Team

Что обеспечивает EIP-7702

EIP-7702, активированный с обновлением Ethereum Pectra в марте 2025 года, вводит новый тип транзакции, позволяющий любому внешнему аккаунту (EOA) установить указатель делегирования — ссылку на смарт-контракт, код которого EOA временно принимает на время транзакции. Это означает, что ваш существующий адрес кошелька MetaMask может выполнять произвольную логику смарт-контракта (пакетные вызовы, пользовательская валидация, спонсирование газа) без развёртывания нового контрактного кошелька или смены адреса.

Это самое значительное улучшение UX в истории Ethereum. Пользователям больше не нужно выбирать между простотой EOA и возможностями смарт-аккаунта.

EIP-7702 vs ERC-4337: когда использовать что

Оба стандарта обеспечивают абстракцию аккаунтов, но работают на разных уровнях и подходят для разных случаев:

ПараметрEIP-7702ERC-4337
УровеньПротокольный (новый тип tx)Прикладной (смарт-контракт)
Тип аккаунтаОбновляет существующие EOAТребует нового контрактного кошелька
АдресСохраняет существующий адрес EOAНовый адрес (контрфактический)
ПостоянствоДелегация на транзакциюПостоянный смарт-контракт
Требуется бандлерНет (стандартный поток tx)Да (отдельный мемпул)
Расход газа~20 000 газа на делегацию~42 000 газа на валидацию UserOp
Поддержка кошельковMetaMask, Coinbase Wallet, RainbowСпециализированные (Safe, ZeroDev, Biconomy)
Лучше дляОбновления существующих пользователейНовых пользователей, сложной логики аккаунтов

Фреймворк принятия решений

Используйте EIP-7702, когда:

  • Ваши пользователи уже имеют EOA-кошельки (MetaMask, Coinbase Wallet)
  • Вам нужны пакетные транзакции или спонсирование газа
  • Вы хотите минимальную сложность интеграции
  • Логика смарт-аккаунта нужна на транзакцию (не постоянно)

Используйте ERC-4337, когда:

  • Вы создаёте новый кошелёк или онбордите новых пользователей
  • Вам нужна постоянная логика аккаунта (постоянный мультисиг, сложное восстановление)
  • Вы хотите, чтобы аккаунт был смарт-контрактом по умолчанию
  • Вам нужны продвинутые функции: модули аккаунта, плагины, гарантии

Используйте оба вместе, когда:

  • Вы хотите ERC-4337 смарт-аккаунты, которые также могут обрабатывать EIP-7702 делегации от EOA (для обратной совместимости)

Примеры кода

Пакетные транзакции

Самый распространённый сценарий использования EIP-7702: выполнение нескольких операций в одной транзакции. Больше никаких двухшаговых потоков “approve, затем swap”.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

/// @title BatchExecutor — цель делегации EIP-7702 для пакетных вызовов
/// @notice EOA делегирует этому контракту для атомарного выполнения множественных вызовов
contract BatchExecutor {
    struct Call {
        address target;
        uint256 value;
        bytes data;
    }
    
    /// @notice Выполнить пакет вызовов от делегирующего EOA
    /// @dev При вызове через EIP-7702, msg.sender — сам EOA
    /// @param calls Массив вызовов для выполнения
    function executeBatch(Call[] calldata calls) external payable {
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory result) = calls[i].target.call{
                value: calls[i].value
            }(calls[i].data);
            
            if (!success) {
                // Прокинуть причину отката
                assembly {
                    revert(add(result, 32), mload(result))
                }
            }
        }
    }
}

Использование на клиенте с ethers.js v6:

import { ethers } from "ethers";

// Тип транзакции EIP-7702 (type: 4)
const batchTx = {
    type: 4,
    to: userAddress, // EOA делегирует самому себе
    authorizationList: [{
        chainId: 1,
        address: BATCH_EXECUTOR_ADDRESS, // цель делегации
        nonce: await provider.getTransactionCount(userAddress),
        // Подписано владельцем EOA:
        yParity: 0, r: "0x...", s: "0x..."
    }],
    data: batchExecutorInterface.encodeFunctionData("executeBatch", [[
        {
            target: USDC_ADDRESS,
            value: 0,
            data: usdcInterface.encodeFunctionData("approve", [
                UNISWAP_ROUTER, ethers.parseUnits("1000", 6)
            ])
        },
        {
            target: UNISWAP_ROUTER,
            value: 0,
            data: routerInterface.encodeFunctionData("exactInputSingle", [{
                tokenIn: USDC_ADDRESS,
                tokenOut: WETH_ADDRESS,
                fee: 3000,
                recipient: userAddress,
                amountIn: ethers.parseUnits("1000", 6),
                amountOutMinimum: 0,
                sqrtPriceLimitX96: 0
            }])
        }
    ]])
};

const tx = await signer.sendTransaction(batchTx);

Спонсирование газа

С EIP-7702 спонсор (paymaster) может оплачивать газ для любой EOA-транзакции, отправляя транзакцию от имени пользователя, в то время как список авторизации пользователя делегирует выполнение:

/// @title SponsoredExecutor — спонсирование газа через EIP-7702
contract SponsoredExecutor {
    mapping(address => uint256) public nonces;
    
    /// @notice Выполнить вызов от имени пользователя, газ оплачивает msg.sender
    /// @param user EOA, подписавший авторизацию
    /// @param target Контракт для вызова
    /// @param data Calldata
    /// @param userNonce Nonce для защиты от повторного воспроизведения
    /// @param deadline Временная метка истечения
    /// @param signature EIP-712 подпись пользователя
    function sponsoredExecute(
        address user,
        address target,
        bytes calldata data,
        uint256 userNonce,
        uint256 deadline,
        bytes calldata signature
    ) external {
        require(block.timestamp <= deadline, "Expired");
        require(nonces[user] == userNonce, "Invalid nonce");
        nonces[user]++;
        
        // Верификация подписи пользователя (EIP-712)
        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);
        address signer = ECDSA.recover(digest, signature);
        require(signer == user, "Invalid signature");
        
        // Выполнение вызова как пользователь
        (bool success, bytes memory result) = target.call(data);
        require(success, "Call failed");
    }
}

Спонсор отправляет транзакцию type-4, оплачивая газ. Пользователь подписывает только EIP-712 сообщение, одобряющее конкретное действие — ETH в кошельке не требуется.

Социальное восстановление

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

/// @title RecoveryModule — социальное восстановление через EIP-7702
contract RecoveryModule {
    struct RecoveryConfig {
        address[] guardians;
        uint256 threshold;
        uint256 delay;
    }
    
    mapping(address => RecoveryConfig) public configs;
    mapping(bytes32 => uint256) public recoveryTimestamps;
    mapping(bytes32 => uint256) public approvalCounts;
    mapping(bytes32 => mapping(address => bool)) public hasApproved;
    
    /// @notice Регистрация хранителей восстановления (вызывается EOA через EIP-7702)
    function setupRecovery(
        address[] calldata guardians,
        uint256 threshold,
        uint256 delay
    ) external {
        require(guardians.length >= threshold, "Invalid threshold");
        require(threshold >= 2, "Min 2 guardians");
        configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);
    }
    
    /// @notice Хранитель одобряет запрос на восстановление
    function approveRecovery(
        address account,
        address newOwner
    ) external {
        RecoveryConfig memory config = configs[account];
        require(_isGuardian(config, msg.sender), "Not a guardian");
        
        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));
        require(!hasApproved[recoveryId][msg.sender], "Already approved");
        
        hasApproved[recoveryId][msg.sender] = true;
        approvalCounts[recoveryId]++;
        
        if (approvalCounts[recoveryId] >= config.threshold) {
            recoveryTimestamps[recoveryId] = block.timestamp + config.delay;
        }
    }
    
    /// @notice Выполнение восстановления после периода ожидания
    function executeRecovery(
        address account,
        address newOwner
    ) external {
        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));
        uint256 timestamp = recoveryTimestamps[recoveryId];
        require(timestamp > 0 && block.timestamp >= timestamp, "Not ready");
        
        // Передача контроля путём обновления цели делегации аккаунта
        // на контракт, управляемый newOwner
        // Реализация зависит от конкретной архитектуры кошелька
    }
}

Статус интеграции кошельков

По состоянию на март 2026 года поддержка EIP-7702 развёрнута в основных кошельках:

MetaMask

MetaMask добавил поддержку EIP-7702 в версии 12.4 (сентябрь 2025). Пользователи видят значок “Smart Transaction” при запросе dApp на транзакцию type-4. Кошелёк показывает:

  • Контракт — цель делегации (с верифицированным исходным кодом на Etherscan)
  • Каждый вызов в пакете с декодированными параметрами
  • Ожидаемую экономию газа по сравнению с отдельными транзакциями
  • Предупреждение, если цель делегации не верифицирована

Coinbase Wallet

Coinbase Wallet стал наиболее агрессивным последователем, интегрировав EIP-7702 в функцию “Smart Wallet” (запущена в ноябре 2025). Ключевые особенности:

  • Авто-батчинг — кошелёк автоматически объединяет последовательности approve+swap
  • Спонсирование газа — Coinbase спонсирует газ для транзакций с комиссией менее $1
  • DeFi в один клик — готовые цели делегации для типичных DeFi-операций

Rainbow, Rabby и другие

Rainbow добавил поддержку в январе 2026 года. Rabby поддерживает транзакции type-4, но не имеет UI визуализации пакетов. Frame (десктопный кошелёк) был одним из первых, кто поддержал EIP-7702, выпустив поддержку в апреле 2025 года.

Руководство по миграции: от EOA к смарт-аккаунтам

Для разработчиков dApp вот рекомендуемый путь миграции для поддержки EIP-7702:

Шаг 1: развёртывание целей делегации

Создайте и проведите аудит смарт-контрактов, которым ваши пользователи будут делегировать. Типичные паттерны:

BatchExecutor       — пакетирование мульти-вызовов
SessionKeyManager   — ограниченные по времени разрешения
SpendingLimiter     — дневные/недельные лимиты расходов
RecoveryModule      — настройка социального восстановления

Шаг 2: обновление фронтенда

Определите, поддерживает ли подключённый кошелёк EIP-7702:

async function supportsEIP7702(provider: ethers.Provider): Promise<boolean> {
    try {
        // Проверяем, поддерживает ли нода транзакции type-4
        const capabilities = await provider.send(
            "wallet_getCapabilities", []
        );
        return capabilities?.atomicBatch?.supported === true;
    } catch {
        return false;
    }
}

Шаг 3: реализация graceful degradation

Не все пользователи будут иметь кошельки с поддержкой EIP-7702. Ваш dApp должен определять возможности и делать фоллбэк:

async function executeSwap(tokenIn, tokenOut, amount) {
    if (await supportsEIP7702(provider)) {
        // Одна транзакция: approve + swap
        return executeBatchSwap(tokenIn, tokenOut, amount);
    } else {
        // Легаси: две отдельные транзакции
        await approve(tokenIn, ROUTER, amount);
        return swap(tokenIn, tokenOut, amount);
    }
}

Шаг 4: обновление отслеживания транзакций

Пакетные транзакции содержат несколько операций в одном tx hash. Обновите UI истории транзакций для парсинга и отображения каждой подоперации:

interface BatchOperation {
    target: string;
    method: string;
    params: Record<string, unknown>;
    status: "success" | "reverted";
}

// Парсинг пакетных операций из квитанции транзакции
function parseBatchOps(receipt: TransactionReceipt): BatchOperation[] {
    // Декодирование логов и внутренних вызовов из квитанции
    // ...
}

Соображения безопасности

EIP-7702 вводит новые поверхности атаки, которые разработчики должны понимать:

Верификация цели делегации

Контракт — цель делегации имеет полный контроль над активами EOA во время транзакции. Злонамеренная цель делегации может:

  • Перевести все ETH и токены из EOA
  • Установить неограниченные разрешения токенов на адреса атакующего
  • Взаимодействовать с DeFi-протоколами для вывода позиций

Защита: делегируйте только проаудированным, верифицированным контрактам. Кошельки должны поддерживать белый список доверенных целей делегации.

Защита от повторного воспроизведения

Списки авторизации EIP-7702 включают nonce для предотвращения атак повторного воспроизведения. Однако разработчики должны обеспечить:

  • Nonce авторизации совпадает с текущим nonce EOA
  • Каждая авторизация используется ровно один раз
  • Кросс-чейн повторное воспроизведение предотвращается включением chain ID

Фишинг через делегацию

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

Защита: кошельки должны чётко отображать, какому коду EOA делегирует, с верификацией исходного кода и оценкой риска.

Реентрантность в пакетном выполнении

Пакетные исполнители, использующие call в цикле, уязвимы к реентрантности, если одна из целей пакета вызывает обратно исполнитель. Используйте защиту от реентрантности или паттерн checks-effects-interactions:

// Используйте защиту от реентрантности на пакетном исполнителе
bool private locked;

modifier noReentrant() {
    require(!locked, "Reentrant");
    locked = true;
    _;
    locked = false;
}

function executeBatch(Call[] calldata calls) external payable noReentrant {
    // ...
}

Коллизии хранилища

Когда EOA делегирует контракту, код контракта выполняется в контексте хранилища EOA. Если две разные цели делегации используют одни и те же слоты хранилища для разных целей, может произойти повреждение данных.

Защита: используйте EIP-7201 (именованное хранилище) во всех целях делегации:

// Именованное хранилище EIP-7201
bytes32 constant STORAGE_SLOT = keccak256(
    abi.encode(uint256(keccak256("batch.executor.storage")) - 1)
) & ~bytes32(uint256(0xff));

Часто задаваемые вопросы

Меняет ли EIP-7702 адрес моего кошелька?

Нет. Ваш адрес EOA остаётся прежним. EIP-7702 временно наделяет ваш адрес возможностями смарт-контракта на время одной транзакции. После завершения транзакции ваш адрес возвращается к стандартному EOA.

Можно ли использовать EIP-7702 на L2?

Да. Все основные L2 (Arbitrum, Base, Optimism, zkSync) приняли EIP-7702 в рамках своих обновлений, эквивалентных Pectra. Формат транзакций и механика делегации идентичны.

Что произойдёт, если в цели делегации есть баг?

Ущерб ограничен одной транзакцией. В отличие от постоянного контрактного кошелька, делегация EIP-7702 истекает после завершения транзакции. Однако в рамках этой транзакции цель делегации имеет полный доступ к активам EOA — баг может опустошить аккаунт.

Совместим ли EIP-7702 с аппаратными кошельками?

Да. Аппаратные кошельки (Ledger, Trezor) могут подписывать транзакции type-4, включая список авторизации. Ledger добавил поддержку в прошивке версии 2.3.0 (декабрь 2025). Пользователь подтверждает цель делегации на экране аппаратного устройства.

Сколько газа экономит EIP-7702?

Для типичного потока approve+swap EIP-7702 экономит примерно 40-50% на газе за счёт устранения накладных расходов второй транзакции (21 000 базового газа) и более эффективного кодирования calldata. Для сложных многошаговых DeFi-операций (например, zap в хранилище) экономия может достигать 60-70%.