EIPs

EIP-6492 — Signature validation for predeploy contracts

eips.ethereum.org/EIPS/eip-6492

EIP-1271 validates a signature against a deployed contract. EIP-6492 extends that to contracts that aren’t deployed yet — the smart account address is known (via CREATE2), but the code isn’t on-chain.

The signature is wrapped: (factory, factory_calldata, inner_signature) || MAGIC_BYTES. A universal validator contract:

  1. Detects the wrapped form via the trailing magic bytes.
  2. If the address has no code, deploys it using the factory + calldata.
  3. Calls isValidSignature on the now-deployed contract.
import {
  wrap_signature,
  verify_hash,
} from "@ethernauta/eip/6492";
import { create_reader, encode_chain_id, http } from "@ethernauta/transport";
import { eip155_1 } from "@ethernauta/chain/eip155-1";
import { AddressSchema, BytesSchema, Hash32Schema } 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 factory = parse(AddressSchema, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
const factory_calldata = parse(BytesSchema, "0x");
const inner_signature = parse(BytesSchema, "0x");
const counterfactual_account = parse(AddressSchema, "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC");
const digest = parse(Hash32Schema, "0x" + "00".repeat(32));

const wrapped = wrap_signature({
  factory,
  factoryData: factory_calldata,
  signature: inner_signature,
});

const ok = await verify_hash({
  address: counterfactual_account,
  hash: digest,
  signature: wrapped,
})(reader({ chain_id: CHAIN_ID }));

void ok;

Surface

ExportTypePurpose
MAGIC_BYTESBytes320x6492…6492 — sentinel suffix.
VALIDATOR_BYTECODEBytesCompiled universal validator.
wrap_signature(args) => BytesProduce a wrapped signature.
unwrap_signature(bytes) => UnwrappedSignatureReverse wrap_signature.
is_wrapped_signature(bytes) => booleanDetect via magic bytes.
UnwrappedSignaturetype{ factory, factory_calldata, inner_signature }.
verify_hashReadable<boolean>Run the universal validator.

How the universal validator works

The trick is that verify_hash deploys an ephemeral contract (via eth_call with the validator bytecode as to: null) that handles both the deployment and the isValidSignature call in a single state-less execution. No transaction is sent; nothing is persisted. Pure read.

This is what makes counterfactual signatures verifiable from a Readable<T> — no wallet, no gas.

Cross-EIP verification

In practice you rarely call this directly. The universal verifiers in @ethernauta/crypto walk the full hierarchy:

import { verify_message_universal } from "@ethernauta/crypto";
import { create_reader, encode_chain_id, http } from "@ethernauta/transport";
import { eip155_1 } from "@ethernauta/chain/eip155-1";
import { AddressSchema, BytesSchema } 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 address = parse(AddressSchema, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
const message = "Hello";
const signature = parse(BytesSchema, "0x");

// works for: EOA, deployed smart account, counterfactual smart account
const ok = await verify_message_universal({
  address,
  message,
  signature,
})(reader({ chain_id: CHAIN_ID }));

void ok;

See also

  • EIP-1014 — CREATE2 address derivation (the “counterfactual” half).
  • EIP-1271 — deployed contract signatures (the inner case).
  • @ethernauta/crypto — universal verifiers.