Actualites·6 min de lecture·Par Solingo

EIP-7702 — The End of EOA vs Contract Account Distinction

How EIP-7702 lets EOAs temporarily behave like smart contract wallets without migration.

# EIP-7702 — The End of EOA vs Contract Account Distinction

EIP-7702, included in Ethereum's Pectra upgrade, introduces a revolutionary feature: EOAs (Externally Owned Accounts) can temporarily delegate their behavior to smart contracts without converting to contract accounts.

The Problem: Two Account Types

Ethereum has two account types:

EOA (Externally Owned Account)

  • Controlled by private key
  • Can initiate transactions
  • No custom logic
  • Fixed 21,000 gas for transfers

Contract Account

  • Controlled by code
  • Cannot initiate transactions (needs EOA)
  • Custom logic (multisig, social recovery, etc.)
  • Higher gas costs

This dichotomy has plagued UX for years.

What EIP-7702 Changes

EIP-7702 introduces a new transaction type that lets EOAs temporarily set their code to a smart contract's logic for the duration of a transaction.

Before EIP-7702

// User must deploy a separate contract wallet

contract SmartWallet {

address public owner;

function execute(address to, uint256 value, bytes calldata data)

external

{

require(msg.sender == owner, "Unauthorized");

(bool success,) = to.call{value: value}(data);

require(success, "Execution failed");

}

}

// User must migrate funds from EOA → SmartWallet

After EIP-7702

// User's EOA can temporarily use SmartWallet logic

// No migration, no new address, no fund transfer

How It Works

Transaction Structure

{

type: 4, // EIP-7702 transaction type

authorizationList: [

{

chainId: 1,

address: "0x...", // Smart wallet contract

nonce: 0,

v: 27,

r: "0x...",

s: "0x..."

}

],

to: "0x...",

data: "0x...",

// ... standard fields

}

The authorizationList tells the EVM: "For this transaction, execute my EOA using the code at address."

Use Cases

1. Batch Transactions

contract BatchExecutor {

function batchExecute(

address[] calldata targets,

bytes[] calldata datas

) external {

for (uint256 i = 0; i < targets.length; i++) {

(bool success,) = targets[i].call(datas[i]);

require(success, "Batch failed");

}

}

}

EOA delegates to BatchExecutor for one transaction, executes multiple calls, then reverts to normal EOA.

2. Gas Sponsorship

contract GaslessExecutor {

function executeWithPaymaster(

address target,

bytes calldata data,

address paymaster

) external {

require(msg.sender == paymaster, "Unauthorized");

(bool success,) = target.call(data);

require(success, "Execution failed");

}

}

Third parties pay gas for user transactions.

3. Social Recovery

contract RecoverableWallet {

mapping(address => bool) public guardians;

uint256 public requiredGuardians = 2;

function recover(address newOwner, bytes[] calldata signatures)

external

{

require(verifyGuardians(signatures), "Insufficient guardians");

// Transfer control to newOwner

assembly {

sstore(0, newOwner)

}

}

}

Users can recover EOAs without pre-deploying contract wallets.

4. Session Keys

contract SessionKeyWallet {

mapping(address => SessionKey) public sessions;

struct SessionKey {

uint256 expiry;

uint256 spendLimit;

uint256 spent;

}

function executeWithSession(

address sessionKey,

address target,

uint256 value,

bytes calldata data

) external {

SessionKey storage session = sessions[sessionKey];

require(block.timestamp < session.expiry, "Expired");

require(session.spent + value <= session.spendLimit, "Limit");

session.spent += value;

(bool success,) = target.call{value: value}(data);

require(success, "Failed");

}

}

Apps get temporary spending permissions without full wallet access.

EIP-7702 vs EIP-3074 vs EIP-4337

| Feature | EIP-7702 | EIP-3074 | EIP-4337 |

|---------|----------|----------|----------|

| EOA keeps address | ✅ | ✅ | ❌ (new wallet) |

| Temporary delegation | ✅ | ❌ (permanent) | N/A |

| Native protocol change | ✅ | ✅ | ❌ (opt-in) |

| Backwards compatible | ✅ | ⚠️ | ✅ |

EIP-7702 is the safest path forward because delegation is temporary and user-controlled.

Security Considerations

1. Malicious Delegation Target

// Malicious contract

contract DrainWallet {

function execute() external {

// Drains all ETH from delegating EOA

payable(attacker).transfer(address(this).balance);

}

}

Mitigation: Only delegate to audited, trusted contracts. Wallets will maintain whitelists.

2. Nonce Replay

The authorizationList includes a nonce to prevent replay attacks:

authorizationList: [{

nonce: 5, // Must match user's authorization nonce

// ...

}]

3. Chain ID Validation

authorizationList: [{

chainId: 1, // Only valid on mainnet

// ...

}]

Prevents cross-chain replay.

Implementation Example

// Simple batch executor for EIP-7702

contract SimpleExecutor {

function execute(

address[] calldata targets,

uint256[] calldata values,

bytes[] calldata datas

) external payable {

require(targets.length == values.length, "Length mismatch");

require(targets.length == datas.length, "Length mismatch");

for (uint256 i = 0; i < targets.length; i++) {

(bool success,) = targets[i].call{value: values[i]}(datas[i]);

require(success, "Call failed");

}

}

}

Users delegate to this contract for one transaction to batch multiple calls.

Timeline

  • Proposed: 2023
  • Accepted: Pectra upgrade (2024)
  • Mainnet: Expected Q2 2026
  • Wallet Support: MetaMask, Rabby, Frame integrating

Key Takeaways

  • EOAs can temporarily use smart contract logic
  • No address migration required
  • Enables batch txs, gas sponsorship, recovery, session keys
  • Safer than EIP-3074 (temporary vs permanent)
  • Wallets will curate trusted delegation targets
  • The future of Ethereum accounts is programmable
  • EIP-7702 bridges the gap between EOAs and smart contract wallets without forcing users to migrate. It's account abstraction without the abstraction overhead.

    Prêt à mettre en pratique ?

    Applique ces concepts avec des exercices interactifs sur Solingo.

    Commencer gratuitement