Разработка смарт-контрактного кошелька (Account Abstraction)

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка смарт-контрактного кошелька (Account Abstraction)
Сложная
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка смарт-контрактного кошелька (Account Abstraction)

Account Abstraction — это архитектурный сдвиг, который превращает кошелёк из пассивного хранилища ключей в программируемый агент. EIP-4337 стандартизировал этот подход без изменений на уровне протокола Ethereum: вся логика живёт в смарт-контрактах, а специализированная мемпул-инфраструктура (Bundlers и Paymasters) обрабатывает UserOperation объекты вместо обычных транзакций. Если вы строите продукт, где пользователь не должен думать о gas, seed phrase и approve — без AA не обойтись.

Архитектура EIP-4337: как это работает на самом деле

Компоненты системы

Классическая EOA-транзакция идёт напрямую в mempool и выполняется нодой. В AA-системе цепочка другая:

  1. UserOperation — псевдотранзакция, подписанная пользователем. Содержит callData, sender (адрес смарт-кошелька), signature, лимиты gas и параметры Paymaster.
  2. Bundler — offchain агент, который собирает UserOperations из альтернативного mempool, упаковывает их в одну on-chain транзакцию и вызывает EntryPoint. Существующие реализации: Stackup, Pimlico, Alchemy Rundler (написан на Rust, на порядок быстрее референсной реализации).
  3. EntryPoint — singleton контракт (0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 на большинстве EVM сетей), развёрнутый командой ERC-4337. Именно он верифицирует и исполняет пачку операций. Нельзя деплоить свой EntryPoint — экосистема завязана на этот адрес.
  4. Account Contract — сам смарт-кошелёк пользователя. Должен реализовывать интерфейс IAccount с методом validateUserOp. Сюда идёт вся кастомная логика.
  5. Paymaster — опциональный контракт, который платит gas за пользователя или принимает оплату в ERC-20 токенах вместо ETH.

Жизненный цикл UserOperation

User → sign UserOp → send to Bundler RPC
Bundler → simulate via eth_estimateUserOperationGas → validate signature + paymaster
Bundler → batch multiple UserOps → call EntryPoint.handleOps()
EntryPoint → validateUserOp() на каждом Account Contract
EntryPoint → Paymaster.validatePaymasterUserOp()
EntryPoint → execute callData
EntryPoint → postOp() на Paymaster (для учёта gas)

Важный момент: simulation и execution разделены. Bundler симулирует через eth_callStateOverride и реджектит операции, которые могут зафейлиться on-chain. Это защищает Bundler от потери ETH на failed transactions.

Реализация Account Contract

Базовая структура

За основу берём SimpleAccount от eth-infinitism или SafeAccount от Safe (бывший Gnosis Safe). Для production — Safe v1.4.1 с 4337 модулем, потому что он battle-tested с $100B+ TVL.

contract SmartWallet is IAccount, Initializable, UUPSUpgradeable {
    address public owner;
    IEntryPoint private immutable _entryPoint;

    function validateUserOp(
        UserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external override returns (uint256 validationData) {
        _requireFromEntryPoint();
        validationData = _validateSignature(userOp, userOpHash);
        _validateNonce(userOp.nonce);
        _payPrefund(missingAccountFunds);
    }

    function _validateSignature(
        UserOperation calldata userOp,
        bytes32 userOpHash
    ) internal view returns (uint256) {
        bytes32 hash = userOpHash.toEthSignedMessageHash();
        if (owner != hash.recover(userOp.signature))
            return SIG_VALIDATION_FAILED;
        return 0; // SIG_VALIDATION_SUCCESS
    }
}

validationData кодирует три вещи: результат валидации (0 = успех, 1 = провал), validAfter и validUntil timestamps. Это позволяет делать time-bounded операции прямо в подписи.

Паттерны расширенной логики

Multisig в одном кошельке. Вместо owner хранится пороговое значение и список авторизованных подписантов. validateUserOp проверяет, что signatures содержит достаточное количество корректных подписей.

Session keys. Ограниченный ключ (например, сгенерированный браузером без seed phrase exposure), которому разрешены операции только в рамках конкретного контракта, лимита суммы и временного окна:

struct SessionKey {
    address key;
    address allowedContract;
    uint256 spendingLimit;
    uint48 validUntil;
    bool enabled;
}
mapping(address => SessionKey) public sessionKeys;

Это фундамент для "gasless gaming" — пользователь один раз подписывает сессию на игровой контракт, дальше игра делает транзакции от его имени.

Social recovery. Guardians — доверенные адреса, которые могут сменить owner через timelock (обычно 72 часа). Реализация Argent — хороший референс: threshold из M-of-N guardians, cancellation в течение timelock window если owner онлайн.

Paymaster: газлесс и ERC-20 оплата

Sponsoring Paymaster

contract SponsoringPaymaster is IPaymaster {
    mapping(address => bool) public whitelistedContracts;

    function validatePaymasterUserOp(
        UserOperation calldata userOp,
        bytes32,
        uint256 maxCost
    ) external returns (bytes memory context, uint256 validationData) {
        // Спонсируем только вызовы whitelisted контрактов
        address target = address(bytes20(userOp.callData[16:36]));
        require(whitelistedContracts[target], "Not whitelisted");
        require(deposit() >= maxCost, "Insufficient deposit");
        return (abi.encode(userOp.sender), 0);
    }
}

Paymaster должен держать депозит в EntryPoint. Механизм staking предотвращает DoS: Paymaster без stake может спонсировать максимум одну операцию за бандл.

ERC-20 Paymaster

Принимает любой ERC-20 как оплату gas. Оракул нужен для конвертации: Chainlink price feed или пул Uniswap V3 TWAP. Схема работы: до выполнения блокируем maxCost * exchangeRate токенов, после — списываем фактический cost через postOp.

Готовые решения: Pimlico ERC-20 Paymaster (open source), Stackup Paymaster SDK.

Factory и counterfactual деплой

Одно из ключевых свойств AA — кошелёк существует как адрес ещё до деплоя. CREATE2 с детерминированным salt (обычно хэш от owner address) даёт предсказуемый адрес. Пользователь получает адрес кошелька до первой транзакции, может принять средства — кошелёк деплоится автоматически при первом использовании.

contract WalletFactory {
    function getAddress(address owner, uint256 salt) public view returns (address) {
        return Create2.computeAddress(
            bytes32(salt),
            keccak256(abi.encodePacked(
                type(ERC1967Proxy).creationCode,
                abi.encode(address(implementation), initData(owner))
            ))
        );
    }

    function createAccount(address owner, uint256 salt) external returns (SmartWallet) {
        address addr = getAddress(owner, salt);
        if (addr.code.length > 0) return SmartWallet(payable(addr)); // уже задеплоен
        return SmartWallet(payable(new ERC1967Proxy{salt: bytes32(salt)}(
            address(implementation), initData(owner)
        )));
    }
}

Фронтенд интеграция

Viem + permissionless.js — наиболее актуальный стек (2024–2025). permissionless построен на Viem и предоставляет абстракции для работы с Bundler и Paymaster RPC:

import { createSmartAccountClient } from "permissionless";
import { signerToSimpleSmartAccount } from "permissionless/accounts";
import { createPimlicoBundlerClient } from "permissionless/clients/pimlico";

const smartAccount = await signerToSimpleSmartAccount(publicClient, {
  signer: walletClient,
  factoryAddress: FACTORY_ADDRESS,
  entryPoint: ENTRY_POINT_ADDRESS,
});

const smartAccountClient = createSmartAccountClient({
  account: smartAccount,
  chain: optimism,
  bundlerTransport: http(BUNDLER_RPC_URL),
  middleware: {
    sponsorUserOperation: paymasterClient.sponsorUserOperation,
  },
});

// Отправка транзакции — идентично обычному кошельку для пользователя
const txHash = await smartAccountClient.sendTransaction({
  to: contractAddress,
  data: encodeFunctionData({ abi, functionName: "doSomething" }),
});

ZeroDev SDK — альтернатива с более высоким уровнем абстракции, встроенными session keys и Kernel account (популярный Account Contract с plugin системой).

Альтернативы EIP-4337

zkSync Native AA — на zkSync Era AA встроена в протокол, не нужен отдельный EntryPoint. Каждый аккаунт может быть смарт-контрактом из коробки. Более эффективно по gas, но привязка к zkSync.

EIP-7702 (Prague/Electra) — предстоящий хардфорк Ethereum. Позволяет EOA временно делегировать исполнение смарт-контракту через специальный тип транзакции. Не заменяет 4337 полностью, но закрывает часть use cases проще.

Этапы разработки и оценки

Компонент Сложность Срок
Базовый Account Contract (single owner) Средняя 1–2 нед
Factory + counterfactual deploy Низкая 3–5 дней
Sponsoring Paymaster Средняя 1 нед
ERC-20 Paymaster + оракул Высокая 1–2 нед
Session keys Высокая 1–2 нед
Social recovery Высокая 1–2 нед
Frontend SDK интеграция Средняя 1 нед
Аудит + исправления 3–6 нед

Минимальный production-ready кошелёк (single owner + sponsoring paymaster + фронтенд) — 4–6 недель разработки. Полнофункциональный продукт с social recovery, session keys и мультисетью — 3–5 месяцев.

Ключевой момент при выборе подрядчика: реализация validateUserOp должна быть аудирована. Ошибка в этой функции — прямая потеря средств пользователей. Экономия на аудите здесь = сознательный риск.