EIP-7702 in der Praxis: Smart-Account-Flows nach Pectra erstellen
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
| Merkmal | EIP-7702 | ERC-4337 |
|---|---|---|
| Ebene | Protokoll (neuer Tx-Typ) | Anwendung (Smart Contract) |
| Kontotyp | Aktualisiert bestehende EOAs | Erfordert neue Contract-Wallet |
| Adresse | Behaelt bestehende EOA-Adresse | Neue Adresse (kontrafaktisch) |
| Persistenz | Delegation pro Transaktion | Permanenter Smart Contract |
| Bundler erforderlich | Nein (Standard-Tx-Flow) | Ja (separater Mempool) |
| Gas-Overhead | ~20.000 Gas fuer Delegation | ~42.000 Gas fuer UserOp-Validierung |
| Unterstuetzte Wallets | MetaMask, Coinbase Wallet, Rainbow | Spezialisiert (Safe, ZeroDev, Biconomy) |
| Ideal fuer | Bestehende Benutzer upgraden | Neue 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.