EIPs

EIP-7702 — Set EOA account code

eips.ethereum.org/EIPS/eip-7702

A transaction type that lets an EOA temporarily delegate to contract code. The EOA signs an Authorization saying “for this transaction, execute as if I had this contract’s bytecode.” That gives EOAs smart-account features (batching, sponsored gas, custom validation) without becoming smart accounts and without bundler infrastructure.

import {
  wallet_signAuthorization,
  wallet_sendSetCodeTransaction,
  type AuthorizationParameter,
} from "@ethernauta/eip/7702";
import type { Provider } from "@ethernauta/eip/1193";
import { create_provider, encode_chain_id } from "@ethernauta/transport";
import { eip155_1 } from "@ethernauta/chain/eip155-1";
import { AddressSchema, UintSchema } from "@ethernauta/core";
import { parse } from "valibot";

const CHAIN_ID = encode_chain_id({ namespace: "eip155", reference: eip155_1.chainId });
declare const provider: Provider; // see /eips/6963 for discovery
const { signer } = create_provider(provider);

const delegate_contract = parse(AddressSchema, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
const target = parse(AddressSchema, "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC");
const calldata: `0x${string}` = "0x";

// 1. dapp builds the authorization payload
const auth: AuthorizationParameter = {
  chainId: parse(UintSchema, "0x1"),
  address: delegate_contract,
  nonce: parse(UintSchema, "0x0"),
};

// 2. wallet signs (path 2)
const signed_auth = await wallet_signAuthorization(auth)(
  signer({ chain_id: CHAIN_ID }),
);

void signed_auth;

// 3. wallet bundles into a type-4 tx and broadcasts (path 1)
const hash = await wallet_sendSetCodeTransaction({
  to: target,
  data: calldata,
  delegations: [{ chainId: parse(UintSchema, "0x1"), address: delegate_contract }],
})(signer({ chain_id: CHAIN_ID }));

void hash;

Surface

Authorization (the inner signature)

ExportTypePurpose
build_authorization_message(auth) => BytesCompose the message hash input.
hash_authorization(auth) => Hash32Final digest.
sign_authorization(args) => AuthorizationSignedSign with a raw private key.
AuthorizationParameter, AuthorizationParameters, AuthorizationSigned, AuthorizationListtypesWire shapes.
is_delegation_designator(bytecode) => booleanCheck whether code is a 7702 designator.

Set-code transaction (the outer envelope)

ExportTypePurpose
encode_transaction_signed(tx) => BytesRLP encode a signed type-4 tx.
encode_transaction_unsigned(tx) => BytesRLP encode the pre-signing payload.
decode_transaction_signed, decode_transaction_unsigned(bytes) => txThe matching decoders.
sign_set_code_transaction(args) => BytesSign + encode.
Transaction7702Signed, Transaction7702UnsignedtypesWire schemas — symmetric naming with 1559 / 2930 / 4844.
DelegationIntenttype
SendSetCodeTransactionParameterstypeThe wallet RPC param shape.
HexDataSchemaValibot schema

RPC methods

MethodShapePurpose
wallet_signAuthorizationSignable<AuthorizationSigned>Path 2: get back a signed authorization.
wallet_sendSetCodeTransactionSignable<Hash32>Path 1: wallet bundles + broadcasts.

Constants

ExportValue
SET_CODE_MAGIC0x05 — the authorization tuple prefix.
SET_CODE_TX_TYPE0x04 — the transaction type byte.

What a delegation looks like on-chain

After a successful 7702 tx, the EOA’s code field becomes 0xef0100 || <delegate_address>. That’s the delegation designator:

import { is_delegation_designator } from "@ethernauta/eip/7702";
import { eth_getCode } from "@ethernauta/eth";
import { create_reader, encode_chain_id, http } from "@ethernauta/transport";
import { eip155_1 } from "@ethernauta/chain/eip155-1";
import { AddressSchema } from "@ethernauta/core";
import { parse } from "valibot";

const CHAIN_ID = encode_chain_id({ namespace: "eip155", reference: eip155_1.chainId });
const reader = create_reader([
  { chainId: CHAIN_ID, transports: [http("https://ethereum-rpc.publicnode.com")] },
]);

const eoa = parse(AddressSchema, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");

const code = await eth_getCode([eoa, "latest"])(reader({ chain_id: CHAIN_ID }));
const delegated = is_delegation_designator(code);
void delegated;

When delegated, transactions to the EOA execute the delegate’s bytecode. The EOA can clear the delegation by signing another authorization pointing to 0x0...0.

Path 1 vs path 2

Path 1 (wallet-bundled)Path 2 (primitive composition)
Methodwallet_sendSetCodeTransactionwallet_signAuthorization + eth_sendRawTransaction
Dapp ownsnothingthe broadcast
Round trips12
Use casetypicalbridges, MEV-sensitive flows, audit-heavy systems

See Concepts → two paths for the general principle.

See also