Zum Hauptinhalt springen
BlockchainMar 28, 2026

EIP-7702 in der Praxis: Smart-Account-Flows nach Pectra erstellen

OS
Open Soft Team

Engineering Team

Was EIP-7702 ermoeglicht

EIP-7702, aktiviert mit Ethereums Pectra-Upgrade im Maerz 2025, fuehrt einen neuen Transaktionstyp ein, der jedem externen Konto (EOA) erlaubt, einen Delegationsbezeichner festzulegen — einen Zeiger auf einen Smart Contract, dessen Code das EOA voruebergehend fuer die Dauer einer Transaktion uebernimmt. Das bedeutet, Ihre bestehende MetaMask-Wallet-Adresse kann beliebige Smart-Contract-Logik ausfuehren, ohne eine neue Contract-Wallet zu deployen oder Ihre Adresse zu aendern.

Dies ist die bedeutendste UX-Verbesserung in der Geschichte von Ethereum.

EIP-7702 vs ERC-4337: Wann was verwenden

MerkmalEIP-7702ERC-4337
EbeneProtokoll (neuer Tx-Typ)Anwendung (Smart Contract)
KontotypAktualisiert bestehende EOAsErfordert neue Contract-Wallet
AdresseBehaelt bestehende EOA-AdresseNeue Adresse (kontrafaktisch)
PersistenzDelegation pro TransaktionPermanenter Smart Contract
Bundler erforderlichNein (Standard-Tx-Flow)Ja (separater Mempool)
Gas-Overhead~20.000 Gas fuer Delegation~42.000 Gas fuer UserOp-Validierung
Unterstuetzte WalletsMetaMask, Coinbase Wallet, RainbowSpezialisiert (Safe, ZeroDev, Biconomy)
Ideal fuerBestehende Benutzer upgradenNeue Benutzer, komplexe Kontologik

Entscheidungsrahmen

EIP-7702 verwenden, wenn:

  • Ihre Benutzer bereits EOA-Wallets haben
  • Sie Batch-Transaktionen oder Gas-Sponsoring benoetigen
  • Sie minimale Integrationskomplexitaet wollen

ERC-4337 verwenden, wenn:

  • Sie eine neue Wallet bauen oder neue Benutzer onboarden
  • Sie persistente Kontologik benoetigen
  • Sie erweiterte Funktionen wie Module, Plugins oder Guardians benoetigen

Code-Beispiele

Batch-Transaktionen

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

/// @title BatchExecutor — EIP-7702-Delegationsziel fuer Batch-Aufrufe
contract BatchExecutor {
    struct Call {
        address target;
        uint256 value;
        bytes data;
    }
    
    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))
                }
            }
        }
    }
}

Clientseitige Nutzung mit ethers.js v6:

import { ethers } from "ethers";

const batchTx = {
    type: 4,
    to: userAddress,
    authorizationList: [{
        chainId: 1,
        address: BATCH_EXECUTOR_ADDRESS,
        nonce: await provider.getTransactionCount(userAddress),
        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);

Gas-Sponsoring

/// @title SponsoredExecutor — Gas-Sponsoring ueber EIP-7702
contract SponsoredExecutor {
    mapping(address => uint256) public nonces;
    
    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]++;
        
        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");
    }
}

Soziale Wiederherstellung

/// @title RecoveryModule — Soziale Wiederherstellung ueber 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;
    
    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);
    }
    
    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;
        }
    }
    
    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");
    }
}

Status der Wallet-Integration

MetaMask

MetaMask hat EIP-7702-Support in Version 12.4 (September 2025) hinzugefuegt.

Coinbase Wallet

Coinbase Wallet ist der aggressivste Adopter und hat EIP-7702 in die “Smart Wallet”-Funktion (November 2025) integriert:

  • Auto-Batching — Automatische Buendelung von Approve+Swap-Sequenzen
  • Gas-Sponsoring — Coinbase sponsert Gas fuer Transaktionen unter 1 $ Gebuehr
  • Ein-Klick-DeFi — Vorgefertigte Delegationsziele fuer gaengige DeFi-Operationen

Rainbow, Rabby und andere

Rainbow hat Support im Januar 2026 hinzugefuegt. Rabby unterstuetzt Type-4-Transaktionen, aber ohne Batch-Visualisierungs-UI.

Migrationsleitfaden

Schritt 1: Delegationsziele deployen

Schritt 2: Frontend aktualisieren

async function supportsEIP7702(provider: ethers.Provider): Promise<boolean> {
    try {
        const capabilities = await provider.send(
            "wallet_getCapabilities", []
        );
        return capabilities?.atomicBatch?.supported === true;
    } catch {
        return false;
    }
}

Schritt 3: Graceful Degradation implementieren

async function executeSwap(tokenIn, tokenOut, amount) {
    if (await supportsEIP7702(provider)) {
        return executeBatchSwap(tokenIn, tokenOut, amount);
    } else {
        await approve(tokenIn, ROUTER, amount);
        return swap(tokenIn, tokenOut, amount);
    }
}

Sicherheitsueberlegungen

Delegationsziel-Verifizierung

Der Delegationsziel-Contract hat volle Kontrolle ueber die Assets des EOA waehrend der Transaktion.

Gegenmassnahme: Nur an auditierte, verifizierte Contracts delegieren.

Replay-Schutz

EIP-7702-Autorisierungslisten enthalten eine Nonce gegen Replay-Angriffe.

Phishing ueber Delegation

Gegenmassnahme: Wallets muessen klar anzeigen, an welchen Code das EOA delegiert.

Reentrancy bei Batch-Ausfuehrung

bool private locked;

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

Speicher-Kollisionen

EIP-7201 (Namespace-Speicher) in allen Delegationszielen verwenden:

bytes32 constant STORAGE_SLOT = keccak256(
    abi.encode(uint256(keccak256("batch.executor.storage")) - 1)
) & ~bytes32(uint256(0xff));

Haeufig gestellte Fragen

Aendert EIP-7702 meine Wallet-Adresse?

Nein. Ihre EOA-Adresse bleibt gleich.

Kann ich EIP-7702 auf L2s verwenden?

Ja. Alle grossen L2s (Arbitrum, Base, Optimism, zkSync) haben EIP-7702 uebernommen.

Was passiert bei einem Bug im Delegationsziel?

Der Schaden ist auf die einzelne Transaktion begrenzt. Aber innerhalb dieser Transaktion hat das Delegationsziel vollen Zugriff auf die EOA-Assets.

Ist EIP-7702 mit Hardware-Wallets kompatibel?

Ja. Ledger hat Support in Firmware 2.3.0 (Dezember 2025) hinzugefuegt.

Wie viel Gas spart EIP-7702?

Fuer einen typischen Approve+Swap-Flow spart EIP-7702 ca. 40-50 % Gas. Fuer komplexe Multi-Schritt-DeFi-Operationen koennen die Einsparungen 60-70 % erreichen.