[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-eip-7702-na-praktike-sozdanie-potokov-smart-akkauntov-posle-pectra":3},{"article":4,"author":55},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":34,"related_articles":35},"dd000000-0000-0000-0000-000000000013","a0000000-0000-0000-0000-000000000012","EIP-7702 на практике: создание потоков смарт-аккаунтов после Pectra","eip-7702-na-praktike-sozdanie-potokov-smart-akkauntov-posle-pectra","EIP-7702 позволяет любому EOA Ethereum временно действовать как смарт-контракт в рамках одной транзакции. Вот как реализовать пакетные транзакции, спонсирование газа и социальное восстановление с помощью нового примитива абстракции аккаунтов.","## Что обеспечивает EIP-7702\n\nEIP-7702, активированный с обновлением Ethereum Pectra в марте 2025 года, вводит новый тип транзакции, позволяющий любому внешнему аккаунту (EOA) установить **указатель делегирования** — ссылку на смарт-контракт, код которого EOA временно принимает на время транзакции. Это означает, что ваш существующий адрес кошелька MetaMask может выполнять произвольную логику смарт-контракта (пакетные вызовы, пользовательская валидация, спонсирование газа) без развёртывания нового контрактного кошелька или смены адреса.\n\nЭто самое значительное улучшение UX в истории Ethereum. Пользователям больше не нужно выбирать между простотой EOA и возможностями смарт-аккаунта.\n\n## EIP-7702 vs ERC-4337: когда использовать что\n\nОба стандарта обеспечивают абстракцию аккаунтов, но работают на разных уровнях и подходят для разных случаев:\n\n| Параметр | EIP-7702 | ERC-4337 |\n|----------|----------|----------|\n| Уровень | Протокольный (новый тип tx) | Прикладной (смарт-контракт) |\n| Тип аккаунта | Обновляет существующие EOA | Требует нового контрактного кошелька |\n| Адрес | Сохраняет существующий адрес EOA | Новый адрес (контрфактический) |\n| Постоянство | Делегация на транзакцию | Постоянный смарт-контракт |\n| Требуется бандлер | Нет (стандартный поток tx) | Да (отдельный мемпул) |\n| Расход газа | ~20 000 газа на делегацию | ~42 000 газа на валидацию UserOp |\n| Поддержка кошельков | MetaMask, Coinbase Wallet, Rainbow | Специализированные (Safe, ZeroDev, Biconomy) |\n| Лучше для | Обновления существующих пользователей | Новых пользователей, сложной логики аккаунтов |\n\n### Фреймворк принятия решений\n\n**Используйте EIP-7702, когда:**\n- Ваши пользователи уже имеют EOA-кошельки (MetaMask, Coinbase Wallet)\n- Вам нужны пакетные транзакции или спонсирование газа\n- Вы хотите минимальную сложность интеграции\n- Логика смарт-аккаунта нужна на транзакцию (не постоянно)\n\n**Используйте ERC-4337, когда:**\n- Вы создаёте новый кошелёк или онбордите новых пользователей\n- Вам нужна постоянная логика аккаунта (постоянный мультисиг, сложное восстановление)\n- Вы хотите, чтобы аккаунт был смарт-контрактом по умолчанию\n- Вам нужны продвинутые функции: модули аккаунта, плагины, гарантии\n\n**Используйте оба вместе, когда:**\n- Вы хотите ERC-4337 смарт-аккаунты, которые также могут обрабатывать EIP-7702 делегации от EOA (для обратной совместимости)\n\n## Примеры кода\n\n### Пакетные транзакции\n\nСамый распространённый сценарий использования EIP-7702: выполнение нескольких операций в одной транзакции. Больше никаких двухшаговых потоков \"approve, затем swap\".\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\n\u002F\u002F\u002F @title BatchExecutor — цель делегации EIP-7702 для пакетных вызовов\n\u002F\u002F\u002F @notice EOA делегирует этому контракту для атомарного выполнения множественных вызовов\ncontract BatchExecutor {\n    struct Call {\n        address target;\n        uint256 value;\n        bytes data;\n    }\n    \n    \u002F\u002F\u002F @notice Выполнить пакет вызовов от делегирующего EOA\n    \u002F\u002F\u002F @dev При вызове через EIP-7702, msg.sender — сам EOA\n    \u002F\u002F\u002F @param calls Массив вызовов для выполнения\n    function executeBatch(Call[] calldata calls) external payable {\n        for (uint256 i = 0; i \u003C calls.length; i++) {\n            (bool success, bytes memory result) = calls[i].target.call{\n                value: calls[i].value\n            }(calls[i].data);\n            \n            if (!success) {\n                \u002F\u002F Прокинуть причину отката\n                assembly {\n                    revert(add(result, 32), mload(result))\n                }\n            }\n        }\n    }\n}\n```\n\nИспользование на клиенте с ethers.js v6:\n\n```typescript\nimport { ethers } from \"ethers\";\n\n\u002F\u002F Тип транзакции EIP-7702 (type: 4)\nconst batchTx = {\n    type: 4,\n    to: userAddress, \u002F\u002F EOA делегирует самому себе\n    authorizationList: [{\n        chainId: 1,\n        address: BATCH_EXECUTOR_ADDRESS, \u002F\u002F цель делегации\n        nonce: await provider.getTransactionCount(userAddress),\n        \u002F\u002F Подписано владельцем EOA:\n        yParity: 0, r: \"0x...\", s: \"0x...\"\n    }],\n    data: batchExecutorInterface.encodeFunctionData(\"executeBatch\", [[\n        {\n            target: USDC_ADDRESS,\n            value: 0,\n            data: usdcInterface.encodeFunctionData(\"approve\", [\n                UNISWAP_ROUTER, ethers.parseUnits(\"1000\", 6)\n            ])\n        },\n        {\n            target: UNISWAP_ROUTER,\n            value: 0,\n            data: routerInterface.encodeFunctionData(\"exactInputSingle\", [{\n                tokenIn: USDC_ADDRESS,\n                tokenOut: WETH_ADDRESS,\n                fee: 3000,\n                recipient: userAddress,\n                amountIn: ethers.parseUnits(\"1000\", 6),\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            }])\n        }\n    ]])\n};\n\nconst tx = await signer.sendTransaction(batchTx);\n```\n\n### Спонсирование газа\n\nС EIP-7702 спонсор (paymaster) может оплачивать газ для любой EOA-транзакции, отправляя транзакцию от имени пользователя, в то время как список авторизации пользователя делегирует выполнение:\n\n```solidity\n\u002F\u002F\u002F @title SponsoredExecutor — спонсирование газа через EIP-7702\ncontract SponsoredExecutor {\n    mapping(address => uint256) public nonces;\n    \n    \u002F\u002F\u002F @notice Выполнить вызов от имени пользователя, газ оплачивает msg.sender\n    \u002F\u002F\u002F @param user EOA, подписавший авторизацию\n    \u002F\u002F\u002F @param target Контракт для вызова\n    \u002F\u002F\u002F @param data Calldata\n    \u002F\u002F\u002F @param userNonce Nonce для защиты от повторного воспроизведения\n    \u002F\u002F\u002F @param deadline Временная метка истечения\n    \u002F\u002F\u002F @param signature EIP-712 подпись пользователя\n    function sponsoredExecute(\n        address user,\n        address target,\n        bytes calldata data,\n        uint256 userNonce,\n        uint256 deadline,\n        bytes calldata signature\n    ) external {\n        require(block.timestamp \u003C= deadline, \"Expired\");\n        require(nonces[user] == userNonce, \"Invalid nonce\");\n        nonces[user]++;\n        \n        \u002F\u002F Верификация подписи пользователя (EIP-712)\n        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);\n        address signer = ECDSA.recover(digest, signature);\n        require(signer == user, \"Invalid signature\");\n        \n        \u002F\u002F Выполнение вызова как пользователь\n        (bool success, bytes memory result) = target.call(data);\n        require(success, \"Call failed\");\n    }\n}\n```\n\nСпонсор отправляет транзакцию type-4, оплачивая газ. Пользователь подписывает только EIP-712 сообщение, одобряющее конкретное действие — ETH в кошельке не требуется.\n\n### Социальное восстановление\n\nEIP-7702 обеспечивает паттерны социального восстановления без необходимости постоянного контрактного кошелька:\n\n```solidity\n\u002F\u002F\u002F @title RecoveryModule — социальное восстановление через EIP-7702\ncontract RecoveryModule {\n    struct RecoveryConfig {\n        address[] guardians;\n        uint256 threshold;\n        uint256 delay;\n    }\n    \n    mapping(address => RecoveryConfig) public configs;\n    mapping(bytes32 => uint256) public recoveryTimestamps;\n    mapping(bytes32 => uint256) public approvalCounts;\n    mapping(bytes32 => mapping(address => bool)) public hasApproved;\n    \n    \u002F\u002F\u002F @notice Регистрация хранителей восстановления (вызывается EOA через EIP-7702)\n    function setupRecovery(\n        address[] calldata guardians,\n        uint256 threshold,\n        uint256 delay\n    ) external {\n        require(guardians.length >= threshold, \"Invalid threshold\");\n        require(threshold >= 2, \"Min 2 guardians\");\n        configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);\n    }\n    \n    \u002F\u002F\u002F @notice Хранитель одобряет запрос на восстановление\n    function approveRecovery(\n        address account,\n        address newOwner\n    ) external {\n        RecoveryConfig memory config = configs[account];\n        require(_isGuardian(config, msg.sender), \"Not a guardian\");\n        \n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        require(!hasApproved[recoveryId][msg.sender], \"Already approved\");\n        \n        hasApproved[recoveryId][msg.sender] = true;\n        approvalCounts[recoveryId]++;\n        \n        if (approvalCounts[recoveryId] >= config.threshold) {\n            recoveryTimestamps[recoveryId] = block.timestamp + config.delay;\n        }\n    }\n    \n    \u002F\u002F\u002F @notice Выполнение восстановления после периода ожидания\n    function executeRecovery(\n        address account,\n        address newOwner\n    ) external {\n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        uint256 timestamp = recoveryTimestamps[recoveryId];\n        require(timestamp > 0 && block.timestamp >= timestamp, \"Not ready\");\n        \n        \u002F\u002F Передача контроля путём обновления цели делегации аккаунта\n        \u002F\u002F на контракт, управляемый newOwner\n        \u002F\u002F Реализация зависит от конкретной архитектуры кошелька\n    }\n}\n```\n\n## Статус интеграции кошельков\n\nПо состоянию на март 2026 года поддержка EIP-7702 развёрнута в основных кошельках:\n\n### MetaMask\n\nMetaMask добавил поддержку EIP-7702 в версии 12.4 (сентябрь 2025). Пользователи видят значок \"Smart Transaction\" при запросе dApp на транзакцию type-4. Кошелёк показывает:\n- Контракт — цель делегации (с верифицированным исходным кодом на Etherscan)\n- Каждый вызов в пакете с декодированными параметрами\n- Ожидаемую экономию газа по сравнению с отдельными транзакциями\n- Предупреждение, если цель делегации не верифицирована\n\n### Coinbase Wallet\n\nCoinbase Wallet стал наиболее агрессивным последователем, интегрировав EIP-7702 в функцию \"Smart Wallet\" (запущена в ноябре 2025). Ключевые особенности:\n- **Авто-батчинг** — кошелёк автоматически объединяет последовательности approve+swap\n- **Спонсирование газа** — Coinbase спонсирует газ для транзакций с комиссией менее $1\n- **DeFi в один клик** — готовые цели делегации для типичных DeFi-операций\n\n### Rainbow, Rabby и другие\n\nRainbow добавил поддержку в январе 2026 года. Rabby поддерживает транзакции type-4, но не имеет UI визуализации пакетов. Frame (десктопный кошелёк) был одним из первых, кто поддержал EIP-7702, выпустив поддержку в апреле 2025 года.\n\n## Руководство по миграции: от EOA к смарт-аккаунтам\n\nДля разработчиков dApp вот рекомендуемый путь миграции для поддержки EIP-7702:\n\n### Шаг 1: развёртывание целей делегации\n\nСоздайте и проведите аудит смарт-контрактов, которым ваши пользователи будут делегировать. Типичные паттерны:\n\n```\nBatchExecutor       — пакетирование мульти-вызовов\nSessionKeyManager   — ограниченные по времени разрешения\nSpendingLimiter     — дневные\u002Fнедельные лимиты расходов\nRecoveryModule      — настройка социального восстановления\n```\n\n### Шаг 2: обновление фронтенда\n\nОпределите, поддерживает ли подключённый кошелёк EIP-7702:\n\n```typescript\nasync function supportsEIP7702(provider: ethers.Provider): Promise\u003Cboolean> {\n    try {\n        \u002F\u002F Проверяем, поддерживает ли нода транзакции type-4\n        const capabilities = await provider.send(\n            \"wallet_getCapabilities\", []\n        );\n        return capabilities?.atomicBatch?.supported === true;\n    } catch {\n        return false;\n    }\n}\n```\n\n### Шаг 3: реализация graceful degradation\n\nНе все пользователи будут иметь кошельки с поддержкой EIP-7702. Ваш dApp должен определять возможности и делать фоллбэк:\n\n```typescript\nasync function executeSwap(tokenIn, tokenOut, amount) {\n    if (await supportsEIP7702(provider)) {\n        \u002F\u002F Одна транзакция: approve + swap\n        return executeBatchSwap(tokenIn, tokenOut, amount);\n    } else {\n        \u002F\u002F Легаси: две отдельные транзакции\n        await approve(tokenIn, ROUTER, amount);\n        return swap(tokenIn, tokenOut, amount);\n    }\n}\n```\n\n### Шаг 4: обновление отслеживания транзакций\n\nПакетные транзакции содержат несколько операций в одном tx hash. Обновите UI истории транзакций для парсинга и отображения каждой подоперации:\n\n```typescript\ninterface BatchOperation {\n    target: string;\n    method: string;\n    params: Record\u003Cstring, unknown>;\n    status: \"success\" | \"reverted\";\n}\n\n\u002F\u002F Парсинг пакетных операций из квитанции транзакции\nfunction parseBatchOps(receipt: TransactionReceipt): BatchOperation[] {\n    \u002F\u002F Декодирование логов и внутренних вызовов из квитанции\n    \u002F\u002F ...\n}\n```\n\n## Соображения безопасности\n\nEIP-7702 вводит новые поверхности атаки, которые разработчики должны понимать:\n\n### Верификация цели делегации\n\nКонтракт — цель делегации имеет **полный контроль** над активами EOA во время транзакции. Злонамеренная цель делегации может:\n- Перевести все ETH и токены из EOA\n- Установить неограниченные разрешения токенов на адреса атакующего\n- Взаимодействовать с DeFi-протоколами для вывода позиций\n\n**Защита:** делегируйте только проаудированным, верифицированным контрактам. Кошельки должны поддерживать белый список доверенных целей делегации.\n\n### Защита от повторного воспроизведения\n\nСписки авторизации EIP-7702 включают nonce для предотвращения атак повторного воспроизведения. Однако разработчики должны обеспечить:\n- Nonce авторизации совпадает с текущим nonce EOA\n- Каждая авторизация используется ровно один раз\n- Кросс-чейн повторное воспроизведение предотвращается включением chain ID\n\n### Фишинг через делегацию\n\nАтакующие могут обманом заставить пользователей подписать списки авторизации, делегирующие злонамеренным контрактам. Это аналогично существующей проблеме фишинга через \"approve\", но потенциально более опасно, поскольку делегация предоставляет более широкий доступ.\n\n**Защита:** кошельки должны чётко отображать, какому коду EOA делегирует, с верификацией исходного кода и оценкой риска.\n\n### Реентрантность в пакетном выполнении\n\nПакетные исполнители, использующие `call` в цикле, уязвимы к реентрантности, если одна из целей пакета вызывает обратно исполнитель. Используйте защиту от реентрантности или паттерн checks-effects-interactions:\n\n```solidity\n\u002F\u002F Используйте защиту от реентрантности на пакетном исполнителе\nbool private locked;\n\nmodifier noReentrant() {\n    require(!locked, \"Reentrant\");\n    locked = true;\n    _;\n    locked = false;\n}\n\nfunction executeBatch(Call[] calldata calls) external payable noReentrant {\n    \u002F\u002F ...\n}\n```\n\n### Коллизии хранилища\n\nКогда EOA делегирует контракту, код контракта выполняется в контексте хранилища EOA. Если две разные цели делегации используют одни и те же слоты хранилища для разных целей, может произойти повреждение данных.\n\n**Защита:** используйте EIP-7201 (именованное хранилище) во всех целях делегации:\n\n```solidity\n\u002F\u002F Именованное хранилище EIP-7201\nbytes32 constant STORAGE_SLOT = keccak256(\n    abi.encode(uint256(keccak256(\"batch.executor.storage\")) - 1)\n) & ~bytes32(uint256(0xff));\n```\n\n## Часто задаваемые вопросы\n\n### Меняет ли EIP-7702 адрес моего кошелька?\n\nНет. Ваш адрес EOA остаётся прежним. EIP-7702 временно наделяет ваш адрес возможностями смарт-контракта на время одной транзакции. После завершения транзакции ваш адрес возвращается к стандартному EOA.\n\n### Можно ли использовать EIP-7702 на L2?\n\nДа. Все основные L2 (Arbitrum, Base, Optimism, zkSync) приняли EIP-7702 в рамках своих обновлений, эквивалентных Pectra. Формат транзакций и механика делегации идентичны.\n\n### Что произойдёт, если в цели делегации есть баг?\n\nУщерб ограничен одной транзакцией. В отличие от постоянного контрактного кошелька, делегация EIP-7702 истекает после завершения транзакции. Однако в рамках этой транзакции цель делегации имеет полный доступ к активам EOA — баг может опустошить аккаунт.\n\n### Совместим ли EIP-7702 с аппаратными кошельками?\n\nДа. Аппаратные кошельки (Ledger, Trezor) могут подписывать транзакции type-4, включая список авторизации. Ledger добавил поддержку в прошивке версии 2.3.0 (декабрь 2025). Пользователь подтверждает цель делегации на экране аппаратного устройства.\n\n### Сколько газа экономит EIP-7702?\n\nДля типичного потока approve+swap EIP-7702 экономит примерно **40-50%** на газе за счёт устранения накладных расходов второй транзакции (21 000 базового газа) и более эффективного кодирования calldata. Для сложных многошаговых DeFi-операций (например, zap в хранилище) экономия может достигать 60-70%.","\u003Ch2 id=\"eip-7702\">Что обеспечивает EIP-7702\u003C\u002Fh2>\n\u003Cp>EIP-7702, активированный с обновлением Ethereum Pectra в марте 2025 года, вводит новый тип транзакции, позволяющий любому внешнему аккаунту (EOA) установить \u003Cstrong>указатель делегирования\u003C\u002Fstrong> — ссылку на смарт-контракт, код которого EOA временно принимает на время транзакции. Это означает, что ваш существующий адрес кошелька MetaMask может выполнять произвольную логику смарт-контракта (пакетные вызовы, пользовательская валидация, спонсирование газа) без развёртывания нового контрактного кошелька или смены адреса.\u003C\u002Fp>\n\u003Cp>Это самое значительное улучшение UX в истории Ethereum. Пользователям больше не нужно выбирать между простотой EOA и возможностями смарт-аккаунта.\u003C\u002Fp>\n\u003Ch2 id=\"eip-7702-vs-erc-4337\">EIP-7702 vs ERC-4337: когда использовать что\u003C\u002Fh2>\n\u003Cp>Оба стандарта обеспечивают абстракцию аккаунтов, но работают на разных уровнях и подходят для разных случаев:\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Параметр\u003C\u002Fth>\u003Cth>EIP-7702\u003C\u002Fth>\u003Cth>ERC-4337\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Уровень\u003C\u002Ftd>\u003Ctd>Протокольный (новый тип tx)\u003C\u002Ftd>\u003Ctd>Прикладной (смарт-контракт)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Тип аккаунта\u003C\u002Ftd>\u003Ctd>Обновляет существующие EOA\u003C\u002Ftd>\u003Ctd>Требует нового контрактного кошелька\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Адрес\u003C\u002Ftd>\u003Ctd>Сохраняет существующий адрес EOA\u003C\u002Ftd>\u003Ctd>Новый адрес (контрфактический)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Постоянство\u003C\u002Ftd>\u003Ctd>Делегация на транзакцию\u003C\u002Ftd>\u003Ctd>Постоянный смарт-контракт\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Требуется бандлер\u003C\u002Ftd>\u003Ctd>Нет (стандартный поток tx)\u003C\u002Ftd>\u003Ctd>Да (отдельный мемпул)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Расход газа\u003C\u002Ftd>\u003Ctd>~20 000 газа на делегацию\u003C\u002Ftd>\u003Ctd>~42 000 газа на валидацию UserOp\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Поддержка кошельков\u003C\u002Ftd>\u003Ctd>MetaMask, Coinbase Wallet, Rainbow\u003C\u002Ftd>\u003Ctd>Специализированные (Safe, ZeroDev, Biconomy)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Лучше для\u003C\u002Ftd>\u003Ctd>Обновления существующих пользователей\u003C\u002Ftd>\u003Ctd>Новых пользователей, сложной логики аккаунтов\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch3>Фреймворк принятия решений\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>Используйте EIP-7702, когда:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Ваши пользователи уже имеют EOA-кошельки (MetaMask, Coinbase Wallet)\u003C\u002Fli>\n\u003Cli>Вам нужны пакетные транзакции или спонсирование газа\u003C\u002Fli>\n\u003Cli>Вы хотите минимальную сложность интеграции\u003C\u002Fli>\n\u003Cli>Логика смарт-аккаунта нужна на транзакцию (не постоянно)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Используйте ERC-4337, когда:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Вы создаёте новый кошелёк или онбордите новых пользователей\u003C\u002Fli>\n\u003Cli>Вам нужна постоянная логика аккаунта (постоянный мультисиг, сложное восстановление)\u003C\u002Fli>\n\u003Cli>Вы хотите, чтобы аккаунт был смарт-контрактом по умолчанию\u003C\u002Fli>\n\u003Cli>Вам нужны продвинутые функции: модули аккаунта, плагины, гарантии\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Используйте оба вместе, когда:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Вы хотите ERC-4337 смарт-аккаунты, которые также могут обрабатывать EIP-7702 делегации от EOA (для обратной совместимости)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"\">Примеры кода\u003C\u002Fh2>\n\u003Ch3>Пакетные транзакции\u003C\u002Fh3>\n\u003Cp>Самый распространённый сценарий использования EIP-7702: выполнение нескольких операций в одной транзакции. Больше никаких двухшаговых потоков “approve, затем swap”.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\n\u002F\u002F\u002F @title BatchExecutor — цель делегации EIP-7702 для пакетных вызовов\n\u002F\u002F\u002F @notice EOA делегирует этому контракту для атомарного выполнения множественных вызовов\ncontract BatchExecutor {\n    struct Call {\n        address target;\n        uint256 value;\n        bytes data;\n    }\n    \n    \u002F\u002F\u002F @notice Выполнить пакет вызовов от делегирующего EOA\n    \u002F\u002F\u002F @dev При вызове через EIP-7702, msg.sender — сам EOA\n    \u002F\u002F\u002F @param calls Массив вызовов для выполнения\n    function executeBatch(Call[] calldata calls) external payable {\n        for (uint256 i = 0; i &lt; calls.length; i++) {\n            (bool success, bytes memory result) = calls[i].target.call{\n                value: calls[i].value\n            }(calls[i].data);\n            \n            if (!success) {\n                \u002F\u002F Прокинуть причину отката\n                assembly {\n                    revert(add(result, 32), mload(result))\n                }\n            }\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Использование на клиенте с ethers.js v6:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">import { ethers } from \"ethers\";\n\n\u002F\u002F Тип транзакции EIP-7702 (type: 4)\nconst batchTx = {\n    type: 4,\n    to: userAddress, \u002F\u002F EOA делегирует самому себе\n    authorizationList: [{\n        chainId: 1,\n        address: BATCH_EXECUTOR_ADDRESS, \u002F\u002F цель делегации\n        nonce: await provider.getTransactionCount(userAddress),\n        \u002F\u002F Подписано владельцем EOA:\n        yParity: 0, r: \"0x...\", s: \"0x...\"\n    }],\n    data: batchExecutorInterface.encodeFunctionData(\"executeBatch\", [[\n        {\n            target: USDC_ADDRESS,\n            value: 0,\n            data: usdcInterface.encodeFunctionData(\"approve\", [\n                UNISWAP_ROUTER, ethers.parseUnits(\"1000\", 6)\n            ])\n        },\n        {\n            target: UNISWAP_ROUTER,\n            value: 0,\n            data: routerInterface.encodeFunctionData(\"exactInputSingle\", [{\n                tokenIn: USDC_ADDRESS,\n                tokenOut: WETH_ADDRESS,\n                fee: 3000,\n                recipient: userAddress,\n                amountIn: ethers.parseUnits(\"1000\", 6),\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            }])\n        }\n    ]])\n};\n\nconst tx = await signer.sendTransaction(batchTx);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Спонсирование газа\u003C\u002Fh3>\n\u003Cp>С EIP-7702 спонсор (paymaster) может оплачивать газ для любой EOA-транзакции, отправляя транзакцию от имени пользователя, в то время как список авторизации пользователя делегирует выполнение:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F\u002F @title SponsoredExecutor — спонсирование газа через EIP-7702\ncontract SponsoredExecutor {\n    mapping(address =&gt; uint256) public nonces;\n    \n    \u002F\u002F\u002F @notice Выполнить вызов от имени пользователя, газ оплачивает msg.sender\n    \u002F\u002F\u002F @param user EOA, подписавший авторизацию\n    \u002F\u002F\u002F @param target Контракт для вызова\n    \u002F\u002F\u002F @param data Calldata\n    \u002F\u002F\u002F @param userNonce Nonce для защиты от повторного воспроизведения\n    \u002F\u002F\u002F @param deadline Временная метка истечения\n    \u002F\u002F\u002F @param signature EIP-712 подпись пользователя\n    function sponsoredExecute(\n        address user,\n        address target,\n        bytes calldata data,\n        uint256 userNonce,\n        uint256 deadline,\n        bytes calldata signature\n    ) external {\n        require(block.timestamp &lt;= deadline, \"Expired\");\n        require(nonces[user] == userNonce, \"Invalid nonce\");\n        nonces[user]++;\n        \n        \u002F\u002F Верификация подписи пользователя (EIP-712)\n        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);\n        address signer = ECDSA.recover(digest, signature);\n        require(signer == user, \"Invalid signature\");\n        \n        \u002F\u002F Выполнение вызова как пользователь\n        (bool success, bytes memory result) = target.call(data);\n        require(success, \"Call failed\");\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Спонсор отправляет транзакцию type-4, оплачивая газ. Пользователь подписывает только EIP-712 сообщение, одобряющее конкретное действие — ETH в кошельке не требуется.\u003C\u002Fp>\n\u003Ch3>Социальное восстановление\u003C\u002Fh3>\n\u003Cp>EIP-7702 обеспечивает паттерны социального восстановления без необходимости постоянного контрактного кошелька:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F\u002F @title RecoveryModule — социальное восстановление через EIP-7702\ncontract RecoveryModule {\n    struct RecoveryConfig {\n        address[] guardians;\n        uint256 threshold;\n        uint256 delay;\n    }\n    \n    mapping(address =&gt; RecoveryConfig) public configs;\n    mapping(bytes32 =&gt; uint256) public recoveryTimestamps;\n    mapping(bytes32 =&gt; uint256) public approvalCounts;\n    mapping(bytes32 =&gt; mapping(address =&gt; bool)) public hasApproved;\n    \n    \u002F\u002F\u002F @notice Регистрация хранителей восстановления (вызывается EOA через EIP-7702)\n    function setupRecovery(\n        address[] calldata guardians,\n        uint256 threshold,\n        uint256 delay\n    ) external {\n        require(guardians.length &gt;= threshold, \"Invalid threshold\");\n        require(threshold &gt;= 2, \"Min 2 guardians\");\n        configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);\n    }\n    \n    \u002F\u002F\u002F @notice Хранитель одобряет запрос на восстановление\n    function approveRecovery(\n        address account,\n        address newOwner\n    ) external {\n        RecoveryConfig memory config = configs[account];\n        require(_isGuardian(config, msg.sender), \"Not a guardian\");\n        \n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        require(!hasApproved[recoveryId][msg.sender], \"Already approved\");\n        \n        hasApproved[recoveryId][msg.sender] = true;\n        approvalCounts[recoveryId]++;\n        \n        if (approvalCounts[recoveryId] &gt;= config.threshold) {\n            recoveryTimestamps[recoveryId] = block.timestamp + config.delay;\n        }\n    }\n    \n    \u002F\u002F\u002F @notice Выполнение восстановления после периода ожидания\n    function executeRecovery(\n        address account,\n        address newOwner\n    ) external {\n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        uint256 timestamp = recoveryTimestamps[recoveryId];\n        require(timestamp &gt; 0 &amp;&amp; block.timestamp &gt;= timestamp, \"Not ready\");\n        \n        \u002F\u002F Передача контроля путём обновления цели делегации аккаунта\n        \u002F\u002F на контракт, управляемый newOwner\n        \u002F\u002F Реализация зависит от конкретной архитектуры кошелька\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">Статус интеграции кошельков\u003C\u002Fh2>\n\u003Cp>По состоянию на март 2026 года поддержка EIP-7702 развёрнута в основных кошельках:\u003C\u002Fp>\n\u003Ch3>MetaMask\u003C\u002Fh3>\n\u003Cp>MetaMask добавил поддержку EIP-7702 в версии 12.4 (сентябрь 2025). Пользователи видят значок “Smart Transaction” при запросе dApp на транзакцию type-4. Кошелёк показывает:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Контракт — цель делегации (с верифицированным исходным кодом на Etherscan)\u003C\u002Fli>\n\u003Cli>Каждый вызов в пакете с декодированными параметрами\u003C\u002Fli>\n\u003Cli>Ожидаемую экономию газа по сравнению с отдельными транзакциями\u003C\u002Fli>\n\u003Cli>Предупреждение, если цель делегации не верифицирована\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Coinbase Wallet\u003C\u002Fh3>\n\u003Cp>Coinbase Wallet стал наиболее агрессивным последователем, интегрировав EIP-7702 в функцию “Smart Wallet” (запущена в ноябре 2025). Ключевые особенности:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Авто-батчинг\u003C\u002Fstrong> — кошелёк автоматически объединяет последовательности approve+swap\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Спонсирование газа\u003C\u002Fstrong> — Coinbase спонсирует газ для транзакций с комиссией менее $1\u003C\u002Fli>\n\u003Cli>\u003Cstrong>DeFi в один клик\u003C\u002Fstrong> — готовые цели делегации для типичных DeFi-операций\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Rainbow, Rabby и другие\u003C\u002Fh3>\n\u003Cp>Rainbow добавил поддержку в январе 2026 года. Rabby поддерживает транзакции type-4, но не имеет UI визуализации пакетов. Frame (десктопный кошелёк) был одним из первых, кто поддержал EIP-7702, выпустив поддержку в апреле 2025 года.\u003C\u002Fp>\n\u003Ch2 id=\"eoa\">Руководство по миграции: от EOA к смарт-аккаунтам\u003C\u002Fh2>\n\u003Cp>Для разработчиков dApp вот рекомендуемый путь миграции для поддержки EIP-7702:\u003C\u002Fp>\n\u003Ch3>Шаг 1: развёртывание целей делегации\u003C\u002Fh3>\n\u003Cp>Создайте и проведите аудит смарт-контрактов, которым ваши пользователи будут делегировать. Типичные паттерны:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>BatchExecutor       — пакетирование мульти-вызовов\nSessionKeyManager   — ограниченные по времени разрешения\nSpendingLimiter     — дневные\u002Fнедельные лимиты расходов\nRecoveryModule      — настройка социального восстановления\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Шаг 2: обновление фронтенда\u003C\u002Fh3>\n\u003Cp>Определите, поддерживает ли подключённый кошелёк EIP-7702:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">async function supportsEIP7702(provider: ethers.Provider): Promise&lt;boolean&gt; {\n    try {\n        \u002F\u002F Проверяем, поддерживает ли нода транзакции type-4\n        const capabilities = await provider.send(\n            \"wallet_getCapabilities\", []\n        );\n        return capabilities?.atomicBatch?.supported === true;\n    } catch {\n        return false;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Шаг 3: реализация graceful degradation\u003C\u002Fh3>\n\u003Cp>Не все пользователи будут иметь кошельки с поддержкой EIP-7702. Ваш dApp должен определять возможности и делать фоллбэк:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">async function executeSwap(tokenIn, tokenOut, amount) {\n    if (await supportsEIP7702(provider)) {\n        \u002F\u002F Одна транзакция: approve + swap\n        return executeBatchSwap(tokenIn, tokenOut, amount);\n    } else {\n        \u002F\u002F Легаси: две отдельные транзакции\n        await approve(tokenIn, ROUTER, amount);\n        return swap(tokenIn, tokenOut, amount);\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Шаг 4: обновление отслеживания транзакций\u003C\u002Fh3>\n\u003Cp>Пакетные транзакции содержат несколько операций в одном tx hash. Обновите UI истории транзакций для парсинга и отображения каждой подоперации:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">interface BatchOperation {\n    target: string;\n    method: string;\n    params: Record&lt;string, unknown&gt;;\n    status: \"success\" | \"reverted\";\n}\n\n\u002F\u002F Парсинг пакетных операций из квитанции транзакции\nfunction parseBatchOps(receipt: TransactionReceipt): BatchOperation[] {\n    \u002F\u002F Декодирование логов и внутренних вызовов из квитанции\n    \u002F\u002F ...\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">Соображения безопасности\u003C\u002Fh2>\n\u003Cp>EIP-7702 вводит новые поверхности атаки, которые разработчики должны понимать:\u003C\u002Fp>\n\u003Ch3>Верификация цели делегации\u003C\u002Fh3>\n\u003Cp>Контракт — цель делегации имеет \u003Cstrong>полный контроль\u003C\u002Fstrong> над активами EOA во время транзакции. Злонамеренная цель делегации может:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Перевести все ETH и токены из EOA\u003C\u002Fli>\n\u003Cli>Установить неограниченные разрешения токенов на адреса атакующего\u003C\u002Fli>\n\u003Cli>Взаимодействовать с DeFi-протоколами для вывода позиций\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Защита:\u003C\u002Fstrong> делегируйте только проаудированным, верифицированным контрактам. Кошельки должны поддерживать белый список доверенных целей делегации.\u003C\u002Fp>\n\u003Ch3>Защита от повторного воспроизведения\u003C\u002Fh3>\n\u003Cp>Списки авторизации EIP-7702 включают nonce для предотвращения атак повторного воспроизведения. Однако разработчики должны обеспечить:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Nonce авторизации совпадает с текущим nonce EOA\u003C\u002Fli>\n\u003Cli>Каждая авторизация используется ровно один раз\u003C\u002Fli>\n\u003Cli>Кросс-чейн повторное воспроизведение предотвращается включением chain ID\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Фишинг через делегацию\u003C\u002Fh3>\n\u003Cp>Атакующие могут обманом заставить пользователей подписать списки авторизации, делегирующие злонамеренным контрактам. Это аналогично существующей проблеме фишинга через “approve”, но потенциально более опасно, поскольку делегация предоставляет более широкий доступ.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Защита:\u003C\u002Fstrong> кошельки должны чётко отображать, какому коду EOA делегирует, с верификацией исходного кода и оценкой риска.\u003C\u002Fp>\n\u003Ch3>Реентрантность в пакетном выполнении\u003C\u002Fh3>\n\u003Cp>Пакетные исполнители, использующие \u003Ccode>call\u003C\u002Fcode> в цикле, уязвимы к реентрантности, если одна из целей пакета вызывает обратно исполнитель. Используйте защиту от реентрантности или паттерн checks-effects-interactions:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F Используйте защиту от реентрантности на пакетном исполнителе\nbool private locked;\n\nmodifier noReentrant() {\n    require(!locked, \"Reentrant\");\n    locked = true;\n    _;\n    locked = false;\n}\n\nfunction executeBatch(Call[] calldata calls) external payable noReentrant {\n    \u002F\u002F ...\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Коллизии хранилища\u003C\u002Fh3>\n\u003Cp>Когда EOA делегирует контракту, код контракта выполняется в контексте хранилища EOA. Если две разные цели делегации используют одни и те же слоты хранилища для разных целей, может произойти повреждение данных.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Защита:\u003C\u002Fstrong> используйте EIP-7201 (именованное хранилище) во всех целях делегации:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F Именованное хранилище EIP-7201\nbytes32 constant STORAGE_SLOT = keccak256(\n    abi.encode(uint256(keccak256(\"batch.executor.storage\")) - 1)\n) &amp; ~bytes32(uint256(0xff));\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">Часто задаваемые вопросы\u003C\u002Fh2>\n\u003Ch3 id=\"eip-7702\">Меняет ли EIP-7702 адрес моего кошелька?\u003C\u002Fh3>\n\u003Cp>Нет. Ваш адрес EOA остаётся прежним. EIP-7702 временно наделяет ваш адрес возможностями смарт-контракта на время одной транзакции. После завершения транзакции ваш адрес возвращается к стандартному EOA.\u003C\u002Fp>\n\u003Ch3 id=\"eip-7702-l2\">Можно ли использовать EIP-7702 на L2?\u003C\u002Fh3>\n\u003Cp>Да. Все основные L2 (Arbitrum, Base, Optimism, zkSync) приняли EIP-7702 в рамках своих обновлений, эквивалентных Pectra. Формат транзакций и механика делегации идентичны.\u003C\u002Fp>\n\u003Ch3 id=\"\">Что произойдёт, если в цели делегации есть баг?\u003C\u002Fh3>\n\u003Cp>Ущерб ограничен одной транзакцией. В отличие от постоянного контрактного кошелька, делегация EIP-7702 истекает после завершения транзакции. Однако в рамках этой транзакции цель делегации имеет полный доступ к активам EOA — баг может опустошить аккаунт.\u003C\u002Fp>\n\u003Ch3 id=\"eip-7702\">Совместим ли EIP-7702 с аппаратными кошельками?\u003C\u002Fh3>\n\u003Cp>Да. Аппаратные кошельки (Ledger, Trezor) могут подписывать транзакции type-4, включая список авторизации. Ledger добавил поддержку в прошивке версии 2.3.0 (декабрь 2025). Пользователь подтверждает цель делегации на экране аппаратного устройства.\u003C\u002Fp>\n\u003Ch3 id=\"eip-7702\">Сколько газа экономит EIP-7702?\u003C\u002Fh3>\n\u003Cp>Для типичного потока approve+swap EIP-7702 экономит примерно \u003Cstrong>40-50%\u003C\u002Fstrong> на газе за счёт устранения накладных расходов второй транзакции (21 000 базового газа) и более эффективного кодирования calldata. Для сложных многошаговых DeFi-операций (например, zap в хранилище) экономия может достигать 60-70%.\u003C\u002Fp>\n","ru","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:35.357227Z","Реализация пакетных транзакций, спонсирования газа и социального восстановления через EIP-7702. Примеры кода, поддержка кошельков и безопасность.","EIP-7702",null,"index, follow",[21,26,30],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000013","Security","security","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000014","Solidity","solidity",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000009","Web3","web3","Блокчейн",[36,43,49],{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":41,"published_at":42},"d0200000-0000-0000-0000-000000000013","Почему Бали становится хабом импакт-технологий Юго-Восточной Азии в 2026 году","pochemu-bali-stanovitsya-khabom-impakt-tekhnologiy-2026","Бали занимает 16-е место среди стартап-экосистем Юго-Восточной Азии. Растущая концентрация Web3-разработчиков, ИИ-стартапов в области устойчивого развития и компаний в сфере эко-тревел-технологий формирует нишу столицы импакт-технологий региона.","Инженерия","2026-03-28T10:44:37.953039Z",{"id":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":41,"published_at":48},"d0200000-0000-0000-0000-000000000012","Защита данных в ASEAN: чек-лист разработчика для мультистранового комплаенса","zashchita-dannykh-asean-chek-list-razrabotchika-komplaens","Семь стран ASEAN имеют собственные законы о защите данных с разными моделями согласия, требованиями к локализации и штрафами. Практический чек-лист для разработчиков мультистрановых приложений.","2026-03-28T10:44:37.944001Z",{"id":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":41,"published_at":54},"d0200000-0000-0000-0000-000000000011","Цифровая трансформация Индонезии на $29 миллиардов: возможности для софтверных компаний","tsifrovaya-transformatsiya-indonezii-29-milliardov-vozmozhnosti-dlya-kompaniy","Рынок IT-услуг Индонезии вырастет с $24,37 млрд в 2025 году до $29,03 млрд в 2026 году. Облачная инфраструктура, искусственный интеллект, электронная коммерция и дата-центры обеспечивают самый быстрый рост в Юго-Восточной Азии.","2026-03-28T10:44:37.917095Z",{"id":13,"name":56,"slug":57,"bio":58,"photo_url":18,"linkedin":18,"role":59,"created_at":60,"updated_at":60},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]