跳到主要内容
BlockchainMar 28, 2026

EIP-7702 in Practice: Building Smart Account Flows After Pectra

OS
Open Soft Team

Engineering Team

What EIP-7702 Enables

EIP-7702, activated with Ethereum’s Pectra upgrade in March 2025, introduces a new transaction type that allows any Externally Owned Account (EOA) to set a delegation designator — a pointer to a smart contract whose code the EOA temporarily adopts for the duration of a transaction. This means your existing MetaMask wallet address can execute arbitrary smart contract logic (batch calls, custom validation, gas sponsorship) without deploying a new contract wallet or changing your address.

This is the most significant UX improvement in Ethereum’s history. Users no longer need to choose between the simplicity of an EOA and the power of a smart account.

EIP-7702 vs ERC-4337: When to Use Which

Both EIP-7702 and ERC-4337 enable account abstraction, but they operate at different levels and suit different use cases:

FeatureEIP-7702ERC-4337
LevelProtocol (new tx type)Application (smart contract)
Account typeUpgrades existing EOAsRequires new smart contract wallet
AddressKeeps existing EOA addressNew address (counterfactual)
PersistencePer-transaction delegationPermanent smart contract
Bundler requiredNo (standard tx flow)Yes (separate mempool)
Gas overhead~20,000 gas for delegation~42,000 gas for UserOp validation
Supported walletsMetaMask, Coinbase Wallet, RainbowSpecialized (Safe, ZeroDev, Biconomy)
Best forUpgrading existing usersNew users, complex account logic

Decision Framework

Use EIP-7702 when:

  • Your users already have EOA wallets (MetaMask, Coinbase Wallet)
  • You need batch transactions or gas sponsorship
  • You want minimal integration complexity
  • The smart account logic is per-transaction (not permanent)

Use ERC-4337 when:

  • You are building a new wallet or onboarding new users
  • You need persistent account logic (permanent multisig, complex recovery)
  • You want the account to be a smart contract by default
  • You need advanced features like account modules, plugins, or guardians

Use both together when:

  • You want ERC-4337 smart accounts that can also process EIP-7702 delegations from EOAs (for backward compatibility)

Code Examples

Batch Transactions

The most common EIP-7702 use case: execute multiple operations in a single transaction. No more “approve then swap” two-step flows.

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

/// @title BatchExecutor — EIP-7702 delegation target for batch calls
/// @notice EOAs delegate to this contract to execute multiple calls atomically
contract BatchExecutor {
    struct Call {
        address target;
        uint256 value;
        bytes data;
    }
    
    /// @notice Execute a batch of calls from the delegating EOA
    /// @dev When called via EIP-7702, msg.sender is the EOA itself
    /// @param calls Array of calls to execute
    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) {
                // Bubble up the revert reason
                assembly {
                    revert(add(result, 32), mload(result))
                }
            }
        }
    }
}

Client-side usage with ethers.js v6:

import { ethers } from "ethers";

// EIP-7702 transaction type (type: 4)
const batchTx = {
    type: 4,
    to: userAddress, // EOA delegates to itself
    authorizationList: [{
        chainId: 1,
        address: BATCH_EXECUTOR_ADDRESS, // delegation target
        nonce: await provider.getTransactionCount(userAddress),
        // Signed by the EOA owner:
        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 Sponsorship

With EIP-7702, a paymaster can sponsor gas for any EOA transaction by submitting the transaction on the user’s behalf while the user’s authorization list delegates execution:

/// @title SponsoredExecutor — gas sponsorship via EIP-7702
contract SponsoredExecutor {
    mapping(address => uint256) public nonces;
    
    /// @notice Execute a call on behalf of a user, gas paid by msg.sender
    /// @param user The EOA that signed the authorization
    /// @param target The contract to call
    /// @param data The calldata
    /// @param userNonce Replay protection nonce
    /// @param deadline Expiration timestamp
    /// @param signature User's EIP-712 signature over the above params
    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]++;
        
        // Verify user's signature (EIP-712)
        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);
        address signer = ECDSA.recover(digest, signature);
        require(signer == user, "Invalid signature");
        
        // Execute the call as the user (via delegatecall in EIP-7702 context)
        (bool success, bytes memory result) = target.call(data);
        require(success, "Call failed");
    }
}

The paymaster submits the type-4 transaction, paying gas. The user signs only an EIP-712 message approving the specific action — no ETH needed in their wallet.

Social Recovery

EIP-7702 enables social recovery patterns without requiring a permanent smart contract wallet:

/// @title RecoveryModule — social recovery via 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 Register recovery guardians (called by the EOA via 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 Guardian approves a recovery request
    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 Execute recovery after delay period
    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");
        
        // Transfer control by updating the account's delegation target
        // to a contract controlled by newOwner
        // Implementation depends on the specific wallet architecture
    }
}

Wallet Integration Status

As of March 2026, EIP-7702 support has rolled out across major wallets:

MetaMask

MetaMask added EIP-7702 support in version 12.4 (September 2025). Users see a “Smart Transaction” badge when a dApp requests a type-4 transaction. The wallet shows:

  • The delegation target contract (with verified source on Etherscan)
  • Each call in the batch with decoded parameters
  • Estimated gas savings vs separate transactions
  • A warning if the delegation target is unverified

Coinbase Wallet

Coinbase Wallet has been the most aggressive adopter, integrating EIP-7702 into its “Smart Wallet” feature (launched November 2025). Key features:

  • Auto-batching — the wallet automatically batches approve+swap sequences
  • Gas sponsorship — Coinbase sponsors gas for transactions under $1 in fee
  • One-click DeFi — pre-built delegation targets for common DeFi operations

Rainbow, Rabby, and Others

Rainbow added support in January 2026. Rabby supports type-4 transactions but lacks the batch visualization UI. Frame (the desktop wallet) was among the first to support EIP-7702, shipping support in April 2025.

Migration Guide: From EOA to Smart Accounts

For dApp developers, here is the recommended migration path to support EIP-7702:

Step 1: Deploy Delegation Targets

Create and audit the smart contracts your users will delegate to. Common patterns:

BatchExecutor       — multi-call batching
SessionKeyManager   — time-limited permissions
SpendingLimiter     — daily/weekly spending caps
RecoveryModule      — social recovery setup

Step 2: Update Your Frontend

Detect whether the connected wallet supports EIP-7702:

async function supportsEIP7702(provider: ethers.Provider): Promise<boolean> {
    try {
        // Check if the node supports type-4 transactions
        const capabilities = await provider.send(
            "wallet_getCapabilities", []
        );
        return capabilities?.atomicBatch?.supported === true;
    } catch {
        return false;
    }
}

Step 3: Implement Graceful Degradation

Not all users will have EIP-7702-capable wallets. Your dApp should detect capabilities and fall back:

async function executeSwap(tokenIn, tokenOut, amount) {
    if (await supportsEIP7702(provider)) {
        // Single transaction: approve + swap
        return executeBatchSwap(tokenIn, tokenOut, amount);
    } else {
        // Legacy: two separate transactions
        await approve(tokenIn, ROUTER, amount);
        return swap(tokenIn, tokenOut, amount);
    }
}

Step 4: Update Transaction Tracking

Batch transactions contain multiple operations in a single tx hash. Update your transaction history UI to parse and display each sub-operation:

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

// Parse batch operations from transaction receipt
function parseBatchOps(receipt: TransactionReceipt): BatchOperation[] {
    // Decode logs and internal calls from the receipt
    // ...
}

Security Considerations

EIP-7702 introduces new attack surfaces that developers must understand:

Delegation Target Verification

The delegation target contract has full control over the EOA’s assets during the transaction. A malicious delegation target can:

  • Transfer all ETH and tokens from the EOA
  • Approve unlimited token allowances to attacker addresses
  • Interact with DeFi protocols to drain positions

Mitigation: Only delegate to audited, verified contracts. Wallets should maintain an allowlist of trusted delegation targets.

Replay Protection

EIP-7702 authorization lists include a nonce to prevent replay attacks. However, developers must ensure:

  • The authorization nonce matches the EOA’s current nonce
  • Each authorization is used exactly once
  • Cross-chain replay is prevented by including the chain ID

Phishing via Delegation

Attackers may trick users into signing authorization lists that delegate to malicious contracts. This is similar to the existing “approve” phishing problem but potentially more dangerous because delegation grants broader access.

Mitigation: Wallets must clearly display what code the EOA is delegating to, with source verification and risk scoring.

Reentrancy in Batch Execution

Batch executors that use call in a loop are vulnerable to reentrancy if one of the batch targets calls back into the executor. Use reentrancy guards or the checks-effects-interactions pattern:

// Use a reentrancy guard on the batch executor
bool private locked;

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

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

Storage Collisions

When an EOA delegates to a contract, the contract’s code executes in the context of the EOA’s storage. If two different delegation targets use the same storage slots for different purposes, data corruption can occur.

Mitigation: Use EIP-7201 (namespaced storage) in all delegation targets:

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

Frequently Asked Questions

Does EIP-7702 change my wallet address?

No. Your EOA address stays the same. EIP-7702 temporarily gives your address smart contract capabilities for the duration of a single transaction. After the transaction completes, your address returns to being a standard EOA.

Can I use EIP-7702 on L2s?

Yes. All major L2s (Arbitrum, Base, Optimism, zkSync) have adopted EIP-7702 as part of their Pectra-equivalent upgrades. The transaction format and delegation mechanics are identical.

What happens if the delegation target has a bug?

The damage is limited to the single transaction. Unlike a permanent smart contract wallet, EIP-7702 delegation expires after the transaction completes. However, within that transaction, the delegation target has full access to the EOA’s assets — a bug could drain the account.

Is EIP-7702 compatible with hardware wallets?

Yes. Hardware wallets (Ledger, Trezor) can sign type-4 transactions, including the authorization list. Ledger added support in firmware version 2.3.0 (December 2025). The user confirms the delegation target on the hardware device screen.

How much gas does EIP-7702 save?

For a typical approve+swap flow, EIP-7702 saves approximately 40-50% on gas by eliminating the second transaction overhead (21,000 base gas) and enabling more efficient calldata encoding. For complex multi-step DeFi operations (e.g., zap into a vault), savings can reach 60-70%.