EIPs
EIP-7702 — Set EOA account code
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)
| Export | Type | Purpose |
|---|---|---|
build_authorization_message | (auth) => Bytes | Compose the message hash input. |
hash_authorization | (auth) => Hash32 | Final digest. |
sign_authorization | (args) => AuthorizationSigned | Sign with a raw private key. |
AuthorizationParameter, AuthorizationParameters, AuthorizationSigned, AuthorizationList | types | Wire shapes. |
is_delegation_designator | (bytecode) => boolean | Check whether code is a 7702 designator. |
Set-code transaction (the outer envelope)
| Export | Type | Purpose |
|---|---|---|
encode_transaction_signed | (tx) => Bytes | RLP encode a signed type-4 tx. |
encode_transaction_unsigned | (tx) => Bytes | RLP encode the pre-signing payload. |
decode_transaction_signed, decode_transaction_unsigned | (bytes) => tx | The matching decoders. |
sign_set_code_transaction | (args) => Bytes | Sign + encode. |
Transaction7702Signed, Transaction7702Unsigned | types | Wire schemas — symmetric naming with 1559 / 2930 / 4844. |
DelegationIntent | type | |
SendSetCodeTransactionParameters | type | The wallet RPC param shape. |
HexDataSchema | Valibot schema |
RPC methods
| Method | Shape | Purpose |
|---|---|---|
wallet_signAuthorization | Signable<AuthorizationSigned> | Path 2: get back a signed authorization. |
wallet_sendSetCodeTransaction | Signable<Hash32> | Path 1: wallet bundles + broadcasts. |
Constants
| Export | Value |
|---|---|
SET_CODE_MAGIC | 0x05 — the authorization tuple prefix. |
SET_CODE_TX_TYPE | 0x04 — 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) | |
|---|---|---|
| Method | wallet_sendSetCodeTransaction | wallet_signAuthorization + eth_sendRawTransaction |
| Dapp owns | nothing | the broadcast |
| Round trips | 1 | 2 |
| Use case | typical | bridges, MEV-sensitive flows, audit-heavy systems |
See Concepts → two paths for the general principle.
See also
- EIP-5792 — wallet may pick a 7702 strategy under the hood.
- Wallet → authorize-delegation view.